mongodb-crud
Description
This Example is Spring WebFlux non-blocking, asynchronous, and event-driven application. We are going to build REST APIs using Spring Boot WebFlux and MongoDB. Using an API call, we will perform a Create, Read, Update, and Delete (CRUD) operation.
Requirements
- Java 17+
- Spring Boot 3.2.3
- MongoDB 7
Project Structure

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>3.2.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>zjc.examples</groupId>
<artifactId>spring-webflux-mongodb-crud-02</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springmongodb</name>
<description>Demo project for Spring Boot MongoDB CRUD API</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.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</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>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
application.properties
spring.data.mongodb.host=localhost
spring.data.mongodb.port=27017
spring.data.mongodb.database=mydb
Entity
Product.java class which will be the MongoDB document.
package zjc.examples.spring.webflux.mongodb.entity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Document(collection = "products")
public class Product {
// The ID of the product
@Id
private String id;
// The name of the product
private String name;
// The quantity of the product
private int qty;
// The price of the product
private double price;
}
ProductDto.java
package zjc.examples.spring.webflux.mongodb.dto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class ProductDto {
// The ID of the product
private String id;
// The name of the product
private String name;
// The quantity of the product
private int qty;
// The price of the product
private double price;
}
ProductRepository.java
package zjc.examples.spring.webflux.mongodb.repository;
import zjc.examples.spring.webflux.mongodb.entity.Product;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface ProductRepository extends ReactiveMongoRepository<Product, String> {
}
ProductService.java
Mono and Flux types represent asynchronous sequence of elements. Where Mono represents a stream of 0 or 1 element and Flux is for a stream of 0 to N elements.
package zjc.examples.spring.webflux.mongodb.service;
import zjc.examples.spring.webflux.mongodb.dto.ProductDto;
import zjc.examples.spring.webflux.mongodb.repository.ProductRepository;
import zjc.examples.spring.webflux.mongodb.utils.AppUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@Service
public class ProductService {
@Autowired
private ProductRepository repository;
// Get all products
public Flux<ProductDto> getProducts(){
return repository.findAll().map(AppUtils::entityToDto);
}
// Get product using Id
public Mono<ProductDto> getProduct(String id){
return repository.findById(id).map(AppUtils::entityToDto);
}
// Create Product
public Mono<ProductDto> saveProduct(Mono<ProductDto> productDtoMono){
return productDtoMono.map(AppUtils::dtoToEntity)
.flatMap(repository::insert)
.map(AppUtils::entityToDto);
}
// Update Product
public Mono<ProductDto> updateProduct(Mono<ProductDto> productDtoMono, String id){
return repository.findById(id)
.flatMap(p -> productDtoMono.map(AppUtils::dtoToEntity)
.doOnNext(e -> e.setId(id)))
.flatMap(repository::save)
.map(AppUtils::entityToDto);
}
// Delete Product
public Mono<Void> deleteProduct(String id){
return repository.deleteById(id);
}
}
AppUtils.java
package zjc.examples.spring.webflux.mongodb.utils;
import zjc.examples.spring.webflux.mongodb.dto.ProductDto;
import zjc.examples.spring.webflux.mongodb.entity.Product;
import org.springframework.beans.BeanUtils;
// Utility class for converting between Product and ProductDto objects
public class AppUtils {
// Convert Product entity to ProductDto
public static ProductDto entityToDto(Product product) {
ProductDto productDto = new ProductDto();
BeanUtils.copyProperties(product, productDto);
return productDto;
}
// Convert ProductDto to Product entity
public static Product dtoToEntity(ProductDto productDto) {
Product product = new Product();
BeanUtils.copyProperties(productDto, product);
return product;
}
}
ProductController.java
package zjc.examples.spring.webflux.mongodb.controller;
import zjc.examples.spring.webflux.mongodb.dto.ProductDto;
import zjc.examples.spring.webflux.mongodb.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
// Controller class for managing Product-related HTTP requests
@RestController
@RequestMapping("/products")
public class ProductController {
@Autowired
private ProductService service;
// Get all products
@GetMapping
public Flux<ProductDto> getProducts(){
return service.getProducts();
}
// GET product using Id
@GetMapping("/{id}")
public Mono<ProductDto> getProduct(@PathVariable String id){
return service.getProduct(id);
}
// Create new Product
@PostMapping
public Mono<ProductDto> saveProduct(@RequestBody Mono<ProductDto> productDtoMono){
return service.saveProduct(productDtoMono);
}
// Update product using Id
@PutMapping("/update/{id}")
public Mono<ProductDto> updateProduct(@RequestBody Mono<ProductDto> productDtoMono, @PathVariable String id){
return service.updateProduct(productDtoMono, id);
}
// Delete Product using Id
@DeleteMapping("/delete/{id}")
public Mono<Void> deleteProduct(@PathVariable String id){
return service.deleteProduct(id);
}
}
Running
mvn spring-boot:run
In Postman:
Create Operation

mongodb:
~$ mongosh
Current Mongosh Log ID: 6676a8b203ca3bc446597192
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.2.9
Using MongoDB: 7.0.11
Using Mongosh: 2.2.9
For mongosh info see: https://docs.mongodb.com/mongodb-shell/
------
The server generated these startup warnings when booting
2024-06-22T09:15:08.912+02:00: Using the XFS filesystem is strongly recommended with the WiredTiger storage engine. See http://dochub.mongodb.org/core/prodnotes-filesystem
2024-06-22T09:15:09.187+02:00: Access control is not enabled for the database. Read and write access to data and configuration is unrestricted
2024-06-22T09:15:09.187+02:00: vm.max_map_count is too low
------
test> use mydb
switched to db mydb
mydb> db.products.find()
[
{
_id: ObjectId('6676a8c7570db464a118377a'),
name: 'Java',
qty: 2,
price: 29,
_class: 'zjc.examples.spring.webflux.mongodb.entity.Product'
}
]
mydb>
Analogously:
- Read Operation,
- Update Operation
- Delete Operation.
Source code:
https://github.com/ZbCiok/zjc-examples/tree/main/spring/webflux/spring-webflux-mongodb-crud-02