Building a CRUD with Spring Webflux
By: Stefano Troìa
Tags: Software Development, Reactive Programming, Java, Software Engineering, Programming

Photo by Biegun Wschodni on Unsplash

Spring Webflux is a recent version of Spring refactored to allow building non-blocking applications using the project reactor. The main difference is the application server: with Webflux your application will run under Netty which is the “Asynchronous event-driven network application framework”, instead of Tomcat.

Reactive programming

If you are not familiar with this kind of programming approach, you have to know we are building applications based on data-stream and propagation of events/changes of data or conditions.

Project Reactor

It’s an interesting framework that brings reactive programming in Java after javaRx. The pillars of this library are two classes:

Mono<T> — is a publisher that produces from 0 to 1 value of T

— is a publisher that produces from to value of Flux<T> — is a publisher that produces from 0 to N values of T

Both classes follow a basic, but a fundamental principle:

Nothing happens until you subscribe

This means all operations are lazy and they are performed only when the subscribe method is called.

Our Example

To get in the core of reactor we are going to try simple CRUD operations persisting entities on MongoDB. It’s important to keep in mind that at this moment Spring Data Reactive supports only: MongoDB, Cassandra, and Redis.

Dependencies

Maven dependencies for webflux

Repositories

Will look the same as Spring Data with few changes:

Book Service

Create

We want to insert a book only if its author exists, otherwise, an Exception will be thrown.

flatMap() is an operation similar to map(), but with max depth to 1. For example, we may use it to go from Mono<Mono<Book>> to Mono<Book> like in line 4 of the gist.

is an operation similar to map(), but with max depth to 1. For example, we may use it to go from to like in line 4 of the gist. switchIfEmpty() or defaultIfEmpty() allows to handle nulls generating errors or setting default values

Read

Get book by id and authorId

The first gist is very simple we are calling a method of a Spring Data Repository. Below we are going to perform a query to retrieve a page of n elements.

We will return results in BookResult described by the following attributes:

List<Book> data

Integer page

Integer elements

Get paginated books

To compose our result, the first step is to count the number of books in the DB, after this, we will fill data performing a query with a pageRequest. If the page has 0 elements we will return an error.

flatMapMany() is similar to flatMap(), but it allows to switch from Mono<Flux<Book>> to Flux<Book>

Update

This method will perform a simple update by checking if the book exists.

Delete

Book Controller

No big changes, each endpoint will return a Flux<T> or Mono<T>

Book Controller

Caveats

Spring WebFlux and project-reactor are good allies to build non-blocking applications, using the minimum number of resources without sacrificing performances.

When building complex applications, if you are a Spring “addicted” you will find out many things are not fully compatible.