Let's suppose I have a CompletableFuture with a couple of stages chained:
processedFuture = someCompletableFuture
.thenApply(<stage1>)
.thenApply(<stage2>)
And let's assume that in case an error happens in <stage1>
we would like to abort the execution of <stage2>
and return SOME_DEFAULT_VALUE
. Given the following options:
// Option A
val mayFailFuture = someCompletableFuture
.thenApply(<stage1>);
if (mayFailFuture.isCompletedExceptionally()) {
log.error(...);
return SOME_DEFAULT_VALUE;
}
processedFuture = mayFailFuture.thenApply(<stage2>)
// Option B
processedFuture = someCompletableFuture
.thenApply(<stage1>) // returns CompletableFuture<T>
.exceptionally(<exceptionally1>) // must return CompletableFuture<T>
.thenApply(<stage2>)
Is Option A the correct way to abort a chained execution of stages?
In Option B is there any way to abort the execution and return SOME_DEFAULT_VALUE
?
To return your default value when stage1 completes exceptionally, you could consider using handle(BiConsumer)
:
processedFuture = someCompletableFuture
.thenApply(<stage1>)
.handle((s1Result, s1Exception) -> {
if(s1Exception!=null) return SOME_DEFAULT_VALUE; //Exception was thrown in S1
else return stage2.apply(s1Result); //apply stage2 otherwise
})
Edit:
Michael already posted a better solution in comments, which is to apply exceptionally
at the end:
processedFuture = someCompletableFuture
.thenApply(<stage1>)
.thenApply(<stage2>)
.exceptionally(e -> SOME_DEFAULT_VALUE);
Just bear in mind that stage2 never executes if stage1 throws an Exception, in which case that same Exception is propagated to exceptionally
.
Edit 2:
As per comment, if you wish to return different default values depending on which stage failed, this should do the trick:
processedFuture = someCompletableFuture
.thenApply(<stage1>)
.handle((s1Result, s1Exception) -> {
if(s1Exception!=null) return DEFAULT_VALUE_1; //Exception was thrown in S1
else return stage2.apply(s1Result); //apply stage2 otherwise
})
.exceptionally(e -> DEFAULT_VALUE_2); //treat exceptional return from stage2