Spring WebFlux - 101

Havva Nur Cihanoğlu
Sahibinden Technology
4 min readOct 4, 2022
Photo by James Harrison on Unsplash

Why Reactive Programming

Nowadays, applications should be able to handle more requests with limited resources. It should be elastic, responsive and resilient. Reactive Systems is a good choice to satisfy these needs. We should use reactive programming to achieve this goal.

Traditional Spring MVC model is working with thread per request model. With the rapid evolution of technology, request counts increased drastically. Systems need more threads to handle more requests. Because of server limitations we have to scale horizontally. On the other hand, reactive programming with non-blocking databases like MongoDB will not block threads and will be more scalable and flexible. If we use a blocking data source, threads would be blocked while performing I/O operations. As a result, with reactive programming the threads will never be at waiting state and continue to process operations. It is generally good for data streaming web applications.

Simple client server communication with WebFlux

Spring WebFlux

Spring WebFlux is a web framework which provides to implement fully asynchronous and non-blocking reactive web applications built on event-loop execution model. It comes with Spring 5 and uses Project Reactor. It runs on servers like Netty, Undertow, Tomcat, Jetty…

Non-blocking systems provide data as soon as available. It overwhelms consumers when data speed rate is more than the consumer can manage. At this point, Spring WebFlux supports backpressure since it supports Reactive Stream API. Backpressure is a method to solve this issue by allowing consumers to request data when they are ready to process.

Reactive streams have a publisher (producer)subscriber (consumer) model. In the Reactive Streams API, there are Publisher, Subscriber, Subscription and Processor interfaces.

  • Publisher has only subscribe method and it sends the event to its subscribers.
  • Subscriber has onSubscribe, onNext, onError, onComplete methods to handle the necessary events that are coming from their publishers.
  • Subscription has request and cancel methods to request data and cancel the request.
  • Processor is publisher and subscriber at the same time and it is not a common use case.
Simple pub-sub flow in WebFlux

RestApi Implementation Example

Spring WebFlux has annotation-based and functional programming models. Annotation-based programming model provides simpler code, but functional programming model provides more complex code but more flexibility in routing operations. For complex routing implementations, functional programming model could be preferred.

WebFlux provides 2 types of publishers that a way of creating streams of data:

  • Mono (0…1) -> returns 0 or 1 element Ex: Mono.just(“book1”);
  • Flux (0…N) -> returns 0 or more elements Ex: Flux.just(“book1”, “book2”);

If we expect to get one or zero result instead of a collection we should use Mono instead of Flux. Mono can be considered as a provider for subset of Flux operators.

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.

Annotation Based Implementation:

An example of a controller model is given below. As you can see the main difference from spring MVC is returning the reactive types Mono and Flux.

BookController:

Functional Programming Based Implementation:

Basically, HandlerFunction generates responses for the routed requests like a servlet. RouterFunction can be used instead of @RequestMapping annotation, to route the requests to their handler functions. Since the route method returns a RouterFunction, we can handle more complex routing operations.

Same example with a functional programming model is given below. We are using RouterFunction and HandlerFunction interfaces.

BookRouter:

BookHandler:

Configuration:

@EnableWebFlux

This annotation can be used to autoconfigure WebFlux, if we need other custom configurations we can write our own WebFluxConfigurer classes and add them with @Configuration annotation.

Security:

@EnableWebFluxSecurity

This annotation can be used to secure our application. We can create user roles and secure the paths with these roles.

@EnableReactiveMethodSecurity

With this annotation we can secure a method instead of a path and use @PreAuthorize annotation on the top of methods to be secured. For example if we need to secure just update and delete endpoints we can secure only these methods.

WebClient:

It is WebFlux’s reactive web client. It is a non-blocking asynchronous alternative to RestTemplate. RestTemplate uses the caller thread for each event, but WebClient creates tasks and reactive framework is handling these tasks asynchronously. Since this provides more performance, WebClient has become a better choice.

WebTestClient:

To test our reactive WebFlux application we can use WebTestClient in our unit tests.

--

--