CompletableFuture Chains: thenApply, thenCompose, exceptionally
Fast recall
Quick revision
Core answer
Ability to build non-blocking async pipelines in Java and handle errors cleanly without nesting callbacks.
Using thenApply when the mapping function itself returns a CompletableFuture — this produces CompletableFuture<CompletableFuture<T>> instead of flattening. Use thenCompose (flatMap) instead.
Discuss thenApplyAsync vs thenApply (which thread executes the callback), handle() vs exceptionally (both error and result in one stage), and whenComplete for side effects.
Interview-ready guide
Interview answer
CompletableFuture's composition API covers four main scenarios: transforming a result, chaining async operations, combining two independent futures, and handling errors. Each scenario has a dedicated method — choosing the wrong one silently wraps results in extra layers or blocks unexpectedly.
thenApply vs thenCompose:
thenApply(fn): function returns a plain value — wraps it in a new CompletableFuture automaticallythenCompose(fn): function returns aCompletableFuture— flattens it; avoidsCompletableFuture> - Use
thenComposewhenever the next step is itself asynchronous
thenCombine:
- Merges two independent futures running in parallel
- Combining function receives both results when both complete — does not introduce sequencing
Error handling:
exceptionally(fn): recover with a default value when an exception occurshandle(fn): receives both result and exception — handles both success and failure pathswhenComplete(fn): side effects like logging — does not transform the value
Thread assignment:
- Without Async suffix: runs on the completing thread — could be any thread, unpredictable
- Use
thenApplyAsync(fn, executor)for predictable thread assignment; always pass a custom executor for I/O stages
I recommend structuring pipelines as: supplyAsync → thenCompose for dependent calls → thenCombine for parallel fetching → exceptionally at the end for recovery.
CompletableFuture Chains: thenApply, thenCompose, exceptionally
Direct Answer
thenApply transforms the result (map); thenCompose chains a function that returns another CompletableFuture (flatMap); exceptionally handles errors and provides a fallback value. Together they form a composable async pipeline without blocking threads.
Deep Dive & Architecture
CompletableFuture provides three recovery/observation hooks. exceptionally(Function<Throwable, T>) — runs only on failure; returns a replacement value of type T; the cleanest "fallback on error" API. handle(BiFunction<T, Throwable, U>) — runs on both success and failure; sees both value and throwable (one is null); can transform type T → U and swallow the exception. whenComplete(BiConsumer<T, Throwable>) — runs on both but is observe-only: can't change the result, exception propagates downstream unchanged.
Key rule: every CompletableFuture chain should terminate in exceptionally, handle, or have someone call .get()/.join() on it.
thenApply transforms the result (map); thenCompose chains a function that returns another CompletableFuture (flatMap); exceptionally handles errors and provides a fallback value. Together they form a composable async pipeline without blocking threads.
A common mistake is calling .get() on a CompletableFuture and missing the whole point. Not knowing that *Async variants run on commonPool and shouldn't be used for blocking work without a custom executor
Common Mistakes & Pitfalls
Using thenApply when the mapping function itself returns a CompletableFuture — this produces CompletableFuture<CompletableFuture<T>> instead of flattening. Use thenCompose (flatMap) instead.
Check your understanding
Answer these without looking back at the article.
- What is `CompletableFuture` in Java? Why was it added when `Future` already existed?
- What is the difference between Future and CompletableFuture in Java?
- What's the difference between `thenCompose` and `thenCombine` in `CompletableFuture`?
Related interview prep categories
2Looking for a structured roadmap?
Every module on this page is also part of the full Java backend interview track.