Issue
I just realised that exception inside of whenComplete, in completable future is not being logged/throwed. Can someone explain that? How to properly use whenComplete?
public static void main(String[] args) {
var c = CompletableFuture.runAsync(() -> {
System.out.println("done");
});
c.whenComplete((unused, throwable) -> {
System.out.println((5/0));
throw new RuntimeException("I am throwing an exception");
});
System.out.println("ok");
}
output of this block of code
done
ok
Solution
From the docs (emphasis mine)
public CompletableFuture<T> whenComplete(BiConsumer<? super T,? super Throwable> action)
Description copied from interface:
CompletionStage
Returns a new
CompletionStage
with the same result or exception as this stage, that executes the given action when this stage completes.When this stage is complete, the given action is invoked with the result (or
null
if none) and the exception (ornull
if none) of this stage as arguments. The returned stage is completed when the action returns. If the supplied action itself encounters an exception, then the returned stage exceptionally completes with this exception unless this stage also completed exceptionally.
whenComplete
returns a new CompletableFuture
. CompletableFuture
keeps track of what exception (if any) has occurred and expects you to deal with it. By ignoring the return value, you're suppressing the exception.
To wait on the result of the future, or throw if it throws, use join
.
c.whenComplete((unused, throwable) -> {
System.out.println((5/0));
throw new RuntimeException("I am throwing an exception");
}).join();
Answered By - Silvio Mayolo
Answer Checked By - Marilyn (JavaFixing Volunteer)