12
votes

I have a very naive conceptual question here for clarification. In my app I'm currently using JSR 303 Hibernate Validator for validating the domain model with @NotBlank and @NotNull annotations, like checking username, password etc.

public class Admin {

  private Long id;
  @NotBlank(message = "Username should not be null")
  private String username;
  @NotBlank(message = "Username should not be null")
  private String password;
  ...

But for validating the domain logic like existing username, I'm still using Spring's Validator interface

@Component
public class AdminValidator implements Validator {
  ...
  @Override
  public void validate(Object target, Errors errors) {
    Admin admin = (Admin) target;
    if (usernameAlradyExist())){
        errors.rejectValue("username", null, "This user already exist's in the system.");
    }

}

In the controller I'm using both

@RequestMapping(value = "/register", method = RequestMethod.POST)
public String register(@Valid @ModelAttribute("admin") Admin admin, BindingResult bindingResult,) {
    validator.validate(admin, bindingResult);
    if (bindingResult.hasErrors()) {
        return REGISTER_ADMIN.getViewName();

    }

Is it possible just to use Hibernate Validator and not at all use Spring Validator for validating domain logic?

2

2 Answers

18
votes

Yes, You can use JSR validation for your domain logic validation. You need to define custom constraint annotations and define your domain logic validation inside it.
Like
Defining custom constraint annotation UserExistsConstraint

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Constraint(validatedBy=UserExistsConstraintValidator.class)

public @interface UserExistsConstraint {
 String message() default "This user already exist's in the system.";
 Class<!--?-->[] groups() default {};
 Class<!--? extends Payload-->[] payload() default {};
}   

Defining validator for custom annotation.

public class UserExistsConstraintValidator implements ConstraintValidator<UserExistsConstraint, object=""> {

 @Override
 public void initialize(UserExistsConstraint constraint) {

 }

 @Override
 public boolean isValid(Object target, ConstraintValidatorContext context) {
   if (usernameAlradyExist())
   {    
     return false;
   }
   else
   {
     return true; 
   }    
 }
}

Using custom annotation

public class Admin {

  private Long id;
  @NotBlank(message = "Username should not be null")
  @UserExistsConstraint
  private String username;
  @NotBlank(message = "Username should not be null")
  private String password;
  ...
2
votes

If you are configuring Spring MVC with <mvc:annotation-driven/> then it will automatically configure a JSR 303 validator if some JSR 303 validator impl(hibernate-validator for eg) is present in the classpath.

Or if you explicitly want to configure the validator, you can do this:

<bean id="validator"
      class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

This again would look for a JSR 303 implementation and use that as the validator.

You can default it to validate any @Valid form object by registering a global validator this way:

<mvc:annotation-driven validator="validator"/>