Lesson 38 / 38
Reactive Programming Intro
See the problem reactive streams solve — blocking threads under load — and read a minimal non-blocking WebFlux endpoint built on Mono and Flux.
The problem: one thread per request
A traditional (servlet) request handler blocks its thread while waiting on a slow downstream call — under heavy load you run out of threads even though the CPU is idle, just waiting on I/O. Reactive programming (Reactive Streams / Project Reactor) instead registers a callback and frees the thread to serve other work while waiting.
Mono and Flux
Mono<T> represents zero-or-one async value, Flux<T> zero-to-many — both are lazy: nothing runs until something subscribes. Spring WebFlux controllers return them directly instead of blocking for the result.
@RestController
class UserController {
private final WebClient client;
@GetMapping("/users/{id}")
Mono<User> get(@PathVariable String id) {
return client.get()
.uri("/legacy-users/{id}", id)
.retrieve()
.bodyToMono(User.class); // non-blocking
}
}When it's (not) worth it
Reactive shines for high-concurrency I/O-bound services (gateways, streaming, fan-out to many backends). For typical CRUD apps under modest load, plain blocking code on virtual threads (Java 21+) gives similar scalability with far simpler, easier-to-debug code — reach for reactive only when you've measured a real need.