BackendBench
Coffee

Unravel › Java concepts › APIs and web

Spring

Reactive programming (Reactor Mono and Flux)

Reactive code describes a pipeline for data that arrives over time.

Learn these first

At a glance

Mental model

A plumbing diagram drawn before any water flows.

What happens, in order
  1. 1Return types Mono<T> and Flux<T> replace T and List<T>A WebFlux controller returns them and the framework subscribes for you; you almost never call subscribe() in server code.
  2. 2Operators build the pipeline: map transforms an item, flatMap turns each item into another async call, filter, zip combines results, switchIfEmpty supplies a default, onErrorResume recovers
  3. 3WebFlux runs on a small, fixed set of event-loop threadsAny blocking call (JDBC, Thread.sleep, a blocking HTTP client) on them stalls many requests at once.
  4. 4subscribeOn and publishOn choose which scheduler runs the work; Schedulers.boundedElastic() is the safe place for unavoidable blocking calls
Remember
Watch out
Ignoring a returned Mono or Flux so nothing executesCalling block() on an event-loop threadUsing blocking JDBC or file I/O in a reactive chainUsing ThreadLocal data (MDC, security context) and losing it across threads
Example (highlighted lines explain it)
public Mono<OrderView> view(String id) {    return orders.findById(id)        .switchIfEmpty(Mono.error(new OrderNotFoundException(id)))        .flatMap(order -> customers.findById(order.customerId())            .map(customer -> new OrderView(order, customer)))        .onErrorResume(TimeoutException.class, e -> Mono.empty());}
  1. line 1 uses Mono, the core of Reactive programming (Reactor Mono and Flux)
  2. line 3 uses switchIfEmpty, the core of Reactive programming (Reactor Mono and Flux)
  3. line 6 uses onErrorResume, the core of Reactive programming (Reactor Mono and Flux)
Read the full explanation (about 2 min)

Reactive code describes a pipeline for data that arrives over time. A Mono is zero or one future value, a Flux is zero to many, and nothing happens until someone subscribes.

A mental model

A plumbing diagram drawn before any water flows. Building the pipes (map, filter, flatMap) does nothing; water only runs when someone opens the tap (subscribe), and the tap can say "slow down" (backpressure).

How it works

Return types Mono<T> and Flux<T> replace T and List<T>. A WebFlux controller returns them and the framework subscribes for you; you almost never call subscribe() in server code.

Operators build the pipeline: map transforms an item, flatMap turns each item into another async call, filter, zip combines results, switchIfEmpty supplies a default, onErrorResume recovers.

WebFlux runs on a small, fixed set of event-loop threads. Any blocking call (JDBC, Thread.sleep, a blocking HTTP client) on them stalls many requests at once.

subscribeOn and publishOn choose which scheduler runs the work; Schedulers.boundedElastic() is the safe place for unavoidable blocking calls.

Going deeper

Nothing runs without a subscription. A repository.save(x); whose Mono result is ignored silently does not save anything. This is the most common reactive bug.

Exceptions are signals inside the pipeline, not thrown to the caller. Handle them with onErrorResume, onErrorReturn or retryWhen, and never block() inside a pipeline.

Reactive pays off with high concurrency and lots of waiting on I/O. For ordinary CRUD with blocking drivers, a plain MVC application (or virtual threads) is simpler and just as fast.

Under the hood

Reactor implements the Reactive Streams contract: a Subscriber calls request(n) to ask for n items and the Publisher may not send more (backpressure). Each operator wraps the upstream publisher; subscribing walks the chain backwards and starts the source. Context propagates through contextWrite rather than thread-locals.

Common mistakes

  • Ignoring a returned Mono or Flux so nothing executes.
  • Calling block() on an event-loop thread.
  • Using blocking JDBC or file I/O in a reactive chain.
  • Using ThreadLocal data (MDC, security context) and losing it across threads.

How Unravel recognises it

When you paste code, Unravel looks for these signs of reactive programming (reactor mono and flux). Spotting them yourself is a good habit when you read unfamiliar code:

Part of a learning path

Related concepts

Builds on this

Frequently asked questions

What is Reactive programming (Reactor Mono and Flux)?

Reactive code describes a pipeline for data that arrives over time. A Mono is zero or one future value, a Flux is zero to many, and nothing happens until someone subscribes.

What are the most common mistakes with Reactive programming (Reactor Mono and Flux)?

Ignoring a returned Mono or Flux so nothing executes. Calling block() on an event-loop thread. Using blocking JDBC or file I/O in a reactive chain. Using ThreadLocal data (MDC, security context) and losing it across threads.

How can I see Reactive programming (Reactor Mono and Flux) in real code?

Paste your own Java into Unravel and it will point out where reactive programming (reactor mono and flux) appears, explain how it works at the detail level you choose, and draw the flow of the code around it.