liveBook · Manning

Flatmap

As explained in Spring in Action, Sixth Edition

flatMap is a Project Reactor operator that maps each source element to a publisher and merges the resulting publishers into one sequence.

`flatMap()` transforms an item by passing it to a function that returns a `Mono` or `Flux`. It then flattens that publisher’s results into the resulting reactive sequence. Use it when the transformation itself produces a publisher, such as a reactive repository save. section 11.3.3 section 12.1.2

The difference from `map()` matters: `map()` transforms each item directly and synchronously. If a mapping function returns a `Mono<TacoOrder>`, using `map()` on a `Mono` would leave a `Mono<Mono<TacoOrder>>`. Using `flatMap()` leaves a `Mono<TacoOrder>` that the next operation can use. section 11.3.3 section 13.1.4

@Test
public void flatMap() {
  Flux<Player> playerFlux = Flux
    .just("Michael Jordan", "Scottie Pippen", "Steve Kerr")
    .flatMap(n -> Mono.just(n)
        .map(p -> {
            String[] split = p.split("\\s");
            return new Player(split[0], split[1]);
          })
        .subscribeOn(Schedulers.parallel())
      );
  
  List<Player> playerList = Arrays.asList(
      new Player("Michael", "Jordan"), 
      new Player("Scottie", "Pippen"), 
      new Player("Steve", "Kerr"));
 
  StepVerifier.create(playerFlux)
      .expectNextMatches(p -> playerList.contains(p))
      .expectNextMatches(p -> playerList.contains(p))
      .expectNextMatches(p -> playerList.contains(p))
      .verifyComplete();
}

Follow each player name into its own `Mono`: `map()` creates the `Player`, `subscribeOn(Schedulers.parallel())` schedules the subscription, and `flatMap()` combines the results. The test checks membership rather than a fixed emission order. section 11.3.3

`flatMap()` does not itself schedule work on another thread. Paired with `subscribeOn()`, it allows the publishers created for individual items to perform transformations asynchronously. The same pattern can process buffered groups of fruit on parallel workers. section 11.3.3

Save a taco from a reactive request body

A WebFlux controller can accept `Mono<Taco>` and return `tacoMono.flatMap(tacoRepo::save)`. When the taco arrives, the repository’s reactive `save()` supplies a new `Mono<Taco>`; `flatMap()` keeps the controller’s result a `Mono<Taco>`. section 12.1.2

Continue after a WebClient response

A WebClient response flow can return `Mono.empty()` when an `X_UNAVAILABLE` header is true, or continue with the response. A following `flatMap(cr -> cr.bodyToMono(Ingredient.class))` extracts the ingredient while keeping the result a `Mono<Ingredient>`. section 12.4.5

Repository workflows use the same idea across several steps. Saving an order first saves its tacos, adds their assigned IDs to the order, and continues with a `Mono<TacoOrder>` rather than nesting publishers. Reading an order can likewise use `flatMap()` to fetch and attach its tacos. section 13.1.4

How Spring in Action, Sixth Edition covers it

How deep it goes
Explains flattening through tests and application code, contrasts `map()`, and shows scheduling with `subscribeOn()` without developing operator internals.
Examples
Demonstrates player conversion, parallel fruit batches, taco POST handling, conditional ingredient responses, and order persistence.
What it assumes
Introduces `flatMap()` after `Flux`, `Mono`, and `map()` examples; uses Java lambdas and chained reactive calls.
What you can do after
Apply it via Project Reactor to flatten publisher-producing transformations and chain reactive saves without nested Monos.
How it connects
Connects `flatMap()` to `map()`, `Mono`, `Flux`, `subscribeOn()`, `Schedulers`, WebFlux, WebClient, and reactive repositories.

Also explained in

Compare how 5 books explain flatmap →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Spring in Action, Sixth Edition. The section links point to the parts of the book it draws on.