Search code examples
springbean-validationservice-layerspring-validator

How to combine JSR-303 and Spring Validator class in a service layer?


I have some model class

public class Account {

    @Email
    private String email;

    @NotNull
    private String rule;
}

and spring-validator

public class AccountValidator implements Validator {

    @Override
    public boolean supports(Class aClass) {
        return Account.class.equals(aClass);
    }

    @Override
    public void validate(Object obj, Errors errors) {
        Account account = (Account) obj;
        ValidationUtils.rejectIfEmpty(errors, "email", "email.required");
        ValidationUtils.rejectIfEmpty(errors, "rule", "rule.required");

        complexValidateRule(account.getRule(), errors);
    }

    private void complexValidateRule(String rule, Errors errors) {
        // ...
    }
}

I run in my service

AccountValidator validator = new AccountValidator();
Errors errors = new BeanPropertyBindingResult(account, "account");
validator.validate(account, errors);

Can I add to my validation process constraints @Email, @NotNull (JSR-303) and don't describe these rules in AccountValidator?

I know how works @Valid in spring-controllers, but what's about service layer? Is it possible? How to do such kind of validation in a proper way? May I should use Hibernate Validator?


Solution

  • Spring provides an Adapter to merge both validation APIs. See the current Spring JavaDoc for more information.

    An possible implementation would be

    public class AccountValidator implements Validator {
    
      private final SpringValidatorAdapter validator;
    
      public AccountValidator(SpringValidatorAdapter validator) {
          super();
          this.validator = validator;
      }
    
      @Override
      public boolean supports(Class aClass) {
          return Account.class.equals(aClass);
      }
    
      @Override
      public void validate(Object obj, Errors errors) {
    
          //jsr303
          validator.validate(obj, errors);
    
          //custom rules
          Account account = (Account) obj;
          complexValidateRule(account.getRule(), errors);
      }
    
      private void complexValidateRule(String rule, Errors errors) {
          // ...
      }
    }