Spring Boot and MongoDB Sequence ID Generator

Welcome, in this tutorial, we will see how to generate a mongodb sequence id in a spring boot application.

1. Introduction

Before going further in this tutorial, we will look at the common terminology such as introduction to Spring Boot and mongodb.

1.1 Spring Boot

1.2 MongoDB

1.2.1 Why MongoDB?

Let us go ahead with the tutorial implementation but before going any further I’m assuming that you’re aware of the Spring boot basics.

2. Spring Boot and MongoDB Sequence ID Generator

2.1 Application Pre-requisite

To start with this tutorial, I am hoping that you have the mongodb and mongodb graphical interface (i.e. mongo-express) up and running in your localhost environment. For easy setup, I have these both up and running on the docker environment. You can execute the below script using the docker-compose command to get both containers running on docker in minutes. If you’re doing it for the first time the mongodb and mongo-express docker images will be downloaded from the docker hub.

docker-compose.yml

services:
  mongodb:
    container_name: mongodb
    image: mongo
    environment:
      MONGO_INITDB_DATABASE: employees
    ports:
      - '27017:27017'
  express:
    container_name: express
    image: mongo-express
    ports:
      - '9001:8081'
    environment:
      - ME_CONFIG_MONGODB_SERVER=mongodb
      - ME_CONFIG_MONGODB_PORT=27017
      - ME_CONFIG_MONGODB_ENABLE_ADMIN=true
    depends_on:
      - mongodb
version: '3'

If everything goes well the containers would be started successfully as shown in Fig. 1. You can use the docker ps -a command to confirm that both the containers are started successfully. For further information on docker basics, you can navigate to this tutorial.

Fig.1: MongoDB and Mongo-express containers on Docker

Navigate to the following URL – localhost:9001 to confirm that the mongo-express is running and can bind with the mongodb successfully.

Fig. 2: Mongo express

2.2 Tools Used for Spring boot application and Project Structure

We are using Eclipse Kepler SR2, JDK 8, and Maven. In case you’re confused about where you should create the corresponding files or folder, let us review the project structure of the spring boot application.

Fig. 3: Project structure

Let us start building the application!

3. Creating a Spring Boot application

Below are the steps involved in developing the application.

3.1 Maven Dependency

Here, we specify the dependency for the Spring boot (Web and MongoDB), Lombok, and Java faker (for generating the mock data). Maven will automatically resolve the other dependencies. The updated file will have the following code.

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         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.4.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.springboot.mongodb</groupId>
    <artifactId>SpringbootandMongodbSequenceId</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringbootandMongodbSequenceId</name>
    <description>Springboot and Mongodb SequenceId generator</description>
    <properties>
        <java.version>1.8</java.version>
    </properties>
    <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>com.github.javafaker</groupId>
            <artifactId>javafaker</artifactId>
            <version>1.0.2</version>
        </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>
    <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>

3.2 Application properties file

Create a new properties file at the location: SpringbootandMongodbSequenceId/src/main/resources/ and add the following code to it. Here we will define the application and mongo database configuration.

application.properties

# application configuration
server.port=9500
spring.application.name=springboot-mongodb-sequence-id-example
# spring boot and mongodb configuration
# db name
spring.data.mongodb.database=employees
# hostname
spring.data.mongodb.host=localhost
# port number
spring.data.mongodb.port=27017
# sql query logging
logging.level.org.springframework.data.mongodb.core.MongoTemplate=debug

3.3 Java Classes

Let us write the important java class(es) involved in this application. For brevity, we will skip the following classes –

3.3.1 Implementation/Main class

Add the following code to the main class to bootstrap the application from the main method. Always remember, the entry point of the spring boot application is the class containing @SpringBootApplication annotation and the static main method.

SpringbootandMongodbSequenceIdApplication.java

package com.springboot.mongodb;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// Lombok annotation for logger
@Slf4j
// Spring annotation
@SpringBootApplication
public class SpringbootandMongodbSequenceIdApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringbootandMongodbSequenceIdApplication.class, args);
        log.info("Springboot and mongodb sequence id generator started successfully.");
    }
}

3.3.2 Database sequence model class

Add the following code to the sequence model class which will help store the sequence number in the mongodb collection (named – db_sequence).

DbSequence.java

package com.springboot.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;
import org.springframework.data.mongodb.core.mapping.Field;
import org.springframework.stereotype.Component;
// Mongodb annotation
// marks a class for the domain object that we want to persist in the db
@Document(collection = "db_sequence")
// Lombok annotations
@Data
@NoArgsConstructor
@AllArgsConstructor
// Spring stereotype annotation
@Component
public class DbSequence {
    @Id
    String id;
    // describes the field name as it will be represented in mongodb bson document
    // offers the name to be different than the field name of the class
    @Field("sequence_number")
    int sequence;
}

3.3.3 Database sequence generator class

Add the following code to the service class which helps to generate the next id sequence for the employee record.

DbSequenceGenr.java

