The reactive-stack web framework, Spring WebFlux, has been added to Spring 5.0. It is fully non-blocking, supports reactive streams backpressure, and runs on such servers as Netty, Undertow, and Servlet 3.1+ containers. In this spring webflux tutorial, we will learn the basic concepts behind reactive programming, webflux APIs, and a fully functional hello world example.

What is reactive programming?

Reactive programming is a programming paradigm that promotes an asynchronous, non-blocking, event-driven approach to data processing. Reactive programming involves modeling data and events as observable data streams and implementing data processing routines to react to the changes in those streams.

These all started after Java’s introduction of Streams in 8. It changed the entire perspective of programming. Instead of consumers waiting for the entire data. They started to receive in bits as soon as the server digs them.

First of all, Java 8 Streams should not be confused with Java I/O streams (ex: FileInputStream, etc); these have very little to do with each other.

Simply put, streams are wrappers around a data source, allowing us to operate with that data source and making bulk processing convenient and fast.

A stream does not store data and, in that sense, is not a data structure. It also never modifies the underlying data source.

This functionality – java.util.stream – supports functional-style operations on streams of elements, such as map-reduce transformations on collections.

Coming back to Spring. Spring used a reactive package and designed a webFlux framework for us to work with. We will create a small example of the same. It has two publisher implementations Flux and Mono.

Dependencies

Let’s start with the spring-boot-starter-webflux dependency, which pulls in all other required dependencies:

  • spring-boot and spring-boot-starter for basic Spring Boot application setup
  • spring-webflux framework
  • reactor-core that we need for reactive streams and also reactor-netty
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-webflux</artifactId>
    <version>2.2.6.RELEASE</version>
</dependency>

Reactive REST Application

Now we’ll build a very simple reactive REST EmployeeManagement application using Spring WebFlux:

  • Use a simple domain model – Employee with an id and a name field
  • Build a REST API with a RestController to publish Employee resources as a single resource and as a collection
  • Build a client with WebClient to retrieve the same resource
  • Create a secured reactive endpoint using WebFlux and Spring Security

Reactive RestController

Spring WebFlux supports annotation-based configurations in the same way as the Spring Web MVC

To begin with, on the server, we create an annotated controller that publishes a reactive stream of the Employee resource.

Let’s create our annotated EmployeeController:

@RestController
@RequestMapping("/employees")
public class EmployeeController {

    private final EmployeeRepository employeeRepository;
    
    // constructor...
}

EmployeeRepository can be any data repository that supports non-blocking reactive streams.

1. Single Resource

Then let’s create an endpoint in our controller that publishes a single Employee resource:

@GetMapping("/{id}")
private Mono<Employee> getEmployeeById(@PathVariable String id) {
    return employeeRepository.findEmployeeById(id);
}

We wrap a single Employee resource in a Mono because we return at most one employee.

2. Collection Resource

We also add an endpoint that publishes the collection resource of all Employees:

@GetMapping
private Flux<Employee> getAllEmployees() {
    return employeeRepository.findAllEmployees();
}

For the collection resource, we use a Flux of type Employee since that’s the publisher for 0..n elements.

Reactive Web Client

WebClient, introduced in Spring 5, is a non-blocking client with support for reactive streams.

We can use WebClient to create a client to retrieve data from the endpoints provided by the EmployeeController.

Let’s create a simple EmployeeWebClient:

public class EmployeeWebClient {

    WebClient client = WebClient.create("http://localhost:8080");

    // ...
}

Here we have created a WebClient using its factory method create. It’ll point to localhost:8080, so we can use relative URLs for calls made by this client instance.

1. Retrieving a Single Resource

To retrieve a single resource of type Mono from endpoint /employee/{id}:

Mono<Employee> employeeMono = client.get()
  .uri("/employees/{id}", "1")
  .retrieve()
  .bodyToMono(Employee.class);

employeeMono.subscribe(System.out::println);

2. Retrieving a Collection Resource

Similarly, to retrieve a collection resource of type Flux from endpoint /employees

Flux<Employee> employeeFlux = client.get()
  .uri("/employees")
  .retrieve()
  .bodyToFlux(Employee.class);
        
employeeFlux.subscribe(System.out::println);