Welcome to the course "Advanced RESTful Techniques in Spring Boot." In your previous courses, you've covered Spring basics such as Inversion of Control (IoC), Dependency Injection (DI), and managing beans. You also learned how to create simple RESTful applications with CRUD endpoints. This course will take you a step further by exploring advanced topics like request body validation, error handling, pagination, and handling request and response headers. In this lesson, we'll focus on body validation.
Imagine you’re developing a check-in form for an airline application. The airline industry is highly regulated, and missing or incorrect information can lead to delays at the check-in counter. Therefore, users must provide their name, surname, age, and must confirm the accuracy of this information by selecting a checkbox.
Here's an example of a valid request body:
JSON1{ 2 "firstName": "John", 3 "lastName": "Doe", 4 "age": 27, 5 "termsAndConditionsAccepted": true 6}
And here's an example of an invalid request body:
JSON1{ 2 "firstName": "", // empty names are not allowed 3 "lastName": "Doe", 4 "age": 27, 5 "termsAndConditionsAccepted": false // falsy values are not allowed 6}
To ensure the integrity and accuracy of the data, various validation approaches can be employed:
-
Client-Side Validation: Here, the frontend application (e.g., built with React) checks the required fields before sending an HTTP request. This approach provides a more responsive user experience since errors are caught instantly. However, it is not foolproof as users can still bypass it by making direct HTTP requests using tools like CLI. Additionally, certain validation scenarios, such as verifying a coupon code against a database, cannot be handled solely on the client side.
-
Server-Side Validation: In this approach, the frontend sends the request regardless of the validation status, and the backend handles the validation logic. While this ensures a higher level of security and accuracy, it introduces a delay as users have to wait for the server response to see validation errors.
-
Combined Validation: This method uses both client-side and server-side validation, offering the best of both worlds. It provides immediate feedback to users and ensures the data’s integrity and security.
To add validation functionality to your ToDo List application, you’ll first need to include a specific dependency in your build.gradle
file. This dependency allows you to use validation annotations in your project:
Groovy1dependencies { 2 // Other dependencies... 3 4 implementation 'org.springframework.boot:spring-boot-starter-validation' 5}
Adding this dependency ensures that Spring Boot can handle and support validation functionalities.
Next, let's create a Plain Old Java Object (POJO) that represents our data model. We can specify validation rules using annotations provided by the jakarta.validation.constraints
package.
Java1package com.codesignal; 2 3import jakarta.validation.constraints.NotBlank; 4import jakarta.validation.constraints.Size; 5 6public class TodoItem { 7 8 @NotBlank(message = "Title is mandatory") 9 @Size(min = 3, message = "Title must be at least 3 characters") 10 private String title; 11 12 private boolean completed; 13 14 // Getters and Setters 15 public String getTitle() { 16 return title; 17 } 18 19 public void setTitle(String title) { 20 this.title = title; 21 } 22 23 public boolean isCompleted() { 24 return completed; 25 } 26 27 public void setCompleted(boolean completed) { 28 this.completed = completed; 29 } 30}
In this example, @NotBlank
ensures that the title is not null and contains at least one non-whitespace character, while @Size(min = 3)
ensures that the title is at least 3 characters long. By using these annotations, Spring Boot will automatically validate the fields based on the specified criteria.
To enable validation in your Spring Boot controller, you can use the @Valid
annotation. This will ensure that the incoming request body is validated according to the rules specified in the POJO. Validation annotations are generally applied to HTTP methods that modify data, such as POST
, PUT
, and PATCH
, since these methods typically involve submitting data that needs to be validated.
Java1package com.codesignal; 2 3import org.springframework.web.bind.annotation.*; 4 5import jakarta.validation.Valid; 6 7@RestController 8public class TodoController { 9 10 private final TodoRepository todoRepository; 11 12 public TodoController(TodoRepository todoRepository) { 13 this.todoRepository = todoRepository; 14 } 15 16 @PostMapping("/todo") 17 public String addTodo(@Valid @RequestBody TodoItem todoItem) { 18 // Assuming todoRepository is correctly set up with proper configuration 19 todoRepository.save(todoItem); 20 return "Todo added!"; 21 } 22}
In this code snippet, the @Valid
annotation on the todoItem
parameter ensures that the TodoItem
object is validated before it is processed by the addTodo
method.
There are several other useful annotations provided by the jakarta.validation.constraints
package. Here are a few:
@Min(value)
: Ensures that a numeric field is greater than or equal to the specified value.@Max(value)
: Ensures that a numeric field is less than or equal to the specified value.@Email
: Validates that a string is a well-formed email address.@Pattern(regexp)
: Validates that a string matches the specified regular expression.@Future
: Ensures that a date field is in the future.@Past
: Ensures that a date field is in the past.
These annotations provide a wide range of validation options to help you ensure data integrity.
In this lesson, you learned about the importance of data validation on both the frontend and backend, how to enable validation functionality in a Spring Boot application by adding necessary dependencies, defining validation rules using annotations in a POJO, and applying validation to an endpoint using the @Valid
annotation. This sets the stage for practical exercises that will help you reinforce these concepts and prepare you for more advanced topics in upcoming lessons.