Sign in
Log inSign up
Reactive Sprint Boot application using web-flux

Reactive Sprint Boot application using web-flux

Prabu Subra's photo
Prabu Subra
·Sep 4, 2018

A Reactive Spring Boot application can be written in

    - Imperative style(Spring WebMVC) or
    - Declarative Style(Spring WebFlux). 

What is Reactive Spring Boot application?

it is a implementation of reactive streams(i.e sequence of data pushed from source to subscribers with back pressure), which are non-blocking, asynchronous and event-driven by nature. Spring Reactive libraries are build as part of Project Reactor projectreactor.io.

What is imperative style?

it is not imperative programming just a imperative programming style. it means Reactive Spring boot application can be written using sprint mvc annotations, so with minimum modifications, the old, legacy, big applications can also be converted to reactive nature and can use its features and benefits.

What is declarative style?

it is the latest functional lambda style of programming, this would be the better for new applications which are starting from scratch. let move further.

i recently converted my code base from Spring web-mvc to web-flux model. Initially, i faced few difficulties to understand and use Routers, Handlers and lambda functions, so i thought, writing a flat and simple controllers and equivalent Routers for same use cases will simplify the understanding.

As of now, spring boot apps can be developed in Spring WebMVC or WebFlux model, it is like... this or that, not a mix of both in a single application. so you shouldn’t have RestController annotation or spring-boot-starter-web dependency in pom.xml, if you are using spring web-flux routers.

REST endpoint should be defined on Configuration annotated class as a Bean of RouerFunction, Neither as a RestController nor Controller annotations.

Spring webflux is a programming paradigm used to compose Spring Boot applications on functional style(declarative style) using lambda functions.

1 b7EFW7REaAXfmuuOKdvxEA.png

lets see some code on each model. i have used below bean and written few GET/POST/DELETE Rest endpoints.

Bean:-

 @Table
  public class Topic {
      @PrimaryKey
      private String topicid;
      private String name;
      private String content;
      private String author;
      private String category;
    }

REST end points in Spring Web-MVC:-

Here everything is defined using annotations.

     @RestController
     @RequestMapping(path="/api")
     public class BlogControllers {
        @Autowired BlogRepository blogRepository;
        @GetMapping(path="/blogs")
        public Flux<Topic> getAll(){
        return blogRepository.findAll();
         }
         @GetMapping(path="/blogs/{id}")
        public Mono<Topic> getById(@PathVariable("id") String id){
            return blogRepository.findById(id);
         }
       @PostMapping(path="/blogs")
        public Flux<Topic> createBlogs(@RequestBody Flux<Topic> blogs){
         return blogRepository.saveAll(blogs);
         }
        @DeleteMapping
        public Mono<Void> deleteById(@PathVariable("id") String id){
           return blogRepository.deleteById(id);
        }
       }

REST endpoints in Spring WebFlux:-

Few bunch of annotations are replaced with lambda functions, Not all the annotations. it is working with combination of annotations and lambda functions.

 @Configuration
 public class BlogRouters {
      @Autowired
      BlogRepository blogRepository;
     @Bean
public RouterFunction blogroute(){
    return RouterFunctions.nest(RequestPredicates.path("/api"),
            RouterFunctions.route(RequestPredicates.GET("/blogs"),
                    req-> ServerResponse.ok().body(blogRepository.findAll(),Topic.class))
            .andRoute(RequestPredicates.GET("/blogs/id/{id}"),
                    req -> ServerResponse.ok().body(blogRepository.findById(req.pathVariable("id")),Topic.class))
            .andRoute(RequestPredicates.POST("/blogs"),
                    req -> ServerResponse.ok().body(blogRepository.saveAll(req.bodyToFlux(Topic.class)),Topic.class))
            .andRoute(RequestPredicates.DELETE("/blogs/id/{id}"),
                    req -> ServerResponse.ok().body(blogRepository.deleteById(req.pathVariable("id")),Void.class))
    );
}

}

For better re usability/structure of code, we can have a dedicated handler and utility classes as Spring Component or Service.

Conclusion:-

Eventually, Controller becomes Router. Request and Response related annotations become lambda functions, it may look like Spring framework is moving towards lambda function based configurations (XML → Annotations → lambda functions). but still annotations are playing huge role, even RouterFunction itself configured with Configuration and Bean annotations.

Refer the below git hub repository for code. github.com/prabusubra/microservicelearning

Thanks for spending your valuable time!!! please feel free to comment your views or suggestions…

My Medium Post link :- medium.com/letscode/sprint-boot-applicatio…