In this tutorial, I will show you how to validate Request Body using Validation annotations in Spring Boot Rest API.
More Practice:
– Spring Boot custom Validation example
– Spring Boot Login and Registration example
– Spring Boot 3 Rest API CRUD example
– Spring Boot @ControllerAdvice & @ExceptionHandler example
– Spring Boot Unit Test for Rest Controller
– Documentation: Spring Boot Swagger 3 example
– Caching: Spring Boot Redis Cache example
Contents
- Validate Request Body in Spring Boot example
- Project Structure
- Setup Spring Boot project with Validation annotations
- Spring Boot Validation annotations
- Use the Validation annotations
- Spring Boot validate Request Body for nested object
- Validate Request Body
- Handle Request Validation Exception
- Conclusion
- Source Code
- Further Reading
Validate Request Body in Spring Boot example
Data validation is very important. It conforms to the expected format, type, range, and business rules, as well as identify and prevent errors, inconsistencies, and fraud. We will implement Spring Boot validate Request Body for Signup Request payload with following fields:
username
: required and has a size between the specified minimum and maximum.email
: required and valid email format.age
: required and equal or greater than 18.graduationDate
: required and in the past.password
: required and 8 characters long and combination of uppercase letters, lowercase letters, numbers, special characters.address
(nested object): required and its fields are valid.
Here is response if user sends invalid request data:
Validate Request Body for nested object:
And this is example of valid request data:
When we need to perform data validation that cannot be handled by the built-in validation annotations provided by Spring Framework (confirm password matching for example), we can use custom validation to define our own rules and constraints:
Spring Boot custom Validation example
Project Structure
Let me explain it briefly.
– SignupRequest
or AddressDTO
is the payload class (or DTO) that uses the validation annotations.
– UserController
is the Rest Controller that exports API endpoint for receiving SignupRequest
payload.
– ValidationExceptionHandler
handles error when the validation fails.
– pom.xml
contains dependencies for Spring Boot and Spring Validation.
Setup Spring Boot project with Validation annotations
To use Validation annotations in Spring Boot, you need to add the spring-boot-starter-validation dependency to your Maven project’s pom.xml file:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Or Gradle project with build.gradle file:
implementation 'org.springframework.boot:spring-boot-starter-validation:3.0.6'
Spring Boot Validation annotations
Spring provides a wide range of validation options. Here is some Spring Boot Validation annotations that you may need to use for validating request body:
@NotNull
: Marks a field as required and cannot be null.@NotBlank
: Marks a field as required and cannot be blank.@NotEmpty
: Marks a field (including collection, map, or array) as required and cannot be empty.@Size
: Specifies the minimum and/or maximum size of a field.@Min
: Specifies the minimum value of a numeric field.@Max
: Specifies the maximum value of a numeric field.@Email
: Validates that a field is a valid email address.@Pattern
: Specifies a regular expression that a field must match.@Valid
: Indicates that a field should be validated recursively.@AssertTrue
: Validates that a boolean field is true.@AssertFalse
: Validates that a boolean field is false.@DecimalMin
: Specifies the minimum value of a decimal field.@DecimalMax
: Specifies the maximum value of a decimal field.@Digits
: Specifies the number of digits and/or fraction digits for a decimal field.@Positive
: Validates that a numeric field is positive.@PositiveOrZero
: Validates that a numeric field is positive or zero.@Negative
: Validates that a numeric field is negative.@NegativeOrZero
: Validates that a numeric field is negative or zero.@Future
: Validates that a date or time field is in the future.@Past
: Validates that a date or time field is in the past.@URL
: Validates that a field is a valid URL.@Validated
: Indicates that a class or interface should be validated recursively.@Range
: Specifies a range of values for a field.
Use the Validation annotations
Let’s use the Validation annotations on the fields in SignupRequest
class that needs to be validated.
payload/SignupRequest.java
package com.bezkoder.spring.validation.payload;
import java.util.Date;
import org.springframework.format.annotation.DateTimeFormat;
import jakarta.validation.Valid;
import jakarta.validation.constraints.*;
public class SignupRequest {
@NotBlank(message = "The username is required.")
@Size(min = 3, max = 20, message = "The username must be from 3 to 20 characters.")
private String username;
@NotEmpty(message = "The email is required.")
@Email(message = "The email is not a valid email.")
private String email;
@NotNull(message = "The age is required.")
@Min(value = 18, message = "The age must be equal or greater than 18")
private int age;
@NotNull(message = "The graduation date is required.")
@Past(message = "The graduation date must be in the past.")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date graduationDate;
@NotBlank(message = "The password is required.")
@Pattern(regexp = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=!*()]).{8,}$", message = "Password must be 8 characters long and combination of uppercase letters, lowercase letters, numbers, special characters.")
private String password;
@NotBlank(message = "The confirm Password is required.")
private String confirmPassword;
@NotNull(message = "The address is required.")
private AddressDTO address;
// getters and setters
}
We use @Pattern
with regular expression (regexp
) for a strong password:
^
: the start of the string(?=.*\d)
: at least one digit(?=.*[a-z])
: at least one lowercase letter(?=.*[A-Z])
: at least one uppercase letter(?=.*[@#$%^&+=!*()])
: at least one special character.{8,}
: at least 8 characters long$
: the end of the string
Spring Boot validate Request Body for nested object
How about validating address
‘s fields?
We’re gonna check the AddressDTO
class with validation annotations for its fields first.
payload/AddressDTO.java
package com.bezkoder.spring.validation.payload;
import jakarta.validation.constraints.NotBlank;
public class AddressDTO {
@NotBlank(message = "[Address] The city is required.")
private String city;
@NotBlank(message = "[Address] The street name is required.")
private String street;
// getters and setters
}
Then just add @Valid
annotation to address
field inside its parent class.
payload/SignupRequest.java
import jakarta.validation.Valid;
import jakarta.validation.constraints.*;
public class SignupRequest {
// other fields
@Valid
@NotNull(message = "The address is required.")
private AddressDTO address;
// getters and setters
}
Validate Request Body
Now we need to add the @Valid
annotation to the field or method parameter we want to validate.
controller/UserController.java
package com.bezkoder.spring.validation.controller;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import com.bezkoder.spring.validation.payload.SignupRequest;
import jakarta.validation.Valid;
@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/api/auth")
public class UserController {
@PostMapping("/signup")
public ResponseEntity<?> registerUser(@Valid @RequestBody SignupRequest signUpRequest) {
return new ResponseEntity<>("User registered Successfully!", HttpStatus.OK);
}
}
Handle Request Validation Exception
When the validation fails, Spring will throw an exception of type MethodArgumentNotValidException
and we need to handle it in ValidationExceptionHandler
class.
exception/ValidationExceptionHandler.java
package com.bezkoder.spring.validation.exception;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import jakarta.servlet.http.HttpServletRequest;
@ControllerAdvice
public class ValidationExceptionHandler {
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<?> notValid(MethodArgumentNotValidException ex, HttpServletRequest request) {
List<String> errors = new ArrayList<>();
ex.getAllErrors().forEach(err -> errors.add(err.getDefaultMessage()));
Map<String, List<String>> result = new HashMap<>();
result.put("errors", errors);
return new ResponseEntity<>(result, HttpStatus.BAD_REQUEST);
}
}
For more detail about the technique, please visit:
Spring Boot @ControllerAdvice & @ExceptionHandler example
Conclusion
Today we’ve known step by step to use validation annotations to validate Request Body in Spring Boot Rest API example.
When we need to perform data validation that cannot be handled by the built-in validation annotations provided by Spring Framework (for example, password and confirm password matching), we can use custom validation to define our own rules and constraints:
Spring Boot custom Validation example
Happy Learning! See you again.
Source Code
You can find the complete source code for this tutorial on Github.
Further Reading
Fullstack CRUD App:
– Spring Boot Thymeleaf example
– Vue + Spring Boot example
– Angular 8 + Spring Boot example
– Angular 10 + Spring Boot example
– Angular 11 + Spring Boot example
– Angular 12 + Spring Boot example
– Angular 13 + Spring Boot example
– Angular 14 + Spring Boot example
– Angular 15 + Spring Boot example
– React + Spring Boot example
More Practice:
– Spring Boot Rest API example: CRUD Application
– Spring Boot Login and Registration example
– Spring Boot Rest XML example
– Spring Boot Multipart File upload example
– Spring Boot Pagination and Sorting example
– Documentation: Spring Boot + Swagger 3 example (with OpenAPI 3)
– Caching: Spring Boot Redis Cache example