spring-webflux
Guide to Spring 5 WebFlux
1. Overview
Spring WebFlux framework is part of Spring 5 and provides reactive programming support for web applications.
In this tutorial, we’ll be creating a small reactive REST application using the reactive web components RestController and WebClient.
We will also be looking at how to secure our reactive endpoints using Spring Security.
Further reading:
Spring 5 WebClient
Discover Spring 5’s WebClient – a new reactive RestTemplate alternative.
Spring WebClient vs. RestTemplate
Learn how to make server-side HTTP calls using WebClient and RestTemplate.
2. Spring WebFlux Framework
Spring WebFlux internally uses Project Reactor and its publisher implementations – Flux and Mono.
The new framework supports two programming models:
-
Annotation-based reactive components
-
Functional routing and handling
Here, we’re going to be focusing on the Annotation-based reactive components, as we already explored the functional style – routing and handling.
3. Dependencies
Let’s start with the spring-boot-starter-webflux dependency, which actually 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.1.6.RELEASE</version>
</dependency>
The latest spring-boot-starter-webflux can be downloaded from Maven Central.
4. Reactive REST Application
-
We’ll use a simple domain model – Employee with an id and a name field
-
We’ll build REST APIs for publishing and retrieve Single as well as Collection Employee resources using RestController and WebClient
-
And we will also be creating a secured reactive endpoint using WebFlux and Spring Security
5. Reactive RestController
Spring WebFlux supports the annotation-based configurations in the same way as Spring Web MVC framework.
To begin with, on the server side, we create an annotated controller that publishes our reactive streams of Employee.
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.
5.1. Single Resource
@GetMapping("/{id}")
private Mono<Employee> getEmployeeById(@PathVariable String id) {
return employeeRepository.findEmployeeById(id);
}
For a single Employee resource, we have used a Mono of type Employee because it will emit at most 1 element.
5.2. Collection Resource
Let’s also add an endpoint in our controller that publishes the collection resource of all Employees:
@GetMapping
private Flux<Employee> getAllEmployees() {
return employeeRepository.findAllEmployees();
}
For the collection resource, we have used Flux of type Employee – since that’s the publisher focused on emitting 0..n elements.
6. Reactive Web Client
WebClient introduced in Spring 5 is a non-blocking client with support for Reactive Streams.
On the client side, we use WebClient to retrieve data from our endpoints created in 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 for relative URLs.
6.1. Retrieving a Single Resource
Mono<Employee> employeeMono = client.get()
.uri("/employees/{id}", "1")
.retrieve()
.bodyToMono(Employee.class);
employeeMono.subscribe(System.out::println);
6.2. Retrieving Collection Resource
Flux<Employee> employeeFlux = client.get()
.uri("/employees")
.retrieve()
.bodyToFlux(Employee.class);
employeeFlux.subscribe(System.out::println);
We also have a detailed article on link:/spring-5-webclient.
7. Spring WebFlux Security
Let’s suppose we have a new endpoint in our EmployeeController. This endpoint updates Employee details and sends back the updated Employee.
Since this allows users to change existing employees, we want to restrict this endpoint to ADMIN role users only.
Let’s add a new method to our EmployeeController:
@PostMapping("/update")
private Mono<Employee> updateEmployee(@RequestBody Employee employee) {
return employeeRepository.updateEmployee(employee);
}
Now, to restrict access to this method let’s create SecurityConfig and define some path-based rules to only allow ADMIN users:
@EnableWebFluxSecurity
public class EmployeeWebSecurityConfig {
// ...
@Bean
public SecurityWebFilterChain springSecurityFilterChain(
ServerHttpSecurity http) {
http.csrf().disable()
.authorizeExchange()
.pathMatchers(HttpMethod.POST, "/employees/update").hasRole("ADMIN")
.pathMatchers("/**").permitAll()
.and()
.httpBasic();
return http.build();
}
}
This configuration will restrict access to the endpoint /employees/update. Therefore only users having a role ADMIN will be able to access this endpoint and update an existing Employee.
Finally, the annotation @EnableWebFluxSecurity adds Spring Security WebFlux support with some default configurations.
We also have a detailed article on configuring and working with Spring WebFlux security.
8. Conclusion
In this article, we’ve explored how to create and work with reactive web components supported by Spring WebFlux framework by creating a small Reactive REST application.
We learned how to use RestController and WebClient to publish and consume reactive streams respectively.
We also looked into how to create a secured reactive endpoint with the help of Spring Security.
Other than Reactive RestController and WebClient, WebFlux framework also supports reactive WebSocket and corresponding WebSocketClient for socket style streaming of Reactive Streams.
We have a detailed article focused on working with Reactive WebSocket with Spring 5.
Finally, the complete source code used in this tutorial is available over on Github.