Spring Boot MongoDB CRUD REST API

In this Post, we’re gonna build a Spring Boot + MongoDB CRUD Rest API example. This project is the same as the previous spring boot + mysql rest api project the only difference is the database connection to the mongoDB. You’ll Know:

  • Run MongoDB using docker compose.
  • How to configure Spring Data, to work with Mongo Database
  • Build a REST API — from Scratch

Before starting I made the steps in making spring boot crud as follows:

  • Install Mongo DB using docker compose
  • Initiate the spring boot project
  • Add the required jar / dependencies to the spring boot project
  • Configuration for Spring Datasource
  • Create data model
  • Create repository
  • Create service
  • Create controller
  • Testing CRUD Rest API

We will build a Spring Boot + Mongo DB + Rest CRUD Rest API for a Book application in that:

  • In this project we will create a library system by just creating a simple table, namely book.
  • Each Book has id, title, edition, author, publisher,copies.
  • Apis help to create, retrieve, retrieve detail, update, delete Book.

These are APIs that we need to provide:

MethodsUrlsActions
POST/api/book/add/Create new Book
GET/api/bookRetrieve all Book
GET/api/book/:idRetrieve detail Book by :id
PUT/api/book/:idUpdate Book by :id
DELETE/api/book/:idDelete Book by :id

Technology

  • Java 11
  • Spring Boot (with Spring Web MVC, Spring Data JPA)
  • MongoDB
  • Maven
  • Docker

1.Install MYSQL using docker compose

Before configuring mongodb and mongoclient with docker compose you have to install docker and docker compose first. If it is installed, we can start mongodb and mongoclient configuration with docker compose.

version: "3.3"

services:
    # create mongodb docker 
    mongodb:
      image: mongo:latest
      container_name: mongodb
      environment:
        MONGO_INITDB_ROOT_USERNAME: root
        MONGO_INITDB_ROOT_PASSWORD: rootpassword
      ports:
        - 27017:27017
      volumes:
        - .dbmongodb:/var/lib/lib/mongodb
      networks:
        - mongodb_net
        
    # create mongoclient docker 
    mongoclient:
      image: mongoclient/mongoclient:latest
      container_name: mongoclient
      hostname: mongoclient
      depends_on:
        - mongodb
      networks:
        - mongodb_net
      ports:
        - 3300:3000

networks:
  mongodb_net:
    driver: bridge
      

And run docker in background just type on terminal

docker-compose up -d

2.Initiate the spring boot project

To Create spring boot project, Open the Spring initializr https://start.spring.io.

Initiate the spring boot project

3.Add the required jar / dependencies to the spring boot project

Add Dependencies for Spring Boot and MonogDB in pom.xml

<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-data-mongodb</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-web</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>
</dependencies>

4.Configuration for Spring Datasource & JPA properties

Add Configuration for Spring Datasource and Spring JPA properties in application.properties

spring.data.mongodb.uri=mongodb://root:rootpassword@localhost:27017/test_db

server.name=springboot-mongodb-crud
server.port=8888
server.servlet.context-path=/api

5.Create data model

model/Book.java

Book class corresponds to entity and table Book.

package com.lemoncode21.springbootmongodbcrud.model;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;

import java.util.UUID;

@Document(collection  = "book")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class Book {

    @Id
    private String id;
    private String title;
    private String edition;
    private String publisher;
    private Integer copies;
}

6.Create repository

repository/BookRepository.java

BookRepository is an interface extends MongoRepository, will be autowired in BookServiceImpl for implementing repository methods and custom finder methods.

package com.lemoncode21.springbootmongodbcrud.repository;

import com.lemoncode21.springbootmongodbcrud.model.Book;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface BookRepository extends MongoRepository<Book,String> {
}

7.Create service

service/BookService.java

BookService

package com.lemoncode21.springbootmongodbcrud.service;

import com.lemoncode21.springbootmongodbcrud.model.Book;

import java.util.List;
import java.util.Optional;

public interface BookService{

    List<Book> retrieve();

    Optional<Book> retrieveDetail(String id);

    void  save(Book book);

    void update(Book book,String id);

    void delete(String id);
}

service/Implementation/BookServiceImplementation.java

Implementation

package com.lemoncode21.springbootmongodbcrud.service.Implementation;

