The CompletableFuture
API allows us to use thenCompose
to chain another future:
CompletableFuture<String> future1 = submit("foo");
CompletableFuture<String> future2 = future.thenCompose((result) -> submit(result));
This only works for successful responses though. Is there a way to do the same but also including exception handling?
For example:
CompletableFuture<String> future1 = submit("foo");
CompletableFuture<String> future2 = future.handleCompose((result, error) -> {
if (error != null)
return submit("failure"); // Handle error by doing a different action with the same result (like a fallback)
else
return submit(result);
});
I know you can do something like whenComplete
:
CompletableFuture<String> future2 = new CompletableFuture<>();
CompletableFuture<String> future1 = submit("foo");
future.whenComplete((result, error) -> {
CompletableFuture<String> tmp;
if (error != null)
tmp = submit("failure");
else
tmp = submit(result);
tmp.whenComplete((result2, error2) -> {
if (error2 != null) future2.completeExceptionally(error2);
else future2.complete(result2);
});
});
This however loses the ability to cancel properly and seems like a very "hacky" solution compared to the success composition handling. Is there a good way that does not require making my own extension of the CompletableFuture class?
The problem is that I need to return a single future from my method and it should be capable to cancel the entire process at any point in time.
You can combine an handle()
returning a CompletableFuture
with a thenCompose(x -> x)
:
CompletableFuture<String> future2 = future.handle((result, error) -> {
if (error != null)
return submit("failure"); // Handle error by doing a different action with the same result (like a fallback)
else
return submit(result);
})
.thenCompose(x -> x);
Unfortunately, there is no way to avoid that last thenCompose()
. See also How to avoid invoking CompletableFuture.thenCompose(x -> x)
? and my comment on it.
Edit: for Java 12+ there is now exceptionallyCompose()
, which I described as an answer on this question’s duplicate target.