Open In App

Spring WebFlux Functional Endpoints CRUD REST API Example

Last Updated : 29 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Spring Boot is a Java framework for back-end development. Another miracle in Spring Boot is the Spring Boot Community has developed the Spring Reactive Web Framework i.e. Spring WebFlux.

To develop this project, we have used the MongoDB database. Here, for every CRUD (Create, Retrieve, Update, Delete) operation, we have created one REST API endpoint. These API endpoints are defined by using the RouterFunction. It returns a route function.

  • In CRUD operation C indicates creating data in MongoDB. For this, we have created a REST API endpoint, this API takes input in the form of JSON format.
  • The R indicates retrieve operation. It means we can retrieve all existing data, or by using ID also we can retrieve data from the database.
  • Next, U indicates an update operation in CRUD. We can be able to update existing data by using ID.
  • The final one is D indicates the delete operation. We can delete the data from MongoDB by using the existing ID or delete all data.

Tools and Technologies:

Below are the tools and technologies we have used to create this project.

  • Spring Tools Suite
  • MongoDB
  • Spring WebFlux Reactive Framework
  • REST APIs

Project Creation:

  • Open the Spring Tool Suite then select New project and select Spring Stater type.
  • After that select Maven or Gradle Project Type.
  • Then provide the project name, package name, and other project details.
  • Then select dependencies (Maven/Gradle).
  • Now click on finish.

Project Folder Structure:

Below we can see the Project Structure.

Project Structure

Project Dependencies:

In this project, we have used below Gradle dependencies.

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-mongodb-reactive'
implementation 'org.springframework.boot:spring-boot-starter-webflux'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.projectreactor:reactor-test'
}

MongoDB Connection

In application.properties file configuration the database connection with required properties. Below we have provided the connection and working is the database name.

spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=working

In project main package, we have created different classes for different purposes. Each Java class perform different actions. Below is the list of all the classes and explanation of their functionally.

  • The Student class is a POJO class which is used for defining the attributes of Student collection.
  • This class have Setters and Getters methods to handle the data while performing CRUD operation. This class have id, studentName, studentAge attributes.
  • After this, we have created one Repository for Database operations. This is an interface which is extends to ReactiveMongoRepository. This interface name is UserRepo.
  • Then, we create one service class by using @service, the class name is ServiceHandler, in this class we develop the CRUD operation APIs.
  • Finally, we have created one more Java class for handling API routing. This class defines the API end points with required API URLs. This class is created by using @Configuration with help of RouterFunction.

Student POJO class

Here, we have created one POJO class which handles the database operations by using lombok dependency.

  • This class provides setters and getters with all types of constructors.
  • This class has two attributes named id, studentName, studentAge.
  • Then the id is automatically generated by the MongoDB at the time of creation of the new record in collection.

Java




package com.webflux.app;
  
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
  
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
  
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "student")
public class Student {
    @Id
    private String id;
    private String studentName;
    private String studentAge;
}


UserRepo Interface

The UserRepo interface (Repository layer) is used for performing the database related operations on Student class.

  • This interface extends the ReactiveMongoRepository.
  • This repository is created by using @Repository, @EnableReactiveMongoRepositories annotations.
  • The ReactiveMongoRepository takes two arguments as an input.

Java




package com.webflux.app;
  
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories;
import org.springframework.stereotype.Repository;
  
@Repository
@EnableReactiveMongoRepositories
public interface UserRepo extends ReactiveMongoRepository<Student, String> {
  
}


ServiceHandler class

This class is a service layer for creating API logic.

  • In this class, we have created four APIs to perform CRUD operations.
  • Below we have provided each API logic.
  • The service class is created by using @Service annotation.
  • And then by using UserRepo repositort class, we perform the CRUD operation.

Java




package com.webflux.app;
  
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.server.ServerRequest;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.Mono;
  
@Service
public class ServiceHandler {
  
    @Autowired
    private UserRepo userRepo;
  
    public Mono<ServerResponse> addStudent(ServerRequest request) {
        return request.bodyToMono(Student.class).flatMap(data -> {
            return ServerResponse.ok().body(userRepo.save(data), Student.class);
        });
    }
  
    public Mono<ServerResponse> deleteStudentById(ServerRequest request) {
        return request.bodyToMono(Student.class).flatMap(data -> {
            return ServerResponse.ok().body(userRepo.deleteById(data.getId()), Student.class);
        }).switchIfEmpty(ServerResponse.ok().bodyValue("No Student Data Found"));
    }
  
