Spring Frameworks (2 Part Series)
1 Swagger-2 API documentation for Spring App using Springfox
2 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.
Spring Frameworks (2 Part Series)
1 Swagger-2 API documentation for Spring App using Springfox
2 Create RESTful APIs using Spring Boot + Mongo DB
暂无评论内容