Bean Validation in Spring Boot complete example with Custom Validation Annotation

In the previous Spring Boot Controller and Swagger, we have written implementation code for our swagger endpoints now we are going to see how we can validate parameters.

Since the client sends various parameters (header, query, path, request body) in request to our Rest API. we have to ensure that these parameters are valid before we can process the request and send the response.

To do that we don't have to write extra code instead we can use the bean validation in our project which contains pre-defined spring bean annotation to validation parameter.

Today we are going to learn how to use bean validation in our project.

Bean validation 

 

Bean validation is validating the bean(Object) using some constraint annotation in fields, methods, classes. The bean Validator will check the declared constraint on the class whether or not constraint is satisfied if any constraint is not met then it triggers MethodArgumentNotValidException

 

Spring boot will enable bean validation automatically if it finds any JSP implementation on the classpath.


Maven dependencies 

 

Add below dependency for spring boot bean validation using hibernate Validator which is the most used bean validation.

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


Hibernate annotations

 

@Min and @Max ensure the numerical field is only valid when its value is above or below a certain value.

  
@min(0)
@Max(100)
private int mark;

@min(6)
@Max(6)
private int oTP;

@NotBlank is used to ensure the string value is not empty and should contain at least one character.

  
@NotBlank
private String name;
  

@NotNull check annotated field is not null.

  
@NotNull
private GenderEnum gender;

@NotEmpty check annotated field or list is not empty nor null

  
@NotEmpty
private List<Employee> employees;

@Size(min=, max=) is used to ensure annotated element size is between min and max.

  
@Size(min=10,max=10) 
private String mobileNo;

@Pattern(regex=) check the string against the given regular expression.

  
@Pattern(regex= "yyyy-MM-dd HH:mm")
private String joinedDate;
  

@Email check the string is valid mail address below annotation is used to do email validation and not empty on the variable.

  
@Email
@NotEmpty
private String yourMailId;


Validating Bean programmatically

 

By using the Validator class we can validate the object by passing the object to validate method in Validator which will check if constraints are satisfied.

  
package com.employee.example.util;

import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.Validator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.employee.example.model.Employee;

@Component
public class RequestBodyValidator {

  @Autowired
  private Validator validator;

  public boolean validRequestBody(Employee employee) {

    Set constraintViolations = validator.validate(employee);
    if (!constraintViolations.isEmpty()) {
      throw new ConstraintViolationException(constraintViolations);
    }
    return true;
  }
}
  
  

Validating Bean using annotation 

 

we can validate the beans without using the Validator class just by @Validated and @Valid annotations.

 

@Validated is a class-level annotation that supports group validation, used to validate parameters passed to the methods of the class.

@Valid is used in method parameters that need to be validated.

  
public ResponseEntity addEmployee(@Valid @RequestBody Employee employeeDetails)


Creating Custom Validator

 

The @Target annotation is used to tell where this annotation is to be used e.g. field, parameter. If @Target is declared as a parameter it can use in the method parameter.

 

The @Retention annotation tells when the annotation must be available we will runtime so it will be available during JVM runtime.

 

@Constraint annotation tells the class which is going to validate our field and contains the validation logic. it's mentioned by validatedBy attribute. 

 

By default, there will be 3 attributes inside the annotation they are the message(), payload(), and groups().

message() which contains the default message that will be used as an error message in case of an exception.

Creating Custom annotation


we can do custom validation in spring boot by creating custom annotation and validator class.
  
package com.employee.example.util;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.validation.Constraint;
import javax.validation.Payload;

@Target({
  ElementType.FIELD, ElementType.PARAMETER
})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = ContainValueValidator.class)
@Documented
public @interface ContainValue {

  String message() default "value is invalid";

  Class<? > [] groups() default {};

  Class<? extends Payload > [] payload() default {};
}

Creating Validator class

 

We have to create a class and implement the ConstraintValidator interface. This class contains the actual validation logic and override isValid() method.

 

The isValid() method contains the validation logic and returns a Boolean if the value passes the validation logic.

      
package com.employee.example.util;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import org.apache.commons.lang3.StringUtils;

public class ContainValueValidator implements ConstraintValidator {

  @Override
  public boolean isValid(String fieldValue, ConstraintValidatorContext validatorContext) {
    return StringUtils.isNotBlank(fieldValue);
  }
}


If you are facing the below error 

 

javax.validation.ConstraintDeclarationException: HV000151: A method overriding another method must not redefine the parameter constraint configuration

 


It means you have added validation annotation on the subclass method parameters which is not there in superclass method parameters so you have to add the validation annotation on the superclass method.


Validating Request body


we have already added a few hibernate spring validation annotations on our request body so now test them by passing invalid values.


spring boot annotation bean validation @size annotation in hibernate


we have added @Size annotation to a mobile number to check its size is 10 and we have passed invalid value because its size is greater than 10 so our validation gets triggered and causes MethodArgumentNotValidException


Validating Request parameter

let use our custom validation annotation created above in the header parameter(x-requestid) to check whether it's working fine. 


spring boot custom annotation to custom validation for request parameters

if we don't pass any value in x-requestid then it triggers ConstraintViolationException.

view source code is available on gitHub.

Post a Comment

Previous Post Next Post

Recent Posts

Facebook