Skip to main content
๐Ÿ“œ WAYPOINT LESSON

CompletableFuture Composition

โญโญ intermediateโณ 15 min read๐Ÿ“ Lesson 98 of 180

Stage chains, thenCompose vs thenCombine, allOf, and the exception-skips-forward rule.

CompletableFuture: composing async work

A Future only waits. A CompletableFuture composes:

CompletableFuture<Integer> price =
    CompletableFuture.supplyAsync(() -> fetchPrice("USD"))
        .thenApply(p -> p * 100)               // transform
        .thenCombine(otherFuture, Integer::sum) // join two pipelines
        .exceptionally(ex -> -1);               // fallback value

Mental model: a chain of stages; each runs when its inputs complete.

  • supplyAsync โ€” start from a value produced on another thread
  • thenApply โ€” map the value
  • thenCompose โ€” chain a dependent async call (flatMap)
  • thenCombine โ€” merge two independent chains
  • allOf / anyOf โ€” wait for many / first
  • exceptionally / handle โ€” recover or transform failures

Golden rule: an exception skips forward to the nearest recovery stage โ€” one exceptionally at the end of a chain covers every step above it. Default executor is the common ForkJoinPool; pass your own executor when task isolation matters.