Spring - Creating Custom Validation Constraint Annotation

[Last Updated: Jul 1, 2018]

The custom constraint annotations (JSR 303/349/380) can be created as specified by the JavaBean validation specification (check out example here).

In spring if we register LocalValidatorFactoryBean to bootstrap javax.validation.ValidatorFactory then custom ConstraintValidator classes are loaded as Spring Bean. That means we can have benefit of Spring's dependency injection in validator classes.


Creating custom constraint annotation

package com.logicbig.example;

import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;

@Target({ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER,
@Constraint(validatedBy = LanguageValidator.class)
public @interface Language {

  String message() default "must be a valid language display name," +
          " found: ${validatedValue}";

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

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

ConstraintValidator implementation

package com.logicbig.example;

import org.springframework.beans.factory.annotation.Autowired;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;

public class LanguageValidator implements ConstraintValidator<Language, String> {
  private LanguageProvider languageProvider;

  public void initialize(Language constraintAnnotation) {

  public boolean isValid(String value, ConstraintValidatorContext context) {
      if (value == null) {
          return false;
      return languageProvider.getLanguages()

As seen above we are injecting other spring bean in the validator class.

LanguageProvider bean

public interface LanguageProvider {

    List<String> getLanguages();

    public static class DefaultLanguageProvider implements LanguageProvider {

        public List<String> getLanguages() {
            List<String> languageList = new ArrayList<>();
            for (Locale locale : Locale.getAvailableLocales()) {
            return languageList;

Example POJO and Client Bean

public class Book {
  private String name;
  private String language;
public class ClientBean {
  private Validator validator;

  public void run(){
      Book book = new Book();
      book.setName("Alien Explorer");

      Set<ConstraintViolation<Book>> violations = validator.validate(book);
      for (ConstraintViolation<Book> violation : violations) {
          String message = violation.getMessage();
          Path path = violation.getPropertyPath();
          System.err.println(path+" "+message);

JavaConfig and main class

public class AppConfig {
  public Validator validatorFactory() {
      return new LocalValidatorFactoryBean();

  public static void main(String[] args) {
      AnnotationConfigApplicationContext context =
              new AnnotationConfigApplicationContext(

      ClientBean bean = context.getBean(ClientBean.class);;
language must be a valid language display name, found: Englis

Example Project

Dependencies and Technologies Used:

  • spring-context 5.0.7.RELEASE: Spring Context.
  • hibernate-validator 6.0.10.Final Hibernate Validator Engine - Relocation Artifact
  • javax.el 3.0.1-b09 Expression Language 3.0
  • JDK 10
  • Maven 3.5.4

Creating constraint annotation in Spring Core Select All Download
  • spring-custom-validation-constraints
    • src
      • main
        • java
          • com
            • logicbig
              • example

    See Also