Spring MVC Custom Validator Example
June 28, 2019
On this page, we will learn Spring MVC custom Validator with @InitBinder and WebDataBinder. Validator is a Spring interface using which we create our custom validators. WebDataBinder binds custom validators. To do this, we create a method in controller and annotate it with @InitBinder which plays the role to identify WebDataBinder method in our controller. registerCustomEditor() is a method of WebDataBinder which configures PropertyEditor like CustomDateEditor. CustomDateEditor binds the date web request parameter to attribute in JavaBean. Here in our example we are creating a JavaBean with username, password, email and date of birth of a user. For the demo we are creating two custom validator classes. In first one, we will validate username and password. The second validator will validate email of the user. Now find the complete example.
Demo Project Structure in Eclipse
Before starting the demo, we should see what are the classes we are using in our demo and how they are kept in eclipse. We can download the complete source code by the link given at the bottom. Find the project structure in eclipse.Validator
org.springframework.validation.Validator is an interface which has two methodsboolean supports(Class<?> clazz) : Checks whether the instance of class passed as argument can be validated or not.
void validate(Object target, Errors errors) : If supports() method returns true, then the target object is validated. Errors.rejectValue() method registers the error message with a field name.
To create our Validator class, we need to implement spring Validator interface and define the validations as required. Find the validator classes being used in our demo.
UserValidator.java
package com.concretepage.validators; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; import com.concretepage.User; @Component public class UserValidator implements Validator { @Override public boolean supports(Class<?> clazz) { return User.class.isAssignableFrom(clazz); } @Override public void validate(Object target, Errors errors) { User user = (User)target; ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "","Username is empty"); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "", "Password is empty"); if (user.getName().length()<5) { errors.rejectValue("name","", "Username length is less than 5"); } } }
EmailValidator.java
package com.concretepage.validators; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; import com.concretepage.User; @Component public class EmailValidator implements Validator { @Override public boolean supports(Class<?> clazz) { return User.class.isAssignableFrom(clazz); } @Override public void validate(Object target, Errors errors) { User user = (User)target; ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "","Email is empty"); if (!user.getEmail().contains("@")) { errors.rejectValue("email","", "Email is not valid."); } } }
package com.concretepage; import java.util.Date; public class User { private String name; private String password; private String email; private Date dob; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getDob() { return dob; } public void setDob(Date dob) { this.dob = dob; } }
@InitBinder Annotation
@InitBinder palys the role to identify the methods which initialize the WebDataBinder. The @InitBinder method supports many arguments as by @RequestMapping methods. @InitBinder method does not support command or form arguments. Mostly used argument is WebDataBinder in @InitBinder method.WebDataBinder
org.springframework.web.bind.WebDataBinder is a DataBinder that binds request parameter to JavaBean objects. It provides methods to assign our validator classes. Using addValidators() and setValidator() methods, we can assign our validators instances.registerCustomEditor()
registerCustomEditor() is a method of WebDataBinder using which we configure custom PropertyEditor for the given type and property.CustomDateEditor
CustomDateEditor is a PropertyEditor which we are using in our demo. CustomDateEditor binds the date value from web request to a JavaBean Date property for a given date format. Find the code snippet.@InitBinder public void dataBinding(WebDataBinder binder) { binder.addValidators(userValidator, emailValidator); SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); dateFormat.setLenient(false); binder.registerCustomEditor(Date.class, "dob", new CustomDateEditor(dateFormat, true)); }
Create Controller and Views
Find the controller and view.MyWorldController.java
package com.concretepage; import java.text.SimpleDateFormat; import java.util.Date; import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.propertyeditors.CustomDateEditor; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.validation.BindingResult; import org.springframework.web.bind.WebDataBinder; import org.springframework.web.bind.annotation.InitBinder; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import com.concretepage.validators.EmailValidator; import com.concretepage.validators.UserValidator; @Controller @RequestMapping("/myworld") public class MyWorldController { @Autowired private UserValidator userValidator; @Autowired private EmailValidator emailValidator; @RequestMapping(value="signup", method = RequestMethod.GET) public ModelAndView user(){ return new ModelAndView("user","user",new User()); } @InitBinder public void dataBinding(WebDataBinder binder) { binder.addValidators(userValidator, emailValidator); SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy"); dateFormat.setLenient(false); binder.registerCustomEditor(Date.class, "dob", new CustomDateEditor(dateFormat, true)); } @RequestMapping(value="save", method = RequestMethod.POST) public String createUser(@ModelAttribute("user") @Valid User user,BindingResult result, ModelMap model) { if(result.hasErrors()) { return "user"; } System.out.println("Name:"+ user.getName()); System.out.println("Email:"+ user.getEmail()); System.out.println("Date of Birth:"+ user.getDob()); model.addAttribute("msg", "Welcome to My World!"); return "success"; } }
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%> <html> <head><title>Create User</title></head> <body> <table> <form:form action="save" method="post" commandName="user"> <tr> <td>User Name:</td> <td><form:input path="name"/> </td> <td> <form:errors path="name" cssStyle="color: red;"/></td> </tr> <tr> <td> Password :</td> <td><form:input path="password"/> </td> <td> <form:errors path="password" cssStyle="color: red;"/> </td> </tr> <tr> <td> Email :</td> <td><form:input path="email"/> </td> <td> <form:errors path="email" cssStyle="color: red;"/> </td> </tr> <tr> <td> Date of Birth :</td> <td><form:input path="dob"/> </td> <td> <form:errors path="dob" cssStyle="color: red;"/> </td> </tr> <tr> <td colspan=3> <input type="submit"> </td> </form:form> </table> </body> </html>
Output
To check the output, deploy the code in tomcat 8 and run the URL.http://localhost:8080/concretepage-1/myworld/signup
After submitting, we will get the validation failure.
Now we are done. Happy Learning!