top of page

What is Reactive Programming? - Building "ReactiveUserService" (A reactive service managing users)


💡 Reactive Programming is:

Asynchronous, non-blocking, event-driven programming with backpressure support, ideal for handling streaming data and concurrent workloads efficiently.

1. Asynchronous

Meaning:In asynchronous programming, tasks are not executed one after another. Instead, a task can start, and while it's waiting (e.g., for data from a server), the program continues doing other work.

Example:Imagine you're cooking dinner and the oven takes 30 minutes to heat. While waiting, you chop vegetables or wash dishes—you don’t just stand there. That's asynchronous behavior.

In code:Instead of waiting for a file to be read before continuing, your program starts the read and moves on to the next instruction, handling the result later when it's ready.


2. Non-blocking

Meaning:Non-blocking means a function does not stop the program's execution to wait for a result. It allows the system to stay responsive by not getting "stuck" on slow operations.

Example:Calling a friend and leaving a voicemail instead of waiting on the line indefinitely. You're not blocked—you go on with your day.

In code:If one function is fetching data from the internet, it doesn’t prevent other functions from running while waiting for the data.


3. Event-driven

Meaning:This style is centered around responding to events—like user clicks, messages from servers, or sensor input. You define what should happen when a specific event occurs.

Example:In a smart home system, if motion is detected (an event), then the lights turn on (a response).

In code:You register a "listener" or a "callback" for an event, and when the event happens, the corresponding function is executed.


4. Backpressure Support

Meaning:Backpressure is a mechanism to handle overload—when a system receives more data/events than it can process. It slows down or buffers data to avoid crashing or memory overuse.

Example:Imagine you're drinking from a faucet, but water comes out too fast. You can ask someone to turn down the flow. That’s backpressure: controlling the rate of input.

In code:A data stream can notify its source to pause or reduce the data rate so the consumer has time to catch up.


✅ Summary of Reactive Programming:

It’s a way to build responsive systems that can handle lots of events or data streams without freezing up, thanks to being asynchronous, non-blocking, event-driven, and smart about flow control (backpressure).


🔄 In Reactive Systems: These are core principles of Reactive Systems, which apply Reactive Programming to building robust applications.


🔄 1. “Data is pushed from the source to the subscriber”

What it means:

  • In reactive systems, the data producer (source) pushes data to the consumer (subscriber) as it becomes available.

  • The subscriber doesn’t keep asking (polling) for data—it just waits, and the system sends it new data automatically.

Example:

  • Think of YouTube subscriptions: You don’t ask every minute if there's a new video; YouTube pushes a notification when a new one is published.

In code: sourceObservable.subscribe((data) => {

console.log("Got new data:", data);

}); Here, data is pushed when available, not requested manually. 🔁 2. “Consumers react to new data”

What it means:

  • Consumers (like UI components, services, etc.) don’t control the flow—they simply react whenever data arrives.

  • This leads to automatic, responsive behavior.

Example:

  • Your email inbox updates when new mail arrives. It doesn’t ask for updates—it just reacts to the new email being delivered.

In code: observable.subscribe((message) => {

showNotification(message);

}); Whenever message arrives, showNotification() is triggered. 🌊 3. “Supports streaming, parallelism, and resilience”

Let’s break that into parts:

📺 a) Streaming

  • Data flows continuously like a stream, not in chunks or batches.

  • Useful for real-time systems like chat apps, stock tickers, or sensor networks.

Example: Think Netflix streaming—you're watching content as it downloads, not after the whole file is ready. 🧠 b) Parallelism

  • Reactive systems can process data in parallel, taking advantage of multi-core systems.

  • Different streams or parts of a stream can be handled by different threads or services.

Benefit: Increases throughput and performance.

Example: A video processing system can process video frames in parallel as they stream in.

🛡️ c) Resilience

  • Reactive systems are fault-tolerant. If part of the system fails (e.g., a service crashes), it can recover gracefully.

  • Using mechanisms like timeouts, retries, fallbacks, or circuit breakers.

Example: If a microservice crashes, the system might retry the request, send a cached response, or route to a backup server. ✅ Summary:

A reactive system pushes data to subscribers, which then react automatically. It’s built for continuous data streams, can scale across cores or machines, and is designed to recover from failures gracefully.

📊 Traditional vs Reactive Comparison

Feature

Traditional Java (Imperative)

Reactive Java (Declarative)

Execution

Step-by-step, blocking

Asynchronous, non-blocking

Thread usage

One thread per request

Fewer threads, event loop based

Data flow

Pull (request → result)

Push (data → event)

Error handling

try-catch

onErrorResume / retry

Example

