Reactive REST APIs with Spring WebFlux.fn
The traditional servlet-based web frameworks such as Spring MVC are blocking in nature. Spring WebFlux was introduced in Spring 5 and is a fully non-blocking, reactive framework which runs on servers such as Netty, Undertow and Servlet 3.1+ containers.
Spring WebFlux supports two programming models. Applications can be created using annotations or in a functional manner using WebFlux.fn.
Functional Endpoints
With WebFlux.fn, the programming model uses functions to route and handle requests.
HandlerFunction
— HTTP requests are handled by aHandlerFunction
which takes aServerRequest
and returns aMono<ServerResponse>
.HandlerFunctions
are like the body of a@RequestMapping
method in the annotation-based programming model.RouterFunction
— Incoming HTTP requests are routed by aRouterFunction
to aMono<HandlerFunction>
. They can be considered similar to the@RequestMapping
annotation.
By way of a quick overview, let’s create a simple WebFlux.fn REST API using HandlerFunction
and RouterFunction
.
Reactive REST APIs with WebFlux.fn
The helper function RouterFunctions.route()
can be used to build routes. When a RequestPredicate
is matched either the handler or an empty Mono
is returned. Routes are declared as beans in a @Configuration
class.
@Bean
public RouterFunction<ServerResponse> routes() {
return route(GET("/companies/{id}"), handler::getCompanyById)
.and(route(POST("/companies"), handler::updateCompany));
}
For each route the first argument defines the request that will return the corresponding handler. In this example routes have been created to a handler function that returns a Company
resource by Id and to another that updates an existing Company
.
In a typical application it is useful to group handler functions together. This handler class exposes a reactive CompanyRepository
.
@Component
public class CompanyHandler {
private CompanyRepository companyRepository;
public CompanyHandler(CompanyRepository companyRepository) {
this.companyRepository = companyRepository;
}
public Mono<ServerResponse> getCompanyById(ServerRequest request) {
return ok().body(
companyRepository
.findById(request.pathVariable("id")), Company.class);
} public Mono<ServerResponse> updateCompany(ServerRequest request) {
return request.bodyToMono(Company.class)
.doOnNext(companyRepository::updateCompany)
.then(ok().build());
}
}
ServerResponse
provides access to the HTTP response and can be created using the build
method. The builder can set the response code, response headers or a body.
Routes and handlers have now been created to get or update a Company
resource in a non-blocking and reactive manner for this simple REST API.
Summary
The Spring Framework uses Reactor which is a Reactive Streams implementation to support reactive applications.
The Spring WebFlux framework was introduced in Spring 5. It has two different programming models: annotation-based and functional.
The functional model is called WebFlux.fn. RouterFunction
and HandlerFunction
are used to create routes to handle requests and generate responses.