Validate Request Body in Spring Boot

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
Spring Boot + GraphQL example


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:

spring-boot-validate-request-body

Validate Request Body for nested object:

spring-boot-validate-request-body-nested-object

And this is example of valid request data:

spring-boot-validate-request-body-success

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

spring-boot-validate-request-body-project

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
Angular 16 + 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
Spring Boot + GraphQL example