Just going through the CompletableFuture
documentation and stumbled upon the completeExceptionally
and obtrudeException
methods and is having a hard time comprehending the difference and use case. Can the community help understand the difference and the use case with an example?
The difference is subtle but important. From the official documentation:
If not already completed, causes invocations of
get()
and related methods to throw the given exception.
Forcibly causes subsequent invocations of method
get()
and related methods to throw the given exception, whether or not already completed. [...]
So they differ in their behavior regarding CompletableFuture
s that are already completed.
Basically, a future can either be completed or still pending (not completed). When you call completeExceptionally
or obtrudeException
, the behavior differs depending on the state of the future at that point in time.
Consider this example where the future is already completed at the moment of calling the method:
CompletableFuture<String> future = CompletableFuture.completedFuture("hello world");
future.completeExceptionally(new RuntimeException("Oh noes!"));
System.out.println(future.get()); // Prints "hello world" just fine
versus
CompletableFuture<String> future = CompletableFuture.completedFuture("hello world");
future.obtrudeException(new RuntimeException("Oh noes!"));
System.out.println(future.get()); // Throws the exception
And in case the future is not completed yet, they will both throw an exception:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
return "hello world";
});
future.completeExceptionally(new RuntimeException("Oh noes!"));
System.out.println(future.get());
and
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
}
return "hello world";
});
future.obtrudeException(new RuntimeException("Oh noes!"));
System.out.println(future.get());
complete
and obtrudeValue
Likewise there are also the methods complete
and obtrudeValue
which behave in the same way, but instead of throwing an exception, you can supply a value instead.
So complete
basically completes the future with the given value, in case the future is not done yet, otherwise it does not do anything.
While obtrudeValue
will supply the given value regardless, so it resets or cancels whatever the future already computed and replaces it by the given value instead.