Sunday, February 17, 2013

SpringMVC Form Errors Tag and Validator Interface

In this article, we will discuss about <form:errors> tag and the Spring's Validator Interface

1. Create a new validator

Spring provides us a Validator interface that we can use to validate objects

For example, we implement a new validator to validate this User object
public class User {

    private String firstName;
    
    private String lastName;
    
    private String password;
    
    private String repassword;

....

}

The implementation of a validator looks like that

public class UserValidator implements Validator {

    @Override
    public boolean supports(Class<?> clazz) {
        return User.class.isAssignableFrom(clazz);
    }

    @Override
    public void validate(Object obj, Errors errors) {
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "required.firstName", "Firstname is required.");
        ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "required.lastName", "LastName is required.");
        
        User user = (User) obj;
        if (!user.getPassword().equals(user.getRepassword())) {
            errors.rejectValue("password", "notmatch.password");
        }
    }
}
Tip: To reject a field value, we can do like that:
errors.rejectValue("password", "notmatch.password");
The first argument is the field name, the second is the message.

2. Configure validator in controller


We need only 2 steps to enable the validation feature in controller:
  • Implement the function initBinder, this function will be invoked by framework when it binds data.
  • Add a binding result attribute to the action which you want to apply the validation, the <form:errors> tag looks at this attribute when it renders the error messages on form
In my controller:
@Autowired
@Qualifier("userValidator")
private UserValidator validator;

@InitBinder
protected void initBinder(WebDataBinder binder) {
    binder.setValidator(this.validator);
}

@RequestMapping(value = "/modifyUser", method = RequestMethod.POST)
public ModelAndView updateUser(@ModelAttribute("user") User user, BindingResult bindingResult) {
    validator.validate(user, bindingResult);
    if (bindingResult.hasErrors()) {
        // show errors
        return new ModelAndView("modifyUser", "user", user);
    } else {
        // success
        return new ModelAndView("viewUser", "user", user);
    }    
}

  • The Spring version used in this example is 3.x
  • The validator will be passed to controller automatically through @Autowired annotation
  • In initBinder function, we tell to Spring that to validate data of this controller, please use the UserValidator
  • At line 11, we have a new attribute with type BindingResult, this attribute will contain our binding result, and used by form:errors tag

3. Prepare the JSP

To show the errors of a field, we use this structure: <form:errors path="firstName"/>

To show the errors of all field, we set the value of path to * <form:errors path="*" />

For example:
<tr>
    <td><form:label path="firstname=">First Name<td>
    <td>
        <form:input path="firstName" />
        <form:errors path="firstName" class="errors" />
    </td>
</tr> 

References:
Source code:
  • For the demonstration, please download source code from HERE
  • My repository on Github

No comments:

Post a Comment