Spring MVC Validation - Tuong-Nguyen/Spring GitHub Wiki

Use validators

Create a validator

  • Create a class implement Validator interface
  • Override supports and validate method
    • supports: check if a specific instance of a class can be validate from this validator'
    • validate: define the rules
  • EX:
    @Override
    public boolean supports(Class<?> clazz) {
        return Account.class.equals(clazz);
    }

    @Override
    public void validate(Object target, Errors errors) {
        Account account = (Account) target;
        String regex = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$";
        Pattern p = Pattern.compile(regex);
        Matcher m = p.matcher(account.getPass());
        if(!m.matches()){
            errors.rejectValue("pass","account.pass", "The password must contain at least one lower case letter, one upper case letter, one digit and one of these special characters ~!@#$%^&*()_+");
        }
    }
  • On that example the validation class support for Account class.
  • The validate method validate for the password.

Indicate the controller use the validator

  • Init a binder
  • Add the validator to it
  • When use @InitBinder the other validation will be Ignore (hibernate validation annotation, javax validation annotation....)
@InitBinder
public void initBinder(WebDataBinder binder) {
    binder.addValidators(new MyValidator());
}
  • if you have more than 1 Validator class in binder the and when you use @Valid the binder will find in list to get the validation class that support for the model class.

Check valid a model attribute

  • Import validation-api library
  • Use @Valid annotation before @ModelAttribute parameter and add Errors as parameter
public String saveModel(@Valid @ModelAttribute MyModel myModel, Errors errors) {
    if (!erros.hasErrors()){
        // validated!
    } else {
        // not validated!
    }
}

Use Hibernate validators

  • Import hibernate-validator library
  • Use annotations as:
    • Field-level constraints
    @NotNull
    private String manufacturer;
    
    • Property-level constraints
    @NotNull
    public String getManufacturer() {
        return manufacturer;
    }
    
    • Class-level constraints
    @ValidPassengerCount
    public class Car { ... }
    

Hibernate Validator 5.x is the reference implementation Bean Validation 1.1

Annotations list

Annotation Description
@AssertFalse The annotated element must be a Boolean type and be false.
@AssertTrue The annotated element must be a Boolean type and be true.
@DecimalMax The annotated element must be a number whose value is less than or equal to a given BigDecimalString value.
@DecimalMin The annotated element must be a number whose value is greater than or equal to a given BigDecimalString value.
@Digits The annotated element must be a number whose value has a specified number of digits.
@Future The value of the annotated element must be a date in the future.
@Max The annotated element must be a number whose value is less than or equal to a given value.
@Min The annotated element must be a number whose value is greater than or equal to a given value.
@NotNull The value of the annotated element must not be null.
@Null The value of the annotated element must be null.
@Past The value of the annotated element must be a date in the past.
@Pattern The value of the annotated element must match a given regular expression.
@Size The value of the annotated element must be either a String, a collection, or an array whose length fits within the given range.

Note:

The Hibernate Validation Annotation not work:

If the hibernate validation annotation not work you must add the com.faster.xml:classmate and org.jboss.logging » jboss-logging libraries to your project because the hibernate validation is compiled dependencies on com.faster.xml:classmate, javax.validation » validation-api and org.jboss.logging » jboss-logging.

Making the validation object and validation annotation work together:

  • Don't use @InitBindder
  • Create the validation object and user validate() function.
@RequestMapping(value = "/register/", method = RequestMethod.POST)
public String register(@Valid @ModelAttribute("account") Account account, BindingResult result, HttpServletRequest request, SessionStatus status) {
        new AccountValidator().validate(account, result); //use with validate annotation
        if(result.hasErrors()){
            return "account/register";
        }
  • The BindingResult result parameter must follow the @Valid | @Validated parameter
@RequestMapping(value = "/register/", method = RequestMethod.POST)
public String register(@Valid @ModelAttribute("account") Account account, BindingResult result,...)