SpringBoot 2 -WebFlux reactive stack.

Spring-boot 2.0 was released recently and everyone is excited about the new features and improvements.
I love the ease and simplicity with which Spring-boot lets you create services with minimum fuss.


One of the most interesting, critical and note-worthy feature is the addition and support of reactive programming model.
Spring 5 introduced WebFlux framework which is a fully asynchronous and non-blocking reactive web stack that enables handling massive number of concurrent connections. This enables us to vertically scale the service to handle more load on the same hardware.



Fluxes and Monos

In our scenario, we use the Flux class. It implements the Publisher interface and, as we briefly introduced, it is just a reactive stream that pushes items whenever the subscriber instructs it to do so.
There is a handy version of a Flux for the special case in which the reactive stream will either emit only one item, or none: Mono. It contains a different subset of methods so, for instance, concatenating a Mono with another Mono, or a Flux, will return a Flux.

Reactor Integrations

Spring is including Reactor in some of their libraries, thus applying reactive programming patterns to them. Following a smart approach, they’re not getting rid of the previous programming style so don’t worry, updating to Spring 5 doesn’t mean being forced to adopt reactive programming.
The first big framework into which Spring is leveraging Reactor is, as you may guess, the Web framework. Starting with the version 5 you can use Spring WebFlux, which comes with major updates like a new way of declaring the routes, and transparent support for Server-Sent Events using the Reactor API.
Spring Data JPA has also embraced Reactive Patterns in its new major version 2.0, with the inclusion of the ReactiveCrudRepository. That means you can perform reactive queries to databases like MongoDB, which already have a reactive version of its driver, and pull data in a flow controlled by the subscribers instead of pushing the query results.

WebFlux – Main Features

Standard Controllers and Router Functions

Spring WebFlux comes with an extra new feature called Router Functions. The idea is to apply Functional Programming to the Web layer and to get rid of the declarative way of implementing Controllers and RequestMapping’s – see the full docs here. However, as you can see depicted in the picture below, Spring 5 still allows you to use the @Controller and @RequestMapping annotations, so you can actually decide.

Spring WebFlux Alternatives
Spring WebFlux Alternatives – Image based on the one available on the official docs

In this guide, I’ll use the classic, simple way of declaring routes and controllers: declarative annotations. The main reason is that I don’t want to distract you with multiples changes at once but also, to be honest, I’m not yet convinced of the convenience of that new style of declaring routes (feel free to judge for yourself).

WebClient

WebFlux comes with a reactive web client too: WebClient. You can use it to perform requests to controllers that use reactive streams, and benefit from backpressure as well. It’s a kind of reactive and fluent version of a RestTemplate.
As described in the first part of this guide, we won’t use here this WebClient to avoid endogamic Java-Spring examples. We’ll create an Angular frontend to consume the endpoints, and detail what we get and what we don’t get when compared to WebClient.

Creating the application

Spring Boot Reactive Skeleton

To start with, the easiest option is to navigate to http://start.spring.io/ and create a Spring Boot application skeleton project. Make sure to select a Spring Boot version 2.0 or newer, the Reactive Web and the Reactive MongoDB dependencies.
Spring Boot 2.0 can integrate the WebFlux capabilities so let’s use its power to set up our backend. The first change we apply is already in our dependency management: we don’t include the MVC starter but the WebFlux one (spring-boot-starter-webflux). This starter contains the Reactor Netty server library dependencies, so Spring Boot will know that’s the one to start at runtime, and we’ll have available the Reactor API during development.
On the other hand, the Reactive MongoDB dependencies are included with the starter spring-boot-starter-data-mongodb-reactive. This one pulls the Spring Data MongoDB dependency, containing Spring Data Commons 2.0 with reactive support, and the asynchronous and reactive-streams versions of the MongoDB driver.

Repository Layer

Reactive Repository with Spring 5 and Spring Data JPA 2.0

To implement a truly Full Reactive Stack we’ll use a MongoDB datastore using its reactive driver. The QuoteMongoRepository implementation consumes quotes from a Spanish masterpiece: Don Quixote. Therefore, this repository data is the source of our Flux.
Creating a basic Reactive repository is as simple as creating a classic one in previous versions of Spring Data JPA: you just need to create an interface that extends ReactiveCrudRepository, which is the reactive version of CrudRepository. You’ll have access to default methods to create, delete, update and read Quotes.
Since we want the paged version of findAll, we define a new interface method that uses a Pageable and has a defined query to return all the quotes with an id – thus all of them. See the MongoDB documentation if you’re curious about this json query specification. Note that, to avoid side effects, you shouldn’t name your method starting with find nor query, otherwise you’ll activate the Query Methods feature.
Both the findAll and the retrieveAllQuotesPaged that we’ll use from the controller return a Flux. That means that our subscriber (the controller) can control how fast the data should be pulled from the database.

Saving entities in a reactive manner

One thing that draws the attention of people not familiar with reactive patterns is how the save method (and its variants) work. Let’s compare the CrudRepository and the ReactiveCrudRepository signatures:
Now imagine that we want to save a Quote and we’re so confident about the result that we just ignore it, so we use:
You can do that with an interface extending CrudRepository and the entity will be persisted. However, if you do that with a ReactiveCrudRepository, the entity is not stored. The reason is simple: the latter is returning a Mono, which is a Publisher, and it won’t start working until you subscribe to it. If you want to keep the blocking behavior that CrudRepository offers, you need to call instead quoteRepository.save(quote).block(). Anyway, we’ll see an example of this while explaining the QuijoteDataLoader class.

The Quote class

Below you can find the Quote class implementation. It contains just an identifier, the book title and the quote contents.

The Reactive Controller

Controller Code

Let’s focus now on the most important part of our backend application for the purpose we have in this post: the Reactive Controller.
If you’re familiar with Spring Controllers, you’ll find out quickly that the only part of the code that seems new is the Flux object we’re returning as a result of the methods. In Spring MVC, we would return a List (Iterable) instead (which we can still use, as we’ll see later).
Note that, if we would have chosen the Router Functions alternative instead of the annotated controllers (@RestController and @GetMapping annotations), the implementation would be quite different. Anyhow, the resulting functionality would be exactly the same.
The controller is calling the QuoteMongoRepository to retrieve all quotes. The printed versions of Don Quixote can easily get to more than 500 pages so you can imagine that there are a lot of quotes (more than 5000). Thanks to the reactive approach, we don’t need the full list of results to be available in the backend before getting them: we can consume the quotes one by one as soon as the MongoDB driver is publishing results.

Source:
https://thepracticaldeveloper.com/2017/11/04/full-reactive-stack-with-spring-webflux-and-angularjs/#Fluxes_and_Monos



Kommentare

Beliebte Posts