DEV Community

Anshul Bansal
Anshul Bansal

Posted on • Edited on

Create RESTful APIs using Spring Boot + Mongo DB

1. Overview

Nowadays, a web application is often separated into two components - frontend and backend.

With the growing popularity of frontend technologies like Angular and React, backend features are often exposed as the RESTful APIs.

In this tutorial, we'll create RESTful APIs using Spring Boot. At the same time, we'll use Spring Data MongoDB to provide persistence support in our App by connecting to MongoDB.

2. Prerequisites

We need a set of standard tools:

  • Java 8 or later
  • Build Tool (Maven or Gradle)
  • IDE (IntelliJ or Eclipse)

We'll use a combination of Java 8, Gradle and IntelliJ for our implementation.

To quickly create the Spring Boot application, we'll use Spring Initializr. Also, we'll install and configure Mongo DB.

3. Application

Let's create RESTful APIs for a user registration app.
For simplicity, we'll just add features to perform CRUD (Create, Read, Update and Delete) operations.

Once the Spring Boot app is created, we'll create the application.properties file with MongoDB configuration details:

spring.data.mongodb.database=springboot_mongo_db
Enter fullscreen mode Exit fullscreen mode

3.1. Entity

First, we'll create the User entity with basic properties like firstName, lastName, and email:

@Getter
@Setter
public class User {
    @Id
    private String id;

    private String firstName;
    private String lastName;
    private String email;
    private String phone;
    private String address;
}
Enter fullscreen mode Exit fullscreen mode

Here, we've used @Id annotation to define the identifier.

At the same time, we've used @Getter and @Setter annotations provided by the Project Lombok to create getters/setters automatically.

3.2. Repository

Then, we'll create the UserRepository interface that provides basic operations on the database using Spring Data provided MongoRepository:

public interface UserRepository extends MongoRepository<User, String> {
}
Enter fullscreen mode Exit fullscreen mode

3.3. Service

Next, we'll create a service class that provides the business logic for basic CRUD operations.

For this, let's create the Registration interface to define the abstraction:

public interface Registration<ID, USER> {
    USER registerUser(USER user) throws Exception;

    USER getUser(ID userId) throws Exception;

    USER updateUser(USER user) throws Exception;

    void deleteUser(ID userId) throws Exception;
}
Enter fullscreen mode Exit fullscreen mode

Then, we'll create the RegistrationImpl class to implement the Registration interface:

@Service
public class RegistrationImpl implements Registration<String, User> {
    @Autowired
    private UserRepository userRepository;

    @Override
    public User registerUser(User user) throws Exception {
        user = userRepository.save(user);
        return user;
    }

    @Override
    public User getUser(String userId) throws Exception {
        User user = userRepository.findById(userId);
        return user;
    }

    public List<User> getAllUser() throws Exception {
        List<User> users = userRepository.findAll();
        return users;
    }

    @Override
    public User updateUser(User user) throws Exception {
        user = userRepository.save(user);
        return user;
    }