package com.springboot.mongodb.service;
import com.springboot.mongodb.entity.DbSequence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoOperations;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import java.util.Objects;
@Service
public class DbSequenceGenr {
    @Autowired
    private MongoOperations operations;
    public int getNextSequence(final String sequenceName) {
        // get the sequence number
        final Query q = new Query(Criteria.where("id").is(sequenceName));
        // increment the sequence number by 1
        // "sequence" should match the attribute value specified in DbSequence.java class.
        final Update u = new Update().inc("sequence", 1);
        // modify in document
        final DbSequence counter = operations.findAndModify(q, u,
                FindAndModifyOptions.options().returnNew(true).upsert(true), DbSequence.class);
        return !Objects.isNull(counter) ? counter.getSequence() : 1;
    }
}

3.3.4 Default bootstrap class

Add the following code to the bootstrap class which helps to store the employee data into the mongodb collection (named – employees) at the application bootstrap.

DefaultEmployeeLoader.java

package com.springboot.mongodb.bootstrap;
import com.github.javafaker.Faker;
import com.springboot.mongodb.entity.Employee;
import com.springboot.mongodb.service.DbSequenceGenr;
import com.springboot.mongodb.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import java.util.Random;
// Lombok annotation for logger
@Slf4j
// Spring annotation
@Component
public class DefaultEmployeesLoader implements CommandLineRunner {
    private static final String[] GENDER = {"Male", "Female", "Transgender"};
    private static final Random RANDOM = new Random();
    @Autowired
    private EmployeeService service;
    @Autowired
    private DbSequenceGenr sequenceGenr;
    @Autowired
    private Faker faker;
    // will add the dummy employee data in the mongodb collection
    // will be executed automatically on the application startup
    @Override
    public void run(String... args) {
        if (service.getCollectionCount() == 0) {
            log.info("Saving default employees in the collection");
            for (int i=0; i<11; i++) {
                persist();
            }
        } else {
            log.info("Default employees are already present in the mongo collection");
        }
    }
    // calls the service layer method which in turn calls the dao layer method
    // to save the employee record in the mongodb collection
    private void persist() {
        final Employee e = createEmployee();
        service.save(e);
    }
    // using the faker library to create some mock data for the employee model
    private Employee createEmployee() {
        final String firstName = faker.name().firstName();
        final String lastName = faker.name().lastName();
        final String gender = GENDER[RANDOM.nextInt(GENDER.length)];
        final String email = firstName.toLowerCase() + "." + lastName.toLowerCase() + "@automation.com";
        return Employee.builder()
                .id(sequenceGenr.getNextSequence(Employee.SEQUENCE_NUMBER))
                .firstName(firstName)
                .lastName(lastName)
                .gender(gender)
                .email(email)
                .phoneNumber(faker.phoneNumber().cellPhone())
                .homeAddress(faker.address().fullAddress())
                .build();
    }
}

3.3.5 Controller class

Add the following code to the controller class. The class has two methods that will fetch the employee’s information from the employees collection.

EmployeeCtrl.java

package com.springboot.mongodb.controller;
import com.springboot.mongodb.entity.Employee;
import com.springboot.mongodb.service.EmployeeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
// Lombok annotation for logger
@Slf4j
// Spring annotations
@RestController
@RequestMapping("/api")
public class EmployeeCtrl {
    @Autowired
    private EmployeeService service;
    // Url - http://localhost:9500/api/employees
    @GetMapping("/employees")
    public ResponseEntity<List<Employee>> getAll() {
        log.info("Fetching all employees from the db");
        return new ResponseEntity<>(service.getEmployees(), HttpStatus.OK);
    }
    // Url - http://localhost:9500/api/employees/gender/Female
    // where gender type can be - Male, Female, or Transgender
    @GetMapping("/employees/gender/{type}")
    public ResponseEntity<List<Employee>> getEmployeesByGender(@PathVariable("type") String type) {
        log.info("Fetching all employees from the db where gender type = {}", type);
        return new ResponseEntity<>(service.getEmployeesByGender(type), HttpStatus.OK);
    }
}

4. Run the Application

To execute the application, right-click on the SpringbootandMongodbSequenceIdApplication.java class, Run As -> Java Application.

Fig. 4: Run the Application

5. Project Demo

When the application is started, the default data will be pushed to the mongodb collection (named – employees). You can hit the following URL – http://localhost:9001/ to confirm that the default data has been successfully persisted in the mongodb collection.

Fig. 5: Default data persisted successfully in employees collection

You are free to use postman or any other tool of your choice to make a post request to the endpoint.

Generate access token endpoint

-- HTTP GET endpoint url –
http://localhost:9500/api/employees
-- HTTP GET endpoint url (to fetch employees by gender)--
http://localhost:9500/api/employees/gender/Female

That is all for this tutorial and I hope the article served you whatever you were looking for. Happy Learning and do not forget to share!

6. Summary

In this section, you learned,

You can download the sample application as an Eclipse project in the Downloads section.

7. Download the Project

This was an example of implementing MongoDB sequence id generator in a Spring Boot application.

Download
You can download the full source code of this example here: Spring Boot and MongoDB Sequence ID Generator
Exit mobile version