Spring Boot, MongoDB, Reactive CRUD example

In this tutorial, we’re gonna build a Spring Boot MongoDB Reactive example – CRUD application that uses Maven, Spring Data Reactive MongoDB to interact with MongoDB database and Spring WebFlux for Reactive Rest API. You’ll know:

  • How to configure Spring Data to work with MongoDB Database
  • How to define Data Model and Repository interface
  • Way to create Spring Rest Controller to process HTTP requests
  • Way to use Spring Data Reactive MongoDB to interact with Database

More Practice:
Spring Boot + GraphQL + MongoDB example with Spring Data & graphql-java
Spring Boot, MongoDB: JWT Authentication with Spring Security
Spring Boot MongoDB Pagination example with Spring Data

Exception Handling:
Spring Boot @ControllerAdvice & @ExceptionHandler example
@RestControllerAdvice example in Spring Boot

Angular 8 + Spring Boot + MongoDB example
Angular 10 + Spring Boot + MongoDB example
Angular 11 + Spring Boot + MongoDB example
Angular 12 + Spring Boot + MongoDB example
Angular 13 + Spring Boot + MongoDB example
Angular 14 + Spring Boot + MongoDB example
Angular 15 + Spring Boot + MongoDB example
React + Spring Boot + MongoDB example
Vue.js + Spring Boot + MongoDB example

Overview of Spring MongoDB Reactive example

We will build a Spring Boot, MongoDB, Reactive example – Rest CRUD API for a Tutorial application in that:

  • Each Tutorial has id, title, description, published status.
  • Apis help to create, retrieve, update, delete Tutorials.
  • Apis also support custom finder methods such as find by published status or by title.

These are APIs that we need to provide:

Methods Urls Actions
POST /api/tutorials create new Tutorial
GET /api/tutorials retrieve all Tutorials
GET /api/tutorials/:id retrieve a Tutorial by :id
PUT /api/tutorials/:id update a Tutorial by :id
DELETE /api/tutorials/:id delete a Tutorial by :id
DELETE /api/tutorials delete all Tutorials
GET /api/tutorials/published find all published Tutorials
GET /api/tutorials?title=[keyword] find all Tutorials which title contains keyword


  • Java 11/17
  • Spring Boot 3 (with Spring WebFlux, Spring Data MongoDB Reactive)
  • MongoDB
  • Maven 3.6.1

Project Structure


Let me explain it briefly.

Tutorial data model class.
TutorialRepository is an interface that extends ReactiveMongoRepository to interact with the database. It is autowired in TutorialService.
TutorialService is a service component that uses TutorialRepository and provides CRUD methods and custom finder methods for TutorialController.
TutorialController is a RestController which has request mapping methods for RESTful requests such as: getAllTutorials, createTutorial, updateTutorial, deleteTutorial, findByPublished
– Configuration for Spring Data MongoDB is in application.properties.
schema.sql has SQL statement for initializing database table.
pom.xml contains dependencies for Spring Boot, WebFlux, Spring Data MongoDB Reactive.

Create & Setup Spring Boot project

Use Spring web tool or your development tool (Spring Tool Suite, Eclipse, Intellij) to create a Spring Boot project.

Then open pom.xml and add these dependencies:



Configure the Spring Data MongoDB database

Under src/main/resources folder, open application.properties and write these lines.


The connection URL is set to mongodb://localhost:27017/[database-name], which indicates that you are using a MongoDB database located at localhost on port 27017.

Define Data Model

Our Data model is Tutorial with four fields: id, title, description, published.
In model package, we define Tutorial class.


package com.bezkoder.spring.mongodb.reactive.model;

import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

public class Tutorial {

  private String id;

  private String title;

  private String description;

  private boolean published;

