In this example, I will show you how to build a custom validator for User
model object. This validator is custom implementation of Validator
interface.
Spring MVC supports validation by means of a validator object that implements the Validator
interface. I will write the below validator code in this example to check if the required form fields are filled.
package com.roytuts.spring.mvc.validators; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; import com.roytuts.spring.mvc.models.User; @Component public class UserValidator implements Validator { @Override public boolean supports(Class<?> claszz) { return User.class.isAssignableFrom(claszz); } @Override public void validate(Object target, Errors errors) { ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "error.name"); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "error.email"); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "address", "error.address"); } }
In this validator, utility methods such as rejectIfEmptyOrWhitespace()
and rejectIfEmpty()
in the ValidationUtils
class are used to validate the required form fields. If any of these form fields is empty, these methods will create a field error and bind it to the field. The second argument of these methods is the property name of the User object, while the third is the error code which is defined in the messages.properties file.
Many times validation errors are not specific to fields. For example name should be greater than three characters long in length. In this case, we can use the reject()
method to create an object error to be bound to the User
object, not to a field.
e.g. errors.reject(“invalid.nameLength”, “Name should be at least 3 characters in length.”);
Now I will move to the actual example.
Prerequisites
The following configurations are required in order to run the application
Eclipse Kepler
JDK 1.8
Tomcat 8
Have maven 3 installed and configured
Spring 4 dependencies in pom.xml
Now we will see the below steps how to create a maven based project in Eclipse
Step 1. Create a maven based web project in Eclipse
Go to File -> New -> Other. On popup window under Maven select Maven Project. Then click on Next. Select the workspace location – either default or browse the location. Click on Next. Now in next window select the row as highlighted from the below list of archtypes and click on Next button.
maven-arctype-webapp
Now enter the required fields (Group Id, Artifact Id) as shown below
Group Id : com.roytuts
Artifact Id : spring-mvc
Step 2. Modify the pom.xml file as shown below.
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.roytuts</groupId> <artifactId>spring-mvc</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>spring-mvc Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <java.version>1.8</java.version> <spring.version>4.3.0.RELEASE</spring.version> </properties> <dependencies> <!-- Spring --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <!-- Servlet --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet.jsp</groupId> <artifactId>javax.servlet.jsp-api</artifactId> <version>2.3.1</version> <scope>provided</scope> </dependency> <!-- jstl --> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies> <build> <finalName>spring-mvc</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>${java.version}</source> <target>${java.version}</target> </configuration> </plugin> </plugins> </build> </project>
Step 3. Now modify the web.xml file with below source code
<?xml version="1.0" encoding="UTF-8"?> <web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"> <!-- dispatcher servlet acts as a front controller for each request/response --> <servlet> <servlet-name>spring-mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <!-- load Spring controllers while dispatcher servlet loads --> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:controllers.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- map URL suffix as .html --> <servlet-mapping> <servlet-name>spring-mvc</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> </web-app>
Step 4. Create controllers.xml file under src/main/resources directory with the below source code
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- Scan the package where Spring Controllers are placed --> <context:component-scan base-package="com.roytuts.spring.mvc" /> <!-- Resolves logical String-based view names to actual View types --> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" /> <!-- Where pages are kept --> <property name="prefix" value="/pages/" /> <!-- What is the page extension --> <property name="suffix" value=".jsp" /> </bean> <!-- register messages.properties file as a resource bundle --> <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basename" value="messages" /> </bean> </beans>
In above configuration file I have used <context:component-scan/>
to register the @Component
classes as Spring beans in the base package com.roytuts.spring.mvc
and when a class is annotated with @Component then we do not need to register the class in the XML configuration to make it registered explicitly.
Step 5. Create messages.properties file under src/main/resources directory
error.name=Name is required error.email=Email is required error.address=Address is required
Step 6. Create a directory called pages under webapp directory for putting jsp views.
Step 7. Create below User model class.
package com.roytuts.spring.mvc.models; public class User { private String name; private String email; private String address; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } }
Step 8. Create the below validator class
package com.roytuts.spring.mvc.validators; import org.springframework.stereotype.Component; import org.springframework.validation.Errors; import org.springframework.validation.ValidationUtils; import org.springframework.validation.Validator; import com.roytuts.spring.mvc.models.User; @Component public class UserValidator implements Validator { @Override public boolean supports(Class<?> claszz) { return User.class.isAssignableFrom(claszz); } @Override public void validate(Object target, Errors errors) { ValidationUtils.rejectIfEmptyOrWhitespace(errors, "name", "error.name"); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email", "error.email"); ValidationUtils.rejectIfEmptyOrWhitespace(errors, "address", "error.address"); } }
Step 9. Create Spring controller class which will handle user request and response
package com.roytuts.spring.mvc.controllers; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.validation.BindingResult; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import com.roytuts.spring.mvc.models.User; import com.roytuts.spring.mvc.validators.UserValidator; @Component @Controller @RequestMapping("/register") public class UserController { @Autowired private UserValidator userValidator; @RequestMapping(method = RequestMethod.GET) public String setupUserForm(Model model) { User user = new User(); model.addAttribute("userForm", user); return "add"; } @RequestMapping(method = RequestMethod.POST) public String submitUserForm(@ModelAttribute("userForm") User user, BindingResult result, Model model) { userValidator.validate(user, result); if (result.hasErrors()) { return "add"; } // save the object user to some persistent storage // return to the success page model.addAttribute("success", "User successfully saved"); return "success"; } }
Step 10. Create below add.jsp page and put it under webapp/pages directory. In the below jsp page I have used Spring framework’s tag library for using in the form. Also notice <form:errors path="*" cssClass="error" />
is used for showing all errors in the same place in a form instead of individual errors.
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <html> <title>Spring MVC Validator Example</title> <head> <style> .error { color: #ff0000; font-weight: bold; } </style> </head> <body> <h2>Spring MVC Validator Example</h2> <div> </div> <form:form action="register" method="post" commandName="userForm"> <!--<form:errors path="*" cssClass="error" /> <div> </div>--> Name: <form:input path="name" /><form:errors path="name" cssClass="error" /> <br /> <br /> Email: <form:input path="email" /><form:errors path="email" cssClass="error" /> <br /> <br /> Address:<form:textarea path="address" rows="5" cols="30" /><form:errors path="address" cssClass="error" /> <br /> <input value="Add User" type="submit" /> </form:form> </body> </html>
Step 11. Create below success.jsp page and put it under webapp/pages directory
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <html> <title>Spring MVC Validator Example</title> <body> <h2>Spring MVC Validator Example</h2> <p>${success}</p> </body> </html>
Step 12. Deploy the application and hit the URL http://localhost:8080/spring-mvc/register
When you do not fill up the form and click on Add User button
When you fill up the form and click on Add User button
Thanks for reading.