List<T>

Flux<T> or Mono<T>

Libraries

JDBC, RestTemplate

R2DBC, WebClient, Project Reactor

 PART 2: Core Concepts: Mono<T> vs Flux<T>

Type

Meaning

When to Use

Mono<T>

0 or 1 result

For a single item or empty (like fetching a user by ID)

Flux<T>

0 to many results

For stream or list (like getting all users)

Both are part of Project Reactor – the backbone of Spring WebFlux.  Let's take a deep dive into the core concepts of Mono<T> and Flux<T> in the context of Project Reactor, which is the reactive foundation of Spring WebFlux. 🔧 What is Project Reactor?

Project Reactor is a fully non-blocking Reactive Programming library for the JVM, developed by Pivotal/VMware, and it's the backbone of Spring WebFlux (the reactive alternative to Spring MVC).

It implements the Reactive Streams Specification, meaning it:

  • Supports asynchronous data processing

  • Handles backpressure

  • Works with data streams


🧱 Key Building Blocks in Reactor:

  • Mono<T> → 0 or 1 item

  • Flux<T> → 0 to N items (possibly infinite)




    🟦 Mono<T>: Think “Maybe one”

    🔍 Definition:

Mono<T> is a Publisher that emits 0 or 1 item and then completes (or fails).

Use Mono<T> when:

  • You expect a single value (or none), such as:

    • A user record from a database

    • An HTTP response body

    • A calculation result


✅ Example: Mono<String> nameMono = Mono.just("Alice");

nameMono.subscribe(name -> System.out.println("Hello, " + name));


💥 Error case: Mono.error(new RuntimeException("Something went wrong"))

.subscribe(

val -> System.out.println(val),

err -> System.err.println("Error: " + err.getMessage())

);


🟩 Flux<T>: Think “A stream of many”

🔍 Definition:

Flux<T> is a Publisher that emits 0 to many items, possibly infinite, and then completes (or fails).

Use Flux<T> when:

  • You expect multiple items, such as:

    • A list of products from a DB

    • Live events from a WebSocket

    • A stream of sensor readings


✅ Example:

Flux<Integer> numbers = Flux.just(1, 2, 3, 4, 5);

numbers.subscribe(num -> System.out.println("Got number: " + num)); ♾️ Infinite Flux (with interval): Flux.interval(Duration.ofSeconds(1))

.subscribe(n -> System.out.println("Tick: " + n)); 🔄 Mono vs Flux: Side-by-side

Feature

Mono<T>

Flux<T>

Emits

0 or 1 value

0 to many values

Completion

Completes after emitting or no item

Completes after all items or infinite

Use case

Single item APIs (e.g., GET /user)

Streams, collections, updates

Example

DB query for one user

Stream of chat messages

🔗 How They Power Spring WebFlux

Spring WebFlux is Spring’s non-blocking, reactive web framework built on top of Project Reactor. It uses Mono and Flux as return types in controller methods.


Example: Mono in WebFlux Controller

@GetMapping("/user/{id}")

public Mono<User> getUser(@PathVariable String id) {

return userService.findUserById(id); // returns Mono<User>

}


Example: Flux in WebFlux Controller @GetMapping("/users")

public Flux<User> getAllUsers() {

return userService.getAllUsers(); // returns Flux<User>

}


🧠 Advanced Concepts (Just a Peek)

  • Backpressure: Both Mono and Flux support it (in Flux, it's more relevant).

  • Operators: You can chain transformations (map, flatMap, filter) just like Java Streams.

  • Schedulers: Control execution context (publishOn, subscribeOn) to shift threads.


✅ Summary:

Concept

Mono

Flux

Purpose

Handle a single result (or none)

Handle multiple results (or stream of data)

Project

Part of Project Reactor (Spring WebFlux)

Part of Project Reactor (Spring WebFlux)

Use Cases

DB fetch by ID, API response

Streaming data, paginated results

Non-blocking?

✅ Yes

✅ Yes

Reactive Streams

✅ Yes (supports backpressure)

✅ Yes (supports backpressure)

Let's walk through a hands-on Spring Boot application (ReactiveUserService) in the live session that uses Project Reactor (Mono and Flux) in a REST API built with Spring WebFlux. 📦 What We'll Build

A simple reactive REST API for managing Users:

Endpoint

Return Type

Description

GET /users

Flux<User>

Return all users

GET /users/{id}

Mono<User>

Return a user by ID

🧪 Step 5: Test the API 🧪 Try with curl or Postman:

Get All Users: curl http://localhost:8080/users Get One User: curl http://localhost:8080/users/1

Recent Posts

See All

Comments


bottom of page