  public Tutorial() {


  public Tutorial(String title, String description, boolean published) {
    this.title = title;
    this.description = description;
    this.published = published;

  // getters and setters

  public String toString() {
    return "Tutorial [id=" + id + ", title=" + title + ", desc=" + description + ", published=" + published + "]";

Create Repository Interface

Let’s create a repository to interact with Tutorials from the MongoDB database.
In repository package, create TutorialRepository interface that extends ReactiveMongoRepository (which extends Spring Data Reactive ReactiveCrudRepository).


package com.bezkoder.spring.mongodb.reactive.repository;

import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import org.springframework.stereotype.Repository;

import com.bezkoder.spring.mongodb.reactive.model.Tutorial;

import reactor.core.publisher.Flux;

public interface TutorialRepository extends ReactiveMongoRepository<Tutorial, String> {
  Flux<Tutorial> findByPublished(boolean published);

  Flux<Tutorial> findByTitleContaining(String title);

Now we can use ReactiveMongoRepository and ReactiveCrudRepository methods: insert() / save(), findById(), findAll(), count(), delete(), deleteById(), deleteAll()… without implementing these methods.

We also define custom finder methods:
findByPublished(): returns all Tutorials with published having value as input published.
findByTitleContaining(): returns all Tutorials which title contains input title.

The implementation is plugged in by Spring Data MongoDB automatically.

Create Data Service

Let’s create a service that uses TutorialRepository to implement CRUD Operations and custom finder methods.
In service package, create TutorialService.


package com.bezkoder.spring.mongodb.reactive.service;

import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.bezkoder.spring.mongodb.reactive.model.Tutorial;
import com.bezkoder.spring.mongodb.reactive.repository.TutorialRepository;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

public class TutorialService {

  TutorialRepository tutorialRepository;

  public Flux<Tutorial> findAll() {
    return tutorialRepository.findAll();

  public Flux<Tutorial> findByTitleContaining(String title) {
    return tutorialRepository.findByTitleContaining(title);

  public Mono<Tutorial> findById(String id) {
    return tutorialRepository.findById(id);

  public Mono<Tutorial> save(Tutorial tutorial) {
    return tutorialRepository.save(tutorial);

  public Mono<Tutorial> update(String id, Tutorial tutorial) {
    return tutorialRepository.findById(id).map(Optional::of).defaultIfEmpty(Optional.empty())
        .flatMap(optionalTutorial -> {
          if (optionalTutorial.isPresent()) {
            return tutorialRepository.save(tutorial);

          return Mono.empty();

  public Mono<Void> deleteById(String id) {
    return tutorialRepository.deleteById(id);

  public Mono<Void> deleteAll() {
    return tutorialRepository.deleteAll();

  public Flux<Tutorial> findByPublished(boolean isPublished) {
    return tutorialRepository.findByPublished(isPublished);

TutorialService class is annotated with @Service to indicate that it is a service component. Spring will create a singleton bean for this class and manage its lifecycle.
– We use @Autowired to inject TutorialRepository bean to local variable.

Create Spring Reactive Rest API Controller

Finally, we create a controller that provides APIs for creating, retrieving, updating, deleting and finding Tutorials.


package com.bezkoder.spring.mongodb.reactive.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import com.bezkoder.spring.mongodb.reactive.model.Tutorial;
import com.bezkoder.spring.mongodb.reactive.service.TutorialService;

import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

@CrossOrigin(origins = "http://localhost:8081")
public class TutorialController {

  TutorialService tutorialService;

  public Flux<Tutorial> getAllTutorials(@RequestParam(required = false) String title) {
    if (title == null)
      return tutorialService.findAll();
      return tutorialService.findByTitleContaining(title);

  public Mono<Tutorial> getTutorialById(@PathVariable("id") String id) {
    return tutorialService.findById(id);

  public Mono<Tutorial> createTutorial(@RequestBody Tutorial tutorial) {
    return tutorialService.save(new Tutorial(tutorial.getTitle(), tutorial.getDescription(), false));

  public Mono<Tutorial> updateTutorial(@PathVariable("id") String id, @RequestBody Tutorial tutorial) {
    return tutorialService.update(id, tutorial);

  public Mono<Void> deleteTutorial(@PathVariable("id") String id) {
    return tutorialService.deleteById(id);

  public Mono<Void> deleteAllTutorials() {
    return tutorialService.deleteAll();

  public Flux<Tutorial> findByPublished() {
    return tutorialService.findByPublished(true);

@CrossOrigin is for configuring allowed origins.
@RestController annotation is used to define a controller and to indicate that the return value of the methods should be be bound to the web response body.
@RequestMapping("/api") declares that all Apis’ url in the controller will start with /api.
– We use @Autowired to inject TutorialService bean to local variable.

Enable WebFlux

We use @EnableWebFlux to enable support for reactive web application using the Spring WebFlux framework.


package com.bezkoder.spring.mongodb.reactive;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.reactive.config.EnableWebFlux;

public class SpringBootMongodbReactiveApplication {

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

Run & Check

Run Spring Boot application with Maven command: mvn spring-boot:run.

Create some Tutorial documents:


Check MongoDB database collection:


Retrieve all Tutorial documents:


Update some Tutorials:


Check MongoDB database collection:


Retrieve a Tutorial document by Id:


Filter published Tutorials:


Find all Tutorial documents which title contains a certain string:


Delete a Tutorial document by id:


Check MongoDB database collection:


Delete all Tutorials and check:


You can also check this Spring Boot App with Client in one of these posts:


Today we’ve built a Spring Data MongoDB Reactive example in Spring Boot successfully using WebFlux Framework for Rest API, Spring Data Reactive MongoDB for CRUD and custom finder methods.

Happy learning! See you again.

Further Reading

Fullstack CRUD App:
Angular 8 + Spring Boot + MongoDB example
Angular 10 + Spring Boot + MongoDB example
Angular 11 + Spring Boot + MongoDB example
Angular 12 + Spring Boot + MongoDB example
Angular 13 + Spring Boot + MongoDB example
Angular 14 + Spring Boot + MongoDB example
Angular 15 + Spring Boot + MongoDB example
React + Spring Boot + MongoDB example
Vue.js + Spring Boot + MongoDB example

More Practice:
Spring Boot + GraphQL + MongoDB example with Spring Data & graphql-java
Spring Boot, MongoDB: JWT Authentication with Spring Security
Spring Boot MongoDB Pagination example with Spring Data

Exception Handling:
Spring Boot @ControllerAdvice & @ExceptionHandler example
@RestControllerAdvice example in Spring Boot

Source Code

You can find the complete source code for this tutorial on Github.