Project Reactor: Explained with Examples
I will give you a clear, beginner-friendly explanation of Project Reactor, based on the official documentation. We’ll cover the basics, core types, common operators, and advanced features — all with practical examples.
1. What is Project Reactor?
- Reactor is a JVM reactive programming library based on the Reactive Streams Specification.
- Key features:
- Asynchronous and non-blocking.
- Backpressure support: downstream tells upstream how much data it can handle.
- Functional API: similar to Java Streams, but works with asynchronous data flow.
- The foundation of Spring WebFlux.
2. Core Types
Reactor provides two main Publisher types.
Mono
Represents a stream with 0 or 1 element. Common use cases: HTTP responses, database lookups.
Mono<String> mono = Mono.just("Hello Reactor");
mono.subscribe(System.out::println);
Flux
Represents a stream with 0 to N elements. Common use cases: event streams, message queues.
Flux<Integer> flux = Flux.range(1, 5);
flux.subscribe(System.out::println);
Subscription Model
Data only flows after you call subscribe().
Flux.range(1, 3)
.map(i -> i * 2)
.subscribe(System.out::println); // Output: 2, 4, 6
3. Operators
Reactor comes with many operators, like SQL + Java Stream combined.
Transforming
map: one-to-one transformationflatMap: flatten async streams
Flux.just("a", "b")
.flatMap(s -> Mono.just(s.toUpperCase()))
.subscribe(System.out::println);
Filtering
filter: keep matching elementstake: take first N elementsskip: skip first N elements
Combining
merge: merge multiple streams (concurrent)concat: concatenate streams in orderzip: pair elements
Flux.zip(Flux.just(1, 2), Flux.just("A", "B"))
.subscribe(System.out::println);
// Output: (1,A) (2,B)
Error Handling
onErrorReturn: fallback valueonErrorResume: fallback streamretry: retry operation
4. Advanced Features
Backpressure
- A core Reactive Streams concept: downstream controls demand.
FluxandMonohandle this automatically, preventing overload.
Schedulers
By default, Reactor runs in the current thread.
Use publishOn or subscribeOn to switch thread pools.
Flux.range(1, 10)
.publishOn(Schedulers.boundedElastic())
.map(i -> i * 2)
.subscribe(System.out::println);
Common schedulers:
immediate(): current threadsingle(): single-threadedboundedElastic(): elastic thread pool (good for blocking tasks)parallel(): parallel thread pool (CPU-intensive tasks)
Cold vs Hot Publishers
- Cold publisher: each subscriber gets a fresh stream (e.g.,
Flux.range). - Hot publisher: data is emitted regardless of subscribers (e.g.,
ConnectableFlux).
5. Summary
- Mono: async single value.
- Flux: async stream of many values.
- Operators: SQL/Stream-like tools for data flow.
- Backpressure & Schedulers: handle performance and resource management.
- Reactor is the foundation of Spring WebFlux and modern Java reactive programming.
Related Resources
- Project Reactor Reference Guide
- Reactive Streams Specification
- Spring WebFlux Documentation
- Spring WebClient Guide
- Related post: Reactive Spring: Reactive Web Explained
- Related post: Spring MVC vs WebFlux: A Practical Look at Concurrency and Performance
- Related post: Building a High-Concurrency AI Moderation Service with Spring WebFlux — From Concept to Production
- Related post: Monitoring Spring WebFlux with Prometheus and Grafana