Creating Reactive REST API with Spring Boot and MongoDB

Meta

Audience : Who knows Spring Boot and want to learn Reactive Spring

Source code: https://github.com/CODINGSAINT/springboot-rective-microservices-with-reactjs/tree/1_user-service

##

Reactive Spring Boot is new paradigm shift in the way we have worked with Spring and traditional approach.While we have always been treating the web api calls as a thread based model where the request is made and response is received as one single transaction (not Database transaction) , Reactive approach further breaks it to multiple segments , where clients creates a request and doesn’t wait for response immediately , whenever server has response ,it will be forwarded to client.

Why Reactive

Let’s look at the impact it makes over regular approach.
While in regular web calls with each request a new thread is created at server, it complete it job and then terminate (read kills). In case when we interact with blocking operation thread waits, for example if we try to retrive lots of data from database , the thread will wait till database gives us the information, once it receives it will give us data back.

Reactive approach doesn’t wait, say if we have to retrieve data from database it just notifies that client requires data after that the thread is free to serve another request. On the reactive database side once the data is ready it will send back to intended client using another thread.
This approach will allow us to scale. Tomcat or any server as a limit of handling concurrent requests say 200 requests per second. What if all of them are waiting for blocking operations. Server will have slow down. Reactive approach helps here.

Creating Simple Reactive API with Spring Boot

Let’s create a Reactive API with Spring boot and Mongo in new Functional approach
Though we can use traditional style of programming using @Controller or @RestController , here we will create a CRUD api with Functional approach and will keep refining our approach in subsequent lectures.

Step 1:
Download the project from http://start.spring.io
Choose following dependencies

  1. spring-boot-starter-webflux (Spring Web Reactive)
  2. spring-boot-starter-data-mongodb-reactive (Reactive Mongo database)
  3. spring-boot-devtools (Devtool)
  4. org.projectlombok (Lombok)

We are using group id as: com.codingsaint.learning.microservices.reactive and artifact-id : user-service.

You can also click here to download all dependencies
ScreenshotReactiveSpringDependencies

Step 2:
Create a User bean (Mongodb document)

package com.codingsaint.learning.microservices.reactive.userservice.model;

import lombok.Data;
import org.springframework.data.mongodb.core.mapping.Document;

@Document
@Data
public class User {
private String id;
private String name;
private String email;
}

Step 3: Create a UserRepository bean for reactive mongo db

com.codingsaint.learning.microservices.reactive.userservice.repository;

import com.codingsaint.learning.microservices.reactive.userservice.model.User;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import org.springframework.stereotype.Repository;

@Repository

public interface UserRepository extends ReactiveMongoRepository<User,String> {
}

Step 4: Instead of Controller we will use a Router Function , It is just simple bean which will act as Router for us, here we can use functional style of mapping to create different routes.

package com.codingsaint.learning.microservices.reactive.userservice;

import com.codingsaint.learning.microservices.reactive.userservice.model.User;
import com.codingsaint.learning.microservices.reactive.userservice.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;

@Configuration
@RequiredArgsConstructor
public class UserRouteConfiguration {
    private final UserRepository userRepository;

    @Bean
    public RouterFunction userRoutes() {
        return RouterFunctions.route(
                RequestPredicates.GET("/users"), serverRequest ->
                        ServerResponse.ok()
                                .body(BodyInserters.fromPublisher(
                                        userRepository.findAll(), User.class))
        ).andRoute(RequestPredicates.POST("/user"), serverRequest -> {
            Mono user = serverRequest.bodyToMono(User.class);
            return ServerResponse.status(HttpStatus.CREATED)
                    .body(BodyInserters.fromPublisher(
                            user.flatMap(userRepository::save), User.class)
                    );
        }).andRoute(RequestPredicates.PUT("/user"), serverRequest -> {
            Mono user = serverRequest.bodyToMono(User.class);
            return ServerResponse.status(HttpStatus.OK)
                    .body(BodyInserters.fromPublisher(
                            user.flatMap(userRepository::save), User.class)
                    );
        }).andRoute(RequestPredicates.GET("/user/{id}"), serverRequest -> {
            String _id = serverRequest.pathVariable("id");
            return ServerResponse.ok()
                    .body(BodyInserters.fromPublisher(
                            userRepository.findById(_id), User.class));
        }).andRoute(RequestPredicates.DELETE("/user/{id}"), serverRequest -> {
            String _id = serverRequest.pathVariable("id");
            return ServerResponse.noContent().build(userRepository.deleteById(_id));
        });
    }
}

Step 5:
add mongodb information to application.properties

spring.data.mongodb.uri=mongodb://localhost/users

Start the application and you will be able to perform CRUD operation is Spring Reactive Mongodb User application. >

Did you find this article valuable?

Support Kumar Pallav by becoming a sponsor. Any amount is appreciated!