Create RESTful APIs using Spring Boot + Mongo DB
Anshul Bansal
Posted on December 30, 2019
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
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;
}
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> {
}
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;
}
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);
}
}
}
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;
}
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);
}
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"}'
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);
}
So, we can use the curl to read the user:
curl -X GET "http://localhost:8080/getUser?id=5e0a0a393844b64a1548c4d9"
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);
}
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);
}
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);
}
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'
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;
}
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);
}
}
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);
}
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"}'
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}}
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'
Then, we'll annotate the main class with @EnableSwagger2 annotation:
@EnableSwagger2
@SpringBootApplication
public class Application {
// ...
}
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.
Posted on December 30, 2019
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.