The following code snippet, which invokes thenCombine, does not set an exception at whenComplete (it prints No exception
):
CompletableFuture.completedFuture(true)
.thenCombine(CompletableFuture.completedFuture(true),
(x,y) -> {
return CompletableFuture.failedStage(new RuntimeException());
})
.whenComplete( (myVal, myEx) -> {
if (myEx == null) {
System.out.println("No exception");
} else {
System.out.println("There was an exception");
}
});
However, the similar code below, which invokes thenCompose, does set an exception:
CompletableFuture.completedFuture(true)
.thenCompose(
x -> {
return CompletableFuture.failedStage(new RuntimeException());
})
.whenComplete( (myVal, myEx) -> {
if (myEx == null) {
System.out.println("No exception");
} else {
System.out.println("There was an exception");
}
});
Why is thenCombine
returning a normally-completed CompletionStage
when its BiFunction is actually returning a failed stage?
In your first example CompletableFuture.failedStage(new RuntimeException())
is the result. The CompletableFuture
returned by thenCombine
is completed with CompletableFuture.failedStage(new RuntimeException())
.
It gets clearer when you don't chain the calls:
CompletableFuture<Boolean> first = CompletableFuture.completedFuture(true);
CompletableFuture<Boolean> second = CompletableFuture.completedFuture(true);
CompletableFuture<CompletionStage<?>> yourQuestion =
first.thenCombine(second, (x, y) ->
CompletableFuture.failedStage(new RuntimeException()));
For your second example you need to read the documentation of thenCompose
carefully:
Returns a new CompletionStage that is completed with the same value as the CompletionStage returned by the given function.
In the function for thenCompose
you return a failed CompletableFuture
and its result is used as the result for the CompletableFuture
returned by thenCompose
: a RuntimeException
.