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?


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

Flux.just("a", "b")
    .flatMap(s -> Mono.just(s.toUpperCase()))
    .subscribe(System.out::println);

Filtering

Combining

Flux.zip(Flux.just(1, 2), Flux.just("A", "B"))
    .subscribe(System.out::println); 
// Output: (1,A) (2,B)

Error Handling


4. Advanced Features

Backpressure

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:

Cold vs Hot Publishers


5. Summary