How to customize request validation in Spring boot using Java Bean Validation

Rodolfo Rojas Segura
4 min readDec 6, 2020

Overview

The input validation is a must in any scale application, and very often is a job that takes place in multiple application layers from Web to Persistence tier applying mostly the same set of rules, becoming a time consuming and verbose work. Java bean validation specification gives us the way to apply the validation at any layer using metadata on the bean to apply the validation rules in any layer with not duplicate code.

For this tutorial, I’m going to show you how to use the Java Bean validation in a Spring Boot application and how extends it’s functionality to create a custom Constraint validator and return with a custom error response when the validation on the request body is not meet.

Prerequisites

  • Hibernate Validator is an official Java Bean Validation implementation and will give us the ability to integrate and extends the Validation functionality.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>6.1.6.Final</version>
</dependency>
  • Expression Language is required in order to use the interpolation in the validation messages
<dependency>
<groupId>javax.el</groupId>
<artifactId>el-api</artifactId>
<version>2.2</version>
</dependency>
  • Spring Web
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

Creating Custom Constrains

Java bean validation and some implementors come with a list of built-in constraints that you can take leverage to validate a bean at any application layer, however, there are cases where those constraints don’t fill our validation needs. The Bean Validation specification gives us the ability to create custom constraints that meets our requirements.

Let’s create a custom Constratin annotation that prevents the use of certain first names

  1. The validator uses for this constraint, will perform the actual validation and do some additional work on the generation of the message if needed.

2. This is a required field, used to constraint grouping. This is not needed for this tutorial.

3. This is a required field, used to create the Payload and set the severity level for the constraint, this is not used by this validator.

Validator

  1. The validator should extend from ConstraintValidator.
  2. Initializes the validator with any required data set in the Constraint annotation. this method is guaranteed to be called before any method in the Validator class.
  3. The method performs the actual validation, for sake of simplicity the isValid performs a simple validation checking the value of the field is not contained in the not notAllowValues attribute.

NOTE: Spring scans for all the classes that extend from ConstraintValidator, and load them in the context as validators, also given this we can inject and access other beans as we normally access in other beans.

Using the New Constraint

Here we’re using the custom constraint NotContains to prevent the use of some firstName and LastName values. We can also notice that the mixing of custom and built-in constraints is possible.

we’re also using the message attribute to specify the response message when the attribute is invalid, the message is interpolate using EL (Expression Language) to make reference to some dynamic attributes values such as notAlloweValues in the case of the NotContains constraint.

Validating Request

In order to validate the request body, we just need to tell Spring to do that annotating the request body argument with @Valid. Spring takes leverage of the Java Bean validation through the usage of Hibernate Validator Implementation.

Customizing Invalid Request Response

Spring throws a MethodArgumentNotValidException when an argument is not valid. To customize the endpoint response, we’re going to take leverage of the Spring exception handling capability.

  1. @ExceptionHandler Instructs Spring which exception type should handle.
  2. We’re extracting all the invalid field errors, they contain the validation metadata for each validation that failed for a specific bean attribute.
  3. Creating a map that will be returned as a JSON format containing the endpoint path and an array with the field errors.

DEMO!

Let’s send and invalid request value and will see how our application will respond with a nice and easy to understand error response.

Seeing the response we got, we can notice the Bean Validation is able to track multiple failed validation for multiple bean attributes so we can build rich responses to let an API client what was wrong or even to display those errors in a UI.

With this tutorial, we could see how to add bean validation to our Spring boot application and extend it to fit our special requirements.

Hope you have found this tutorial helpful and you can integrate this technique in your next project. You can find the code for this tutorial on GitHub.

--

--