    public Mono<ServerResponse> updateStudentById(ServerRequest request) {
        return request.bodyToMono(Student.class).flatMap(data -> {
            return userRepo.findById(data.getId()).flatMap(change -> {
                change.setId(data.getId());
                change.setStudentName(data.getStudentName());
                change.setStudentAge(data.getStudentAge());
                return ServerResponse.ok().body(userRepo.save(change), Student.class);
            }).switchIfEmpty(ServerResponse.ok().bodyValue("No Student Data Found"));
        });
    }
  
    public Mono<ServerResponse> getAllStudents(ServerRequest request) {
        return request.bodyToMono(Student.class).flatMap(data -> {
            return ServerResponse.ok().body(userRepo.findAll(), Student.class);
        }).switchIfEmpty(ServerResponse.ok().bodyValue("No Student Data Found"));
    }
}


ServiceRouter class

This is another Java class for handling REST API end point.

  • The ServiceRouter class is created by using @Configuration annotation and this class has one bean i.e. the RouterFunction.
  • And this bean creates routing end points for ServiceHandler.
  • Below we have provided the Java code for handling API end points.
  • This class has four REST API end points to handle all the CRUD operations.

Java




package com.webflux.app;
  
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
  
@Configuration
public class ServiceRouter {
      
    @Autowired
    private ServiceHandler serviceHandler;
      
    @Bean
    RouterFunction<ServerResponse> routerFunction(){
        return RouterFunctions.route(RequestPredicates.POST("api/student/add"),serviceHandler::addStudent)
                .andRoute(RequestPredicates.POST("api/student/delete"), serviceHandler::deleteStudentById)
                .andRoute(RequestPredicates.POST("api/student/update"), serviceHandler::updateStudentById)
                .andRoute(RequestPredicates.POST("api/student/getall"), serviceHandler::getAllStudents)
                ;
                  
    }
      
}


addStudent REST API:

This logic is used for creating a new Student row in collection. Here, we have used Mono publisher, and it returns the ServerResponse as an output.

  • In this, first we have converted the Student POJO class body to Mono publisher by using bodyToMono().
  • Then we have created one flatmap. In this flatmap, we have created one lambda expression for save the data.
  • Then we save the student data by using the object of UserRepo repository.
  • And Its REST API URL is defined in ServiceRouter.
REST API URL: api/student/add

Java




public Mono<ServerResponse>
addStudent(ServerRequest request)
{
    return request.bodyToMono(Student.class)
        .flatMap(data -> {
            return ServerResponse.ok().body(
                userRepo.save(data), Student.class);
        });
}


When we test this API URL by using the Postman, successfully the data is inserted into a collection. Below we have provided the output image for reference. When we hit this API URL, the data is saved into collection and return that saved record as an output.

Output:

Below we can see that we have added one Student with name and age in POSTMAN.

Add Student Details

deleteStudentById REST API:

The API logic is used for deleting an existing student data by using Student Id. If Id is available student data will be deleted, or else, it will give some error message as an output. In this, we have created one flatmap for finding Id. If the id exists, then deleted or switchIfEmpty() method will be executed.

REST API URL: api/student/delete

Java




public Mono<ServerResponse> deleteStudentById(ServerRequest request) {
    return request.bodyToMono(Student.class).flatMap(data -> {
        return ServerResponse.ok().body(userRepo.deleteById(data.getId()), Student.class);
    }).switchIfEmpty(ServerResponse.ok().bodyValue("No Student Data Found"));
}


Output:

Below we can see the deleted student id in POSTMAN.

Delete Student details

updateStudentById REST API:

This API is used for updating the existing Student data by using the Student ID. If Student Id not found it gives an error message otherwise successfully update new data for existing id, then return the new data as server response.

REST API URL: api/student/update

Java




public Mono<ServerResponse> updateStudentById(ServerRequest request) {
        return request.bodyToMono(Student.class).flatMap(data -> {
            return userRepo.findById(data.getId()).flatMap(change -> {
                change.setId(data.getId());
                change.setStudentName(data.getStudentName());
                change.setStudentAge(data.getStudentAge());
                return ServerResponse.ok().body(userRepo.save(change), Student.class);
            }).switchIfEmpty(ServerResponse.ok().bodyValue("No Student Data Found"));
        });
    }


Output:

Below we can see the updated student details in POSTMAN.

Updated Student details

getAllStudents REST API:

This REST API returns all existing student data from database.

REST API URL: api/student/update

Java




public Mono<ServerResponse> getAllStudents(ServerRequest request) {
        return request.bodyToMono(Student.class).flatMap(data -> {
            return ServerResponse.ok().body(userRepo.findAll(), Student.class);
        }).switchIfEmpty(ServerResponse.ok().bodyValue("No Student Data Found"));
    }


We have two Student details only, when we hit this in POSTMAN, the API return that two records data from database.

Output:

In POSTMAN, we can test the API end point, and we got the below student details.

Get all Student details



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads