Functional Endpoints
By: Augusto Sopelsa Klaic
Tags: Webflux, Rest Api, Functional Programming, Spring Framework

A Webflux new way of endpointing

Functional web framework

With the release of the new module of Spring framework, more specific the version 5, brought new and cool features to it, for example, the reactive module was added to the framework stack.

This reactive module adds support to a fully non-blocking API, reactive streams back-pressure and uses servers as Netty and Undertow that are reactive native. But one of the most cool things that was added is the functional endpoints.

So what is this thing? It is another way of doing REST endpoints, opposing the annotation based that is largely used nowadays. Instead of annotation mapping now the functional web framework uses two different functions know as RouterFunction & HandlerFunction to map the endpoints. This guys runs on the same reactive core foundation as the annotation based ones. To brief a little the Router takes care of incoming requests and send then to the Handler that sends a response.

Router Function:

It’s objective is to serve as a substitute for the annotation @RequestMapping, it provides data like Request Mapping but also provide behavior and the main usage is to route requests to the handler function. Is not common to write routers functions by yourself, the best practice is to create them using the Router Function utility class, like this RouterFunction.route() and then you can list out the endpoints needed like this:

In the example above you can see that I have nested two REST GET endpoints that return hello messages, one is personalized with some name passed by path parameter. For this work we need to put a @Bean annotation on the top of the method hello(HelloHandlre helloHandler) that will tell Spring to inject it’s dependency and create the route and that Bean needs to be in the file annotated with @Configuration. The last parameter in .GET() method is the Handler Function, that will execute some action based on the info it receive, create, delete, update or return.

Handler Function:

The handler function like said previously, will execute some desirable action based on the REST verb that is used. Basically is where the business logic is present. It works with two immutable interfaces the ServerRequest for receiving information from the server and the ServerResponse for sending information to the server. Both of them work with the Reactor Mono and Flux and provide Reactive Streams back pressure against the body streams. A simple Handler Function looks like this:

In the example above, I’ve created two handlers the first one just return a Hello for the one who calls the endpoint and a status of success (HTTP 200). In the second one I receive a parameter from the URL and add it to the response String and set the status to success too (HTTP 200). All these handlers has to be inside of some Spring Stereotype class, that is annotated with @Component or other.

Nested Endpoints:

This section here I will use to show how to create composed routes with common paths. In the examples of the previous topics I showed a simple example creating two simple routes, but what if we have a complex set of URLs? How can we create composed URL wit common predicates? To solve this problem we can use two types:

The first one is using .path() & .nest() functions to define a super URL and then use list the HTTP verbs and the rest of URLs inside nest block, something like this:

The nest function can helps when there are a group of routes that share the same path, header or predicate. The path function defines a common path to the nested routes. In the example above I defined a common header that accepts the media type JSON and under it i specified all the routes.

The second type it is a more verbose solution using the functions .and() and the .andRoute() . This two function are very similar but one is more generic than the other.

The basic diference between the two of them is that the andRoute can delegate the request directly to the specified Handler Function. It combines the and & route into a single function.