    @Override
    public void deleteUser(String userId) throws Exception {
        if (userId == null) {
            throw new Exception("user id is null");
        } else {
            userRepository.delete(userId);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Note that we've used @Service annotation to declare the RegistrationImpl class as a service for Spring Boot. Also, we've used @Autowired annotation to inject the UserRepository dependency.

3.4. Controller

Now that we've got entity, repository and service ready, we'll create the RegistrationController class to expose the APIs:

@RestController
public class RegistrationController {
    @Autowired
    private RegistrationImpl registrationImpl;
}
Enter fullscreen mode Exit fullscreen mode

Here, we've used @RestController annotation to declare it as a RESTful API controller.

At first, we'll add a method registerUser to register the user (CREATE):

@PostMapping(path = "/registerUser")
public ResponseEntity registerUser(@RequestBody User user) throws Exception {
    HashMap<String, Object> resp = new HashMap<>();
    registrationImpl.registerUser(user);
    resp.put("user", user);
    return new ResponseEntity<>(resp, HttpStatus.OK);
}
Enter fullscreen mode Exit fullscreen mode

Voila, we're ready with our first RESTful API to register the user.

Let's try it using the following curl command:

curl -X POST "http://localhost:8080/registerUser" -H "Content-Type: application/json" \
-d '{"email": "xyz@email.com", "firstName": "norman", "lastName": "lewis", "phone": "90909090"}'

Enter fullscreen mode Exit fullscreen mode

Then, let's add a method getUser to search the user by id (READ):

@GetMapping("/getUser" )
public ResponseEntity getUser(@RequestParam("id") String id) throws Exception {
    User user = registrationImpl.getUser(id);
    return new ResponseEntity<>(user, HttpStatus.OK);
}
Enter fullscreen mode Exit fullscreen mode

So, we can use the curl to read the user:

curl -X GET "http://localhost:8080/getUser?id=5e0a0a393844b64a1548c4d9"
Enter fullscreen mode Exit fullscreen mode

Similarly, we can define a method getAllUser to fetch all the users:

@GetMapping("/getAllUser" )
public ResponseEntity getAllUser() throws Exception {
    List<User> users = registrationImpl.getAllUser();
    return new ResponseEntity<>(users, HttpStatus.OK);
}
Enter fullscreen mode Exit fullscreen mode

Then, we'll add a method updateUser to update the user (UPDATE):

@PutMapping(path = "/updateUser")
public ResponseEntity updateUser(@RequestParam("id") String id, @RequestBody User user) 
throws Exception {
    HashMap<String, Object> resp = new HashMap<>();
    registrationImpl.updateUser(user);
    resp.put("user", user);
    return new ResponseEntity<>(resp, HttpStatus.OK);
}
Enter fullscreen mode Exit fullscreen mode

Last, let's add a method deleteUser to delete the user (DELETE):

@DeleteMapping("/deleteUser")
public ResponseEntity deleteUser(@RequestParam("id") String id) throws Exception {
    registrationImpl.deleteUser(id);
    HashMap<String,String> resp = new HashMap<>();
    resp.put("message", "User is successfully deleted");
    return new ResponseEntity<>(resp, HttpStatus.OK);
}
Enter fullscreen mode Exit fullscreen mode

3.5. Validation

Next, we'll add the feature of bean validations to our APIs using hibernate-validator.

First, we'll add the dependency to the build.gradle:

compile group: 'org.hibernate', name: 'hibernate-validator', version: '5.0.0.Final'
Enter fullscreen mode Exit fullscreen mode

Then, we'll add a few annotations like @NotNull and @Email to the User entity.

public class User {
    // ...

    @NotNull(message = "First Name is mandatory")
    private String firstName;

    @NotNull(message = "Last Name is mandatory")
    private String lastName;

    @NotNull(message = "Email is mandatory")
    @Email(message = "Not valid email")
    @Indexed(unique=true)
    private String email;

    @NotNull(message = "Phone Number is mandatory")
    private String phone;    
}
Enter fullscreen mode Exit fullscreen mode

Next, we'll use the ValidatingMongoEventListener to register as a bean in the main class - Application:

@SpringBootApplication
public class Application {
    @Bean
    public ValidatingMongoEventListener validatingMongoEventListener() {
        return new ValidatingMongoEventListener(validator());
    }

    @Bean
    public LocalValidatorFactoryBean validator() {
        return new LocalValidatorFactoryBean();
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}
Enter fullscreen mode Exit fullscreen mode

Last, we'll modify the registerUser method in the RegistrationController to validate the User object:

@PostMapping(path = "/registerUser")
public ResponseEntity registerUser(@RequestBody User user) throws Exception {
    HashMap<String, Object> resp = new HashMap<>();
    try {
        registrationImpl.registerUser(user);
    } catch (ConstraintViolationException e) {
        HashMap<String, String> messages = new HashMap<>();
        e.getConstraintViolations().stream().forEach(constraintViolation -> {
            messages.put(
                    constraintViolation.getPropertyPath().toString(),
                    constraintViolation.getMessage());
        });
        resp.put("error", true);
        resp.put("messages", messages);
    }
    resp.put("user", user);
    return new ResponseEntity<>(resp, HttpStatus.OK);
}
Enter fullscreen mode Exit fullscreen mode

That's it! We're ready to examine the validation:

curl -X POST "http://localhost:8080/registerUser" -H "Content-Type: application/json" -d '{"email": "xyz@email.com"}'
Enter fullscreen mode Exit fullscreen mode

Here, we've not provided firstName, lastName, and phone. So, the response will be:

{"messages":{"firstName":"First Name is mandatory","lastName":"Last Name is mandatory","phone":"Phone Number is mandatory"},"error":true,"user":{"id":null,"firstName":null,"lastName":null,"email":"xyz12@email.com","phone":null,"address":null}}
Enter fullscreen mode Exit fullscreen mode

3.6. Swagger Integration

So far, we've used curl to request our APIs. Now, we'll integrate Swagger 2 documentation for our APIs using Springfox.

All we need is to add the Springfox dependencies in build.gradle:

compile "io.springfox:springfox-swagger2:2.9.2"
compile 'io.springfox:springfox-swagger-ui:2.9.2'
Enter fullscreen mode Exit fullscreen mode

Then, we'll annotate the main class with @EnableSwagger2 annotation:

@EnableSwagger2
@SpringBootApplication
public class Application {

    // ...
}
Enter fullscreen mode Exit fullscreen mode

That's it! Our API specifications are ready and are accessible at http://localhost:8080/swagger-ui.html.

4. Conclusion

In this tutorial, we've created RESTful APIs for the User registration App using SpringBoot and Spring Data Mongo DB.
Also, we've used Project Lombok to reduce the boiler-plate code and Springfox APIs for Swagger 2 documentation.

The entire code implementations are available over on Github

Please let me know your thoughts on it!
Thanks for reading.

Top comments (0)