Validating Request Input in Spring Boot

In this tutorial, you will learn how to validate request input in Spring Boot applications. Input validation is important to ensure the integrity and security of data being passed to an API.

his guide will cover the annotation-based validation approach using Spring's built-in annotations such as @NotNull, @NotEmpty, and @Valid. We will learn how to annotate request models and utilize these annotations to enforce constraints on input fields.

Follow these steps to validate request input in Spring Boot:

  1. Add Spring Boot Starter Validation dependency to your Spring Boot project.
  2. For Maven

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-validation</artifactId>
        <version>3.1.1</version>
    </dependency>
    

    For Gradle

    implementation group: 'org.springframework.boot', name: 'spring-boot-starter-validation', version: '3.1.1'

  3. Create a model class to represent the user input received in a request.

  4. import jakarta.validation.Valid;
    import jakarta.validation.constraints.Email;
    import jakarta.validation.constraints.Max;
    import jakarta.validation.constraints.Min;
    import jakarta.validation.constraints.NotEmpty;
    import jakarta.validation.constraints.NotNull;
    import jakarta.validation.constraints.Size;
    
    public class UserRequestDto {
    
      @NotEmpty(message = "firstName is required")
      private String firstName;
    
      @NotEmpty(message = "lastName is required")
      private String lastName;
    
      @NotNull(message = "age is required")
      @Min(value = 18, message = "age must be at least 18")
      @Max(value = 80, message = "age must be less than or equal to 80")
      private int age;
    
      @NotEmpty(message = "email is required")
      @Email(message = "Invalid email format")
      private String email;
    
      @Size(min = 6, max = 20, message = "Password must be between 6 and 20 characters")
      private String password;
    
      @Valid
      @NotNull(message = "address is required")
      private Address address;
    
      // Getter and Setter methods
    
      public String getFirstName() {
        return firstName;
      }
    
      public void setFirstName(String firstName) {
        this.firstName = firstName;
      }
    
      public String getLastName() {
         return lastName;
      }
    
      public void setLastName(String lastName) {
        this.lastName = lastName;
      }
    
      public int getAge() {
         return age;
      }
    
      public void setAge(int age) {
         this.age = age;
      }
    
      public String getEmail() {
         return email;
      }
    
      public void setEmail(String email) {
         this.email = email;
      }
    
      public String getPassword() {
         return password;
      }
    
      public void setPassword(String password) {
         this.password = password;
      }
     
      public Address getAddress() {
         return address;
      }
    
      public void setAddress(Address address) {
         this.address = address;
      }
    
    }

    import jakarta.validation.constraints.NotEmpty;
    
    public class Address {
    
      @NotEmpty(message = "Street is required")
      private String street;
    	
      @NotEmpty(message = "City is required")
      private String city;
    	
      @NotEmpty(message = "Country is required")
      private String country;
    	
      // Getter Setters methods here
    }

    Here, each field is annotated with validation annotations to enforce specific rules. For example, @NotEmpty ensures that the fields are not empty, @NotNull ensures that the fields are not null, @Min and @Max specify the range for the age field, @Email validates the email format, and @Size restricts the length of the password field. The @Valid annotation is used to validate the address field by delegating the validation to the associated Address object.


  5. Create your controller. Annotate it with @Validated annotation. Also annotate the method parameter with @Valid as shown in the code below:

  6. import org.springframework.validation.annotation.Validated;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.PostMapping;
    import org.springframework.web.bind.annotation.PutMapping;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    import com.example.dto.UserRequestDto;
    import jakarta.validation.Valid;
    
    @Validated
    @RestController
    @RequestMapping(path = "/users")
    public class UserController {
    
      @PostMapping(path = "/register")
      public void registerNewUser(@Valid @RequestBody UserRequestDto userRequestDto) {
    
      }
    
      @PutMapping(path = "/{userId}/update")
      public void updateUser(@PathVariable(name = "userId", required = true) String userId,	@Valid @RequestBody UserRequestDto userRequestDto) {
    
      }
    
    }

    The @Validated annotation is used to enable method-level validation in combination with the @Valid annotation. The @Validated annotation instructs Spring to validate the method's arguments or return values according to the validation constraints defined on those parameters.


  7. Disable sending stack trace in validation error response by adding the following line in application.properties configuration file:

  8. server.error.include-stacktrace=never

    This configuration property server.error.include-stacktrace in Spring Boot is used to control whether stack traces are included in error responses returned by the server. When you set server.error.include-stacktrace to never, it means that stack traces will not be included in the error responses. This is useful in production environments where you typically don't want to expose detailed error information, including stack traces, to users or clients.