CompletableFuture and async composition question 96 of 180 mid
How do exceptions propagate through a chain, and what do exceptionally, handle and whenComplete do?
- They all behave identically
- Correct: A failure skips every dependent stage until one that can handle it:
exceptionallyrecovers a value,handlesees both outcomes and maps them,whenCompleteobserves without changing the result - Exceptions are thrown on the calling thread immediately
- Only
get()can observe a failure
A stage that throws completes exceptionally, and every downstream thenApply is skipped, carrying the
failure along wrapped in a CompletionException.
exceptionally(fn)runs only on failure and substitutes a fallback value.handle((value, error) -> ...)runs either way and produces a new value, so it can convert a failure into a result or the reverse.whenComplete((value, error) -> ...)runs either way for a side effect and leaves the result alone, which makes it the right place for logging and cleanup.
The wrapping catches people out: get() throws ExecutionException, join() throws
CompletionException, and the cause is your original exception in both cases. And a chain nobody ever
joins, gets or handles swallows its failure completely.
Quiz yourself on CompletableFuture and async composition Suggest a correction