import com.lemoncode21.springbootmongodbcrud.model.Book;
import com.lemoncode21.springbootmongodbcrud.repository.BookRepository;
import com.lemoncode21.springbootmongodbcrud.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

@Service
public class BookServiceImplementation implements BookService {

    @Autowired
    BookRepository bookRepository;


    @Override
    public List<Book> retrieve() {
        return this.bookRepository.findAll();
    }

    @Override
    public Optional<Book> retrieveDetail(String id) {
        return this.bookRepository.findById(id);
    }

    @Override
    public void save(Book book) {
        book.setId(String.valueOf(UUID.randomUUID()));
        this.bookRepository.save(book);
    }

    @Override
    public void update(Book book,String id) {
        Optional<Book> bookData = this.bookRepository.findById(id);
        if(bookData.isEmpty()){
            System.out.print("Book id not found");
        }

        bookData.get().setPublisher(book.getPublisher());
        bookData.get().setTitle(book.getTitle());
        bookData.get().setCopies(book.getCopies());
        bookData.get().setEdition(book.getEdition());
        this.bookRepository.save(bookData.get());
    }

    @Override
    public void delete(String id) {
        this.bookRepository.deleteById(id);
    }
}

8. Create controller

BookController is a REST Controller which has request mapping methods for RESTful requests such as: getAll, getDetail, create, update, delete Book. Before build controller, I Add ResponseHandler class for handler response controller.

response/ResponseHandler.java

package com.lemoncode21.springbootmongodbcrud.response;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@JsonInclude(JsonInclude.Include.NON_NULL)
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class ResponseHandler<T> {

    @JsonProperty("status")
    private String status;
    @JsonProperty("message")
    private String message;
    @JsonProperty("data")
    private T data;

    public ResponseHandler(String status, String message) {
        this.status = status;
        this.message = message;
    }
}

controller/BookController.java

package com.lemoncode21.springbootmongodbcrud.controller;

import com.lemoncode21.springbootmongodbcrud.model.Book;
import com.lemoncode21.springbootmongodbcrud.response.ResponseHandler;
import com.lemoncode21.springbootmongodbcrud.service.BookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;
import java.util.UUID;

@RestController
@RequestMapping("/book")
public class BookController {

    @Autowired
    BookService bookService;

    @PostMapping("/add")
    public ResponseHandler add(@RequestBody Book book){
        try {
            this.bookService.save(book);
            return new ResponseHandler(HttpStatus.OK.toString(),"Success saved data!");
        }catch (Exception e){
            return new ResponseHandler(HttpStatus.MULTI_STATUS.toString(),e.getMessage());
        }
    }

    @GetMapping
    public ResponseHandler getAll(){
        try {
            List<Book> bookList = this.bookService.retrieve();
            return new ResponseHandler(HttpStatus.OK.toString(),"Success retrieve data!",bookList);
        }catch (Exception e){
            return new ResponseHandler(HttpStatus.MULTI_STATUS.toString(),e.getMessage());
        }
    }

    @GetMapping(value = "/{id}")
    public ResponseHandler getDetail(@PathVariable("id")String id){
        try {
            Optional<Book> book = this.bookService.retrieveDetail(id);
            return new ResponseHandler(HttpStatus.OK.toString(),"Success retrieve detail data!",book);
        }catch (Exception e){
            return new ResponseHandler(HttpStatus.MULTI_STATUS.toString(),e.getMessage());
        }
    }

    @PutMapping(value = "/{id}")
    public  ResponseHandler update(@PathVariable("id")String id,@RequestBody Book book){
        try {
            this.bookService.update(book,id);
            return new ResponseHandler(HttpStatus.OK.toString(),"Success update data!");
        }catch (Exception e){
            return new ResponseHandler(HttpStatus.MULTI_STATUS.toString(),e.getMessage());
        }
    }

    @DeleteMapping(value = "/{id}")
    public ResponseHandler delete(@PathVariable("id")String id){
        try {
            this.bookService.delete(id);
            return new ResponseHandler(HttpStatus.OK.toString(),"Success delete data!");
        }catch (Exception e){
            return new ResponseHandler(HttpStatus.MULTI_STATUS.toString(),e.getMessage());
        }
    }
}

9.Testing CRUD Rest API

Time to test CRUD Rest API

Add Book

Retrieve All Book

Retrieve By Id Book

Update Book

Delete Book

Leave a Reply

Your email address will not be published. Required fields are marked *