Spring Rest API Request Body Validation

Introduction:

Before processing the request body validation is must. We can validate the request body by using hibernate and Javax Validation dependency.

Maven Dependencies

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.1.5.Final</version>
</dependency>

After adding dependency bean validation is automatically enabled by JSR-303 implementation. because bean validator dependencies available at classpath.

Bean Validation Annotations:

Add the bean validation annotations in Request Body DTO or Model classes.

Student.java

import javax.validation.constraints.NotEmpty;

public class Student {
    @NotEmpty(message = "Name must not be empty")
    private String name;

    @NotNull(message = "Code must not be null")
    private String code;
}
  1. @NotEmpty denotes annotated field must not be null nor empty
  2. @NotNNull denotes annotated field not null but can be empty.
  3. @Size validates that the annotated property value has a size between the attributes min and max; can be applied to String, Collection, Map, and array properties.
  4. @Email validates that the annotated property is a valid email address.
  5. @NotBlank can be applied only to text values and validates that the property is not null or whitespace.

Add @Valid annotation:

The @Valid annotation is used to specify the rest controller to be validated. The spring boot application validates the method before it is called.

@RestController
@Validated
@RequestMapping("/student")
public class StudentController {

    @Autowired
    private StudentService service;

    @PostMapping("/saveStudent")
    public Student saveStudent(@Valid @RequestBody Student student) {
        return service.save(student);
    }
}

Handle Constraint Violation Exception:

In case any validation failures spring will throw a Runtime Exception. we can handle it and return a meaningful json response using ExceptionHandler annotation.

@ControllerAdvice
@ResponseBody
public class CustomExceptionHandler extends ResponseEntityExceptionHandler
{
    @ExceptionHandler(ConstraintViolationException.class)
    public final ResponseEntity<ErrorResponse> handleConstraintViolation(
                                            ConstraintViolationException ex,
                                            WebRequest request)
    {
        List<String> details = ex.getConstraintViolations()
                                    .parallelStream()
                                    .map(e -> e.getMessage())
                                    .collect(Collectors.toList());

        ErrorResponse error = new ErrorResponse(BAD_REQUEST, details);
        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }
}