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>&nbsp;</div>
	<form:form action="register" method="post" commandName="userForm">
                <!--<form:errors path="*" cssClass="error" />
                <div>&nbsp;</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


spring mvc validator

When you do not fill up the form and click on Add User button


spring mvc validator

When you fill up the form and click on Add User button


spring mvc validator

Thanks for reading.

Tags:

I am a professional Web developer, Enterprise Application developer, Software Engineer and Blogger. Connect me on Roy Tutorials | TwitterFacebook Google PlusLinkedin | Reddit

Leave a Reply

Your email address will not be published. Required fields are marked *