Reactive Programming in Spring Boot using Spring Webflux Framework

What is Spring Webflux?

The Spring Webflux was included in Spring 5 to provide reactive programming support to the Spring-based applications and it is based on Project Reactor and uses non-blocking reactive streams. Spring Webflux can also be used in RxJava or any other reactive streams implementation as seen in the above article Reactive Programming in Java โ€” part 2

As we see from the above diagram, Spring Webflux and Spring MVC sit parallelly in the Spring stack. The major difference is that the Web flux stack is reactive in nature in comparison to the MVC stack which works on the Thread per request model. The Servlet container, Application, and the databases must be reactive in order to achieve the objective of a Reactive Application. But Spring Webflux can be used along with Spring Boot without much changes

Dependencies required to set up Spring Web flux

We just need the dependency which is the latest version as of June 2022.

<dependency>  

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-webflux</artifactId>     <version>2.7.0</version>

</dependency>

Usually, we add spring-boot-starter-web for the traditional MVC framework model but we add spring-boot-starter-webflux for the reactive application using webflux

This dependency includes the below dependencies

  • spring-webflux framework
  • reactor-core that we need for reactive streams
  • reactor-netty (the default server that supports reactive streams). Any other servlet 3.1+ containers like Tomcat, Jetty or non-servlet containers like Undertow can be used as well
  • spring-boot and spring-boot-starter for basic Spring Boot application setup

Spring Webflux publishers

Webflux provides 2 types of publishers namely

  • Mono (0โ€ฆ1)
  • Flux (0โ€ฆN)

The framework accepts a plain publisher as input and maps it to a reactor type internally, processes it, and returns either a Mono or Flux as the output

Mono

The Mono will return 0 or 1 element

Mono<String> mono = Mono.just(“Hello”);

Mono<String> mono = Mono.empty();

Flux

The Flux is a collection that returns 0 to N elements

Flux<String> flux = Flux.just(“Hello”, “World”);

Flux<String> flux = Flux.fromArray(new String[]{“A”, “B”});

Let’s see a simple example of how to use Mono and Flux in a RestController.

@RequestMapping(value = “”, method = RequestMethod.GET)

public Flux<User> findByName(@PathVariable(“name”) String name, produces = MediaType.TEXT_EVENT_STREAM_VALUE) {

return userService.findByName(name);

}

@RequestMapping(method = RequestMethod.GET, produces = MediaType.TEXT_EVENT_STREAM_VALUE)

public Flux<Employee> findAll() {

Flux<Employee> emps = employeeService.findAll();

return emps;

}

As we see, both the above APIs get the request and they either return either a Mono or Flux and the content type is text/event-stream.

So when the above 2 APIs are called, it will return immediately but the results will be delivered through Mono or Flux once they are ready.

The below diagram demonstrates the data flow on how the requests come in and flow through the webflux framework and how the response is returned in the form of Mono / Flux

Eg: let’s assume we need to retrieve all the records in a student table through the get API and let’s say we have 1000 records.

In a traditional MVC application, the request will come into the server and is processed and a response is constructed after fetching all 1000 records, then the response is sent to the requestor. Until the entire operation, the particular Thread-per-Request is blocked and if there are a lot of concurrent requests, everything will be blocked.

In Spring Webflux, the request comes in and it is mapped to the event loop there is no specific thread assigned to that request, and it is not blocking any resource. So the requestor will not get all 1000 records at once from the API instead the records will be sent one by one to the requestor when ready. Hence response is faster and its non-blocking which is very efficient

Reactive Spring Security

We can use the Spring Security to secure the reactive endpoints / APIs. It works the same way as the normal Spring Boot application by using the dependency as shown below

<dependency>

<groupId>org.springframework.boot</groupId>         <artifactId>spring-boot-starter-security</artifactId>

</dependency>

We need to use the below annotation and the config to set up basic authentication and authorization

@EnableWebFluxSecurity

public class HelloWebfluxSecurityConfig {

@Bean

public MapReactiveUserDetailsService userDetailsService() {

 UserDetails user = User.withDefaultPasswordEncoder()

  .username(“user”)

  .password(“user”)

  .roles(“USER”)

  .build();

 return new MapReactiveUserDetailsService(user);

}

}

Reactive Database โ€” R2DBC

The Reactive Relational Database Connectivity (R2DBC) project brings reactive programming APIs to relational databases. The traditional JDBC is blocking in nature and to work well with reactive applications, we need a non-blocking JDBC drivers and then came the R2DBC. R2DBC specifies a new API to allow reactive code that works efficiently with relational databases.

Spring Data R2DBC is implemeted using the R2DBC and provides the specification to integrate SQL databases using reactive drivers. Spring Data R2DBC provides R2dbcEntityTemplate to interact with the database and it is supported for following databases namely

  • H2 (io.r2dbc:r2dbc-h2)
  • MariaDB (org.mariadb:r2dbc-mariadb)
  • Microsoft SQL Server (io.r2dbc:r2dbc-mssql)
  • MySQL (dev.miku:r2dbc-mysql)
  • jasync-sql MySQL (com.github.jasync-sql:jasync-r2dbc-mysql)
  • Postgres (io.r2dbc:r2dbc-postgresql)
  • Oracle (com.oracle.database.r2dbc:oracle-r2dbc)

We can use the dependency for any of the above databases and i am just demonstrating for the postgresql

<dependency>

<groupId>io.r2dbc</groupId>

<artifactId>r2dbc-postgresql</artifactId>

<version>1.0.0.M5</version>

</dependency>

The Repository for the reactive APIs looks like below

interface UserRepository extends ReactiveCrudRepository<User, String> {

Flux<User> findByFirstname(String firstname);

}

As we see above, we use the ReactiveCrudRepository whereas in the traditional JDBC, we use CrudRepository

The response from DB is again sent as Mono or Flux which is in line with what we saw in above in the Controller

In this article, we saw what is Spring Webflux and how to do reactive programming in Spring using Webflux. We also saw what is Spring Data R2DBC and how to use it from Spring application to interact with the relational databases using reactive APIs to make the whole application reactive.

I work as a freelance Architect at Ontoborn, who are experts in putting together a team needed for building your product. This article was originally published on my personal blog.