Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A real-world controller example with Spring 5: Web Reactive

I want to be involved in a reactive programming world with Spring. As I realised, it gives me a choice between two different paradigms: the annotation-based (with well-known to us @Controller, @RequestMapping) and the reactive one (which is intended to resolve an "Annotation Hell").

My problem is a lack of understanding how a typical reactive controller will look like. There are three conceptual interfaces, which I can use in my controller class:

HandlerFunction<T> (1) - I define a method for each specific ServerRequest which returns a concrete HandlerFunction<T> instance, then register these methods with a router. Right?

RouterFunction (2) and FilterFunction (3) - Is there a specific place where all RequestPredicates with corresponding HandlerFunctions should be placed? Or can I do it separately in each controller (as I used to do with the annotation approach)? If so, how then to notify a global handler (router, if any?) to apply this router part from this controller?

It's how I see a reactive controller "template" by now:

public class Controller {
    // handlers
    private HandlerFunction<ServerResponse> handleA() {
        return request -> ok().body(fromObject("a"));
    }

    // router
    public RouterFunction<?> getRouter() {
        return route(GET("/a"), handleA()).and(
               route(GET("/b"), handleB()));
    }

    // filter
    public RouterFunction<?> getFilter() {
        return route(GET("/c"), handleC()).filter((request, next) -> next.handle(request));
    }
}

And, finally, how to say that it is a controller, without marking it with the annotation?

I've read the Spring reference and all posts related to this issue on the official blog. There is a plenty of samples, but all of them are pulled out of context (IMHO) and I can't assemble them into a full picture.

I would appreciate if you could provide a real-world example and good practices of how to organise interactions between these functions.

like image 608
Andrew Tobilko Avatar asked Jan 05 '17 03:01

Andrew Tobilko


People also ask

What is the use of spring reactive programming?

Reactive programming is driven by events and focuses on the flow of data in a non-blocking, asynchronous way. Reactive programming is the foundation of Spring WebFlux, an alternative way of developing web applications. Spring WebFlux makes it possible to build reactive applications on the HTTP layer.

What is the use of WebClient and WebTestClient?

WebTestClient is a thin shell around WebClient, using it to perform requests and exposing a dedicated, fluent API for verifying responses. WebTestClient binds to a WebFlux application by using a mock request and response, or it can test any web server over an HTTP connection.

What is the use of spring WebFlux?

WebFlux is a Spring reactive-stack web framework. It was added to Spring 5. It is fully non-blocking, supports reactive streams back pressure, and runs on such servers such as Netty, Undertow, and Servlet 3.1+ containers. Spring WebFlux is an alternative to the traditional Spring MVC.

What is web client example?

What are the examples of web clients? These are examples that allow users to perform different tasks using the web. The popular web browsers such as Google Chrome, Internet Explorer, Opera, Firefox and Safari are examples that allow users to access any website through the Internet.


2 Answers

This is not a real world example, but so far Is how I view some kind of organization on this:

https://github.com/LearningByExample/reactive-ms-example

like image 116
Juan Medina Avatar answered Sep 19 '22 18:09

Juan Medina


As far as I concerned:

RouterFunction is the closest analogue to @Controller (@RequestMapping precisely) in terms of new Spring approach:

Incoming requests are routed to handler functions with a RouterFunction (i.e. Function>). A router function evaluates to a handler function if it matches; otherwise it returns an empty result. The RouterFunction has a similar purpose as a @RequestMapping annotation. However, there is an important distinction: with the annotation your route is limited to what can be expressed through the annotation values, and the processing of those is not trivial to override; with router functions the processing code is right in front of you: you can override or replace it quite easily.

Then instead of Spring Boot SpringApplication.run in main method your run server manually by :

// route is your route function
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route); 
HttpServlet servlet = new ServletHttpHandlerAdapter(httpHandler);
Tomcat server = new Tomcat();
Context rootContext = server.addContext("",
System.getProperty("java.io.tmpdir"));
Tomcat.addServlet(rootContext, "servlet", servlet);
rootContext.addServletMapping("/", "servlet");
tomcatServer.start();

There are both reactive and non-reactive approach. It's illustrated on Spring github

like image 42
Sergii Getman Avatar answered Sep 17 '22 18:09

Sergii Getman