Spring Boot CRUD Application Example with MongoDB

Spring Boot CRUD MongoDB

Introduction

In this post, I will show how we can use Spring Boot to build a simple CRUD REST application example with MongoDB. I know your first question will be what is MongoDB?

 

What is MongoDB?

MongoDB is a NoSQL document database. In this database, records are documents which behave a lot like JSON objects. So it is mostly key-value pair.

The key advantages of using MongoDB as a database are:

  • MongoDB is a schema-less document database. One collection holds different documents.
  • The structure of a single object is clear.
  • No complex joins
  • Deep query ability.
  • Easy to scale-out

Here are the few reasons why you would use MongoDB or similar NoSQL databases in an enterprise applications:

  • If you need faster data retrieval in JSON style
  • Easy to add index on an attribute
  • For Sharding purposes – Sharding is the process of storing data records across multiple machines. You will usually partition this data according to some criteria while storing across multiple machines.
  • Fast in-place updates
  • Easier to query

Prerequisites

To create this sample application, you need:

  • Spring Boot (version 2.4.1)
  • MongoDB
  • Gradle
  • Java

Spring Boot CRUD Application

As part of this post, I will be building a REST CRUD application. This includes

  • A book library – We will be creating a collection library in our MongoDB database.
  • A library where we will be storing the books by author
  • A user can call the REST API to retrieve the book by author
  • A user can call the REST API to retrieve all the books from the library
  • POST – /v1/mongodbapp/books – To add a book to library
  • GET – /v1/mongodbapp/books – To retrieve all the books from the library
  • GET – /v1/mongodbapp/books/id – To retrieve a specific book
  • DELETE – /v1/mongodbapp/books/id – To remove a book from the library

How to use Spring Boot CRUD with MongoDB

To get started with creating this application, we will be using gradle to handle our dependencies and build the application. Add the following the dependencies in our Spring Boot application:

implementation 'org.springframework.boot:spring-boot-starter-data-mongodb'
implementation 'org.springframework.boot:spring-boot-starter-web'

MongoDB Connection Properties

Once we have these dependencies, we will be able to connect to mongo db database. But we still need to add where our database is located. We will add the required properties in our application.properties file as below:

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

This will allow us to connect to MongoDB database running at host localhost on the port 27017 and the database schema is library.

Define Data Model

As part of the library, we will need books. So our main data object is Book. The data model for this will include the book title, author, and ISBN. This will be as follows:

package com.betterjavacode.mongodbdemo.mongodbapp.models;

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



@Document(collection = "books")
public class Book
{
    @Id
    private String id;

    private String title;
    private String author;
    private String isbn;

    public Book()
    {

    }

    public Book(String title, String author, String isbn)
    {
        this.title = title;
        this.author = author;
        this.isbn = isbn;
    }

    public String getId ()
    {
        return id;
    }

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

    public String getTitle ()
    {
        return title;
    }

    public void setTitle (String title)
    {
        this.title = title;
    }

    public String getAuthor ()
    {
        return author;
    }

    public void setAuthor (String author)
    {
        this.author = author;
    }

    public String getIsbn ()
    {
        return isbn;
    }

    public void setIsbn (String isbn)
    {
        this.isbn = isbn;
    }
}

Since we are using MongoDB, @Document annotation overrides the collection books.

Add Repository Interface

We will need a repository interface to fetch, save or delete our book object.  In repositories package, we will add BookRepository interface


package com.betterjavacode.mongodbdemo.mongodbapp.repositories;

import com.betterjavacode.mongodbdemo.mongodbapp.models.Book;
import org.springframework.data.mongodb.repository.MongoRepository;

import java.util.List;

public interface BookRepository extends MongoRepository<Book, String>
{
    List findByTitleContaining(String title);
    List findByAuthor(String name);
}

This repository has two methods to fetch list of books by a title or by author name.

Add Spring REST API Controller

Now to make our application REST CRUD, we will add a REST controller. This controller will contain POST, PUT, GET and DELETE APIs.


package com.betterjavacode.mongodbdemo.mongodbapp.controller;

import com.betterjavacode.mongodbdemo.mongodbapp.models.Book;
import com.betterjavacode.mongodbdemo.mongodbapp.repositories.BookRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

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

@CrossOrigin("http://localhost:8080")
@RestController
@RequestMapping("/v1/mongodbapp")
public class BookController
{
    @Autowired
    BookRepository bookRepository;

    @GetMapping("/books")
    public ResponseEntity<List> getAllBooks(@RequestParam(required = false) String bookTitle)
    {
        try
        {
            List listOfBooks = new ArrayList<>();
            if(bookTitle == null || bookTitle.isEmpty())
            {
                bookRepository.findAll().forEach(listOfBooks::add);
            }
            else
            {
                bookRepository.findByTitleContaining(bookTitle).forEach(listOfBooks::add);
            }

            if(listOfBooks.isEmpty())
            {
                return new ResponseEntity<>(HttpStatus.NO_CONTENT);
            }

            return new ResponseEntity<>(listOfBooks, HttpStatus.OK);
        }
        catch (Exception e)
        {
            return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @GetMapping("/books/{id}")
    public ResponseEntity getBookById(@PathVariable("id") String id)
    {
        try
        {
            Optional bookOptional = bookRepository.findById(id);

            return new ResponseEntity<>(bookOptional.get(), HttpStatus.OK);
        }
        catch (Exception e)
        {
            return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("/books")
    public ResponseEntity addABookToLibrary(@RequestBody Book book)
    {
        try
        {
            Book createdBook = bookRepository.save(new Book(book.getTitle(), book.getAuthor(),
                    book.getIsbn()));
            return new ResponseEntity<>(createdBook, HttpStatus.CREATED);
        }
        catch (Exception e)
        {
            return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PutMapping("/books/{id}")
    public ResponseEntity updateABook(@PathVariable("id") String id, @RequestBody Book book)
    {
        Optional bookOptional = bookRepository.findById(id);

        if(bookOptional.isPresent())
        {
            Book updatedBook = bookOptional.get();
            updatedBook.setTitle(book.getTitle());
            updatedBook.setAuthor(book.getAuthor());
            updatedBook.setIsbn(book.getIsbn());
            return new ResponseEntity<>(bookRepository.save(updatedBook), HttpStatus.OK);
        }
        else
        {
            return new ResponseEntity<>(HttpStatus.NOT_FOUND);
        }
    }

    @DeleteMapping("/books/{id}")
    public ResponseEntity deleteABook(@PathVariable("id") String id)
    {
        try
        {
            bookRepository.deleteById(id);
            return new ResponseEntity<>(HttpStatus.NO_CONTENT);
        }
        catch (Exception e)
        {
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}

BookController is our REST Controller class. It includes

  • @RestController – to mark this as a REST controller.
  • @CrossOrigin – This annotation allows cross-origin resource sharing (CORS). This will add CORS access control headers in the REST response. These headers are necessary because it allows servers to specify not only who can access the resources, but how they can be accessed.
  • We have added different methods – addABookToLibrary adds the book to database, getAllBooks retrieves the book from database.

The Complete Demo

Now we have added our REST controller, repository methods, we will build and run this application. As part of the demo, I will use POSTMAN to access APIs.

You can build the application from command line or from the code editor you are using. I prefer command line, so I already built the application. Once built, you can run the program as follows:

java -jar mongodbapp-0.0.1-SNAPSHOT.jar.

Let’s use POSTMAN to add books to our library.

As shown above, we added a book and the response shows added book in the database.

The following API is a GET API to get all the books from the database.

Now to show delete the book from library, we will use DELETE API.

The code for this sample application is available in my github repository.

If you want to see this data in the MongoDB database, you can access MongoDB compass tool and access the collection books in the library database.

Conclusion

In this post, I showed how to use Spring Boot to create REST API while using MongoDB database. The approach we used is very similar to what we have while using a regular SQL database. There are some changes that we have to add while using NoSQL database. If you find this post useful or have any questions that I can help you with, you can subscribe to my blog here. I recently pre-launched my book – Simplifying Spring Security which will be released on 7th February 2021. You can preorder it here.

References

1. Spring Boot MongoDB References – MongoDB Reference

2. Spring Boot Blog – Blog