DEV Community

Niteshnitian
Niteshnitian

Posted on

A Step-by-Step Guide to Reactive Programming in Spring Boot

Reactive programming is becoming increasingly popular due to its ability to handle high-throughput applications efficiently. Spring Boot provides excellent support for reactive programming through Spring WebFlux, allowing developers to build non-blocking, event-driven applications.

In this blog, we will explore Reactive Programming step by step using Spring Boot with practical examples.


1. What is Reactive Programming?

Reactive programming is an asynchronous programming paradigm that deals with data streams and event-driven architecture. It helps in building high-performance, scalable, and resilient applications by using non-blocking operations.

Key Concepts of Reactive Programming

  1. Reactive Streams: A specification for processing asynchronous data with backpressure.
  2. Publisher: Emits a stream of data.
  3. Subscriber: Consumes the stream emitted by the Publisher.
  4. Subscription: Manages the interaction between Publisher and Subscriber.
  5. Processor: A mix of both Publisher and Subscriber.

2. Setting Up a Reactive Spring Boot Project

To start with Reactive Programming in Spring Boot, follow these steps:

Step 1: Add Dependencies

Create a Spring Boot project and add the required dependencies in pom.xml:

<dependencies>
    <!-- Spring Boot WebFlux for Reactive programming -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>

    <!-- Spring Boot Reactive MongoDB -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
    </dependency>

    <!-- Lombok for boilerplate code reduction -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <scope>provided</scope>
    </dependency>

    <!-- Spring Boot DevTools for development -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional>
    </dependency>
</dependencies>
Enter fullscreen mode Exit fullscreen mode

3. Understanding Mono and Flux

Spring WebFlux provides Mono and Flux, which represent reactive data types.

  • Mono: Represents 0 or 1 element (useful for single object responses).
  • Flux: Represents 0 to N elements (useful for streaming data).

Example of Mono and Flux

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class ReactiveExample {
    public static void main(String[] args) {
        Mono<String> monoExample = Mono.just("Hello Reactive World");
        monoExample.subscribe(System.out::println);

        Flux<String> fluxExample = Flux.just("A", "B", "C", "D");
        fluxExample.subscribe(System.out::println);
    }
}
Enter fullscreen mode Exit fullscreen mode

4. Creating a Reactive REST API

Now, let’s build a CRUD API using Spring WebFlux and Reactive MongoDB.

Step 1: Define Entity Class

Create a model class Product.java:

import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

@Data
@Document(collection = "products")
public class Product {
    @Id
    private String id;
    private String name;
    private double price;
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Create a Reactive Repository

Spring Data provides ReactiveMongoRepository, which supports non-blocking operations.

import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import reactor.core.publisher.Flux;

public interface ProductRepository extends ReactiveMongoRepository<Product, String> {
    Flux<Product> findByName(String name);
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Implement a Reactive Service Layer

Create a service class ProductService.java:

import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@Service
public class ProductService {
    private final ProductRepository productRepository;

    public ProductService(ProductRepository productRepository) {
        this.productRepository = productRepository;
    }

    public Flux<Product> getAllProducts() {
        return productRepository.findAll();
    }

    public Mono<Product> getProductById(String id) {
        return productRepository.findById(id);
    }

    public Mono<Product> createProduct(Product product) {
        return productRepository.save(product);
    }

    public Mono<Void> deleteProduct(String id) {
        return productRepository.deleteById(id);
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Create a Reactive REST Controller

Now, let’s create a Reactive Controller to expose the API endpoints.

import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@RestController
@RequestMapping("/products")
public class ProductController {
    private final ProductService productService;

    public ProductController(ProductService productService) {
        this.productService = productService;
    }

    @GetMapping
    public Flux<Product> getAllProducts() {
        return productService.getAllProducts();
    }

    @GetMapping("/{id}")
    public Mono<Product> getProductById(@PathVariable String id) {
        return productService.getProductById(id);
    }

    @PostMapping
    public Mono<Product> createProduct(@RequestBody Product product) {
        return productService.createProduct(product);
    }

    @DeleteMapping("/{id}")
    public Mono<Void> deleteProduct(@PathVariable String id) {
        return productService.deleteProduct(id);
    }
}
Enter fullscreen mode Exit fullscreen mode

5. Testing the Reactive API

You can test the API using Postman or cURL.

Create a Product

curl -X POST http://localhost:8080/products -H "Content-Type: application/json" -d '{"name":"Laptop","price":1200}'
Enter fullscreen mode Exit fullscreen mode

Get All Products

curl -X GET http://localhost:8080/products
Enter fullscreen mode Exit fullscreen mode

Get Product by ID

curl -X GET http://localhost:8080/products/{id}
Enter fullscreen mode Exit fullscreen mode

Delete a Product

curl -X DELETE http://localhost:8080/products/{id}
Enter fullscreen mode Exit fullscreen mode

6. Benefits of Using Reactive Programming

  • Non-blocking I/O: Handles more requests with fewer resources.
  • Better Scalability: Suitable for microservices and real-time applications.
  • Efficient Resource Utilization: Reduces thread blocking and improves performance.
  • Streaming Capabilities: Handles continuous data streams efficiently.

7. When to Use Reactive Programming?

✅ Best suited for real-time applications like chat applications, stock price monitoring, and IoT applications.

✅ Useful for high-throughput services that require scalability.

❌ Not necessary for traditional CRUD-based applications with low concurrency.


Conclusion

In this guide, we explored Reactive Programming with Spring Boot step by step. We covered:

✔️ Setting up a Spring Boot WebFlux project

✔️ Understanding Mono and Flux

✔️ Creating a reactive REST API

✔️ Testing and best use cases

Reactive programming is a powerful paradigm, but it should be used when asynchronous processing is truly needed. For high-performance applications, Spring WebFlux is a great choice.

Let me know in the comments if you have any questions! Happy coding!

Top comments (0)