Building Reactive REST CRUD APIs with Spring Boot, Spring WebFlux, Azure Cosmos DB and Azure Cosmos DB API for MongoDB

Hello everyone, Hope you are doing well. In this tutorial, you will learn how to build reactive REST CRUD APIs with Spring Boot, Spring WebFlux, Spring Data Reactive MongoDB, Azure Cosmos DB, and Azure Cosmos DB API for MongoDB. 


A little bit of Background

Azure Cosmos DB

Azure Cosmos DB is a fully managed NoSQL database for modern app development. Single-digit millisecond response times, and automatic and instant scalability, guarantee speed at any scale. 

Azure Cosmos DB API for MongoDB

The Azure Cosmos DB API for MongoDB makes it easy to use Cosmos DB as if it were a MongoDB database. You can apply your MongoDB experience and continue to use your favourite MongoDB drivers, SDKs, and tools by pointing your application to the API for the MongoDB account's connection string.

Spring Boot

Spring Boot makes it easy to create stand-alone, production-grade Spring-based Applications that you can "just run". 

Spring WebFlux

The original web framework included in the Spring Framework, Spring Web MVC, was purpose-built for the Servlet API and Servlet containers. The reactive-stack web framework, Spring WebFlux, was added later in version 5.0. It is fully non-blocking, supports Reactive Streams back pressure, and runs on such servers as Netty, Undertow, and Servlet 3.1+ containers.

Reactive APIs are non-blocking and tend to be more efficient because they’re not tying up processing while waiting for stuff to happen. Reactive systems adopt asynchronous I/O. Reactive apps allow us to scale better if we are dealing with lots of streaming data. 
If we are going to build a reactive app, we need it to be reactive all the way down to your database. Use a blocking JDBC driver with Spring WebFlux, and we will be displeased with its performance. Use a reactive NoSQL database like Cassandra, MongoDB, Couchbase, and Redis – and we will be satisfied with its performance.
Spring WebFlux uses a library called Reactor for its reactive support. The Reactor is an implementation of the Reactive Streams specification. The Reactor Provides two main types called Flux and Mono. Both of these types implement the Publisher interface provided by Reactive Streams. Flux is used to represent a stream of 0..N elements and Mono is used to represent a stream of 0..1 element.


After completing this tutorial what we will build? 

We will build REST APIs  CRUD features: 




Step 1: Sign in to Azure Portal and create a resource group

Sign in to Azure portal https://portal.azure.com/#home and find "Resource groups" like below.



Then, create a resource group like the one below.


Here the resource group name is "Knowledgefactory". Create a resource group by clicking the "Review + create " button.




Step 2: Create an Azure Cosmos DB

Sign in to Azure portal https://portal.azure.com/#home and search for "Azure Cosmos DB" like below.

You will be taken to a page like the below image, Then click on the "Create Azure Cosmos DB account" button.

Select API Option,
Then click on the "create" button of the "Azure Cosmos DB API for MongoDB" division.

You will be taken to a page like the below image, 
Enter/Select Resource groupAccount name, etc... Then click on the "Review + create" button.  

You will be taken to a page like the below image, 
Then click on the "Create" button.

Now, You can see "Deployment is in progress" like the below image.

Once deployment is completed you can see the "Your deployment is complete" page like the below image.

Then go to the "Data Explorer" and click on the "New Collection".

Then enter "Database name", "Collection id" etc... like the below image.
Then click on the "OK" button.

Then click on the "Connection String"
Copy "PRIMARY CONNECTION STRING" and keep it safe for future purposes.



Step 3: Creating a simple spring boot web application

First, open the Spring initializr https://start.spring.io/

Then, Provide the Group and Artifact name. We have provided Group name com.knf.dev.demo and Artifact spring-webflux-cosmosdb-mongo-api-crud. Here I selected the Maven project - language Java - Spring Boot 2.7.1 and add Spring Reactive Web dependency and Spring Data Reactive MongoDB dependency. 

Then, click on the Generate button. When we click on the Generate button, it starts packing the project in a .zip(spring-webflux-cosmosdb-mongo-api-crud.zip) file and downloads the project. 
Then, Extract the Zip file and import the project on your favourite IDE.

Final Project Directory



Pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.1</version>
<relativePath/>
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>spring-webflux-cosmosdb-mongo-api-crud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-webflux-cosmosdb-mongo-api-crud</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>
spring-boot-starter-data-mongodb-reactive
</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>



application.properties

Configure your Spring Boot application to use your Azure Cosmos DB API for MongoDB.

spring.data.mongodb.database=<Database name>
spring.data.mongodb.uri=<PRIMARY CONNECTION STRING>


Create User model

@Document(collection = "user")
public class User {

@Id
private String id;
private String name;
private String emailId;

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public String getEmailId() {
return emailId;
}

public void setEmailId(String emailId) {
this.emailId = emailId;
}

public User(String id, String name,
String emailId) {

this.id = id;
this.name = name;
this.emailId = emailId;
}

public User() {

}
}
  • @Id annotation is currently used by Spring to support mapping for other non-relational persistence databases or frameworks that do not have a defined common persistence API like JPA.
  • @Document is an annotation provided by the Spring Data project. It is used to identify a domain object, which is persisted to MongoDB. So you can use it to map a Java class into a collection inside MongoDB.


Create User repository

public interface UserRepository 
extends ReactiveMongoRepository<User, String> {

}
By extending from the ReactiveMongoRepository, we have a reactive MongoDB repository.


Create User service

public interface UserService {

Mono<User> save(User user);

Mono<User> delete(String id);

Mono<User> update(String id, User user);

Flux<User> findAll();

Mono<User> findById(String id);
}


Create User service implementation

@Service
public class UserServiceImpl implements UserService {

@Autowired
private UserRepository userRepository;

@Override
public Mono<User> save(User user) {
return this.userRepository.save(user);
}

@Override
public Mono<User> delete(String id) {

return this.userRepository
.findById(id).flatMap(p ->
this.userRepository
.deleteById(p.getId())
.thenReturn(p));

}

@Override
public Mono<User> update(String id, User user) {

return this.userRepository.findById(id)
.flatMap(u -> {
u.setId(id);
u.setEmailId(user.getEmailId());
u.setName(user.getName());
return save(u);
}).switchIfEmpty(Mono.empty());
}

@Override
public Flux<User> findAll() {
return this.userRepository.findAll();
}

@Override
public Mono<User> findById(String id) {
return this.userRepository.findById(id);
}
}
The @Service annotation represents that our bean holds some business logic.


Implement a Reactive Rest Controller with Spring WebFlux

@RestController
public class UserController {

@Autowired
private UserService userService;

@PostMapping("/users")
@ResponseStatus(HttpStatus.CREATED)
private Mono<User> save(@RequestBody User user) {

return this.userService.save(user);
}

@DeleteMapping("/users/{id}")
private Mono<ResponseEntity<String>> delete
(@PathVariable("id") String id) {

return this.userService.delete(id)
.flatMap(user -> Mono.just(ResponseEntity
.ok("Deleted Successfully")))
.switchIfEmpty(Mono.just(ResponseEntity
.notFound().build()));

}

@PutMapping("/users/{id}")
private Mono<ResponseEntity<User>> update
(@PathVariable("id") String id,
@RequestBody User user) {

return this.userService.update(id, user)
.flatMap(user1 -> Mono.just(ResponseEntity
.ok(user1))).switchIfEmpty(Mono
.just(ResponseEntity.notFound().build()));

}

@GetMapping(value = "/users")
private Flux<User> findAll() {

return this.userService.findAll();
}

@GetMapping("/users/{id}")
private Mono<User> findUserById
(@PathVariable("id") String id)
{
return this.userService.findById(id);
}
}


Spring Boot Driver

@SpringBootApplication
public class Application {

public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}

}
The Spring Boot application's main class contains a public static void main() method that starts up the Spring ApplicationContext.

Download the complete source code - click here   

Step 4: Local Setup and Run the application

Step 1: Download or clone the source code from GitHub to the local machine - Click here


Step 2: mvn clean install


Step 3: Run the Spring Boot application - 

mvn spring-boot:run




Step 5: Test the APIs using postman

1. Add User:



2. Get User By Id:



3. Update User:



4. Get All Users:



5. Delete User:

Popular posts from this blog

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Java Stream API - How to convert List of objects to another List of objects using Java streams?

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Java, Spring Boot Mini Project - Library Management System - Download

ReactJS, Spring Boot JWT Authentication Example

Spring Boot + Mockito simple application with 100% code coverage

Top 5 Java ORM tools - 2024

Java - Blowfish Encryption and decryption Example

Spring boot video streaming example-HTML5

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete