Spring MVC Form Validation using Validator

This tutorial with source code will show you how to validate data submission using Spring validator.
To demonstrate i will using source code that i use for the post Spring MVC and apache Tiles 3 integration

1. Add message resource

We need a message resource file to define key and message to show for specific validate. So create message.properties file in src/main/resources/

Follow is content of message.properties file:

#General use
error.invalid={0} is invalid format.
error.requried={0} is required.

#Add Employee Form
employee.form.title=Add Employee
employee.form.firstname=First name
employee.form.lastname=Last Name
employee.form.phone=Phone
employee.form.email=Email
#End Add Employee Form

To Spring MVC can look up message resource we need define follow bean in our Dispatch Servlet config file servlet-context.xml

<beans:bean id="messageSource"
    class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <beans:property name="defaultEncoding" value="UTF-8" />
    <beans:property name="basenames" value="classpath:messages"/>
  </beans:bean>

Remember name of this bean must be messageSource

2. Define Validator

To support validate submission data we need define a validator for the form.

I created two classes: EmployeeValidator for validate EmployeeForm and PatternValidator for validate field require match a pattern such as: email, phone …etc. Source code as below

EmployeeValidator.java

/*
 * devjav [http://devjav.com]
 * Copyright (C) 2014-2014 Pham Thai Thinh
 * Contact:phamthaithinh@gmail.com
 * 
 */
package com.devjav.validator;

import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.validation.Validator;

import com.devjav.form.EmployeeForm;

/**
 * 
 * @author Pham Thai Thinh
 * 
 */
public class EmployeeValidator implements Validator {
  public boolean supports(Class<?> clazz) {
    return clazz.isAssignableFrom(EmployeeForm.class);
  }

  public void validate(Object form, Errors errors) {
    EmployeeForm employeeForm = (EmployeeForm) form;
    ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName",
        "error.requried", new Object[] { "First name" });
    ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName",
        "error.requried", new Object[] { "Last name" });

    ValidationUtils.rejectIfEmptyOrWhitespace(errors, "phone",
        "error.requried", new Object[] { "Phone" });
    ValidationUtils.rejectIfEmptyOrWhitespace(errors, "email",
        "error.requried", new Object[] { "Email" });

    if (!errors.hasFieldErrors("email")) {
      if (!PatternValidator.validateEmail(employeeForm.getEmail())) {
        errors.rejectValue("email", "error.invalid",
            new Object[] { "Email" }, "Email is invalid format");
      }
    }
    if (!errors.hasFieldErrors("phone")) {
      if (!PatternValidator.validatePhone(employeeForm.getPhone())) {
        errors.rejectValue("phone", "error.invalid",
            new Object[] { "Phone" }, "Phone is invalid format");
      }
    }
  }
}

PatternValidator.java

public class PatternValidator {
  private static String PHONE = "[0-9]{10}";
  private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@"
      + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$";

  public static boolean validateEmail(String email) {
    Pattern pattern = Pattern.compile(EMAIL_PATTERN);
    Matcher matcher = pattern.matcher(email);
    return matcher.matches();
  }
  public static boolean validatePhone(String phone) {
    Pattern pattern = Pattern.compile(PHONE);
    Matcher matcher = pattern.matcher(phone);
    return matcher.matches();
  }
}

3. Controller

To enable Spring validate for data submission we need add follow thing:

  • add Validator class to WebDataBinder so that Spring can find and apply validate
  • Annotation ModelAtribute with@Valid
  • Add binderResult follow immediate after parameter need validate

To add EmployeeValidator to WebDataBinder i change AddEmployeeController.java as below:

@InitBinder(value = "employee")
  public void initBinder(WebDataBinder binder) {
    binder.addValidators(new EmployeeValidator());
  }

@InitBinder(value = "employee") mean this validator just apply for model attribute has name employee

We change <code>process</code> function in AddEmployeeController as below

@RequestMapping(method = RequestMethod.POST)
  public String process(
      @ModelAttribute("employee") @Valid EmployeeForm employee,
      BindingResult results, HttpSession session) {
    if (results.hasErrors()) {
      return getSuccessView();
    }
    Employee emp = new Employee();
    emp.setEmail(employee.getEmail());
    emp.setPhone(employee.getPhone());
    emp.setLastName(employee.getLastName());
    emp.setFirstName(employee.getFirstName());
    session.setAttribute("message", "Insert employee successful.");
    employeeService.insert(emp);

    return getRedirectView();
  }

That mean we request Spring validate ModelAttribute employee and put result to BindingResult parameter results

4. Change add.jsp to show message

To show validate message on page we using taglib form:errors as below:

<%@ page language="java" contentType="text/html; charset=UTF-8"
  pageEncoding="UTF-8" isELIgnored="false"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<style type="text/css">
.error{
color: red;
}
</style>
  <spring:hasBindErrors name="employee">
    <div class="error">
      <h4>Oops!</h4>
      <ul>
        <c:forEach var="error" items="${errors.allErrors}">
          <li><spring:message code="${error.code}"
              arguments="${error.arguments}" text="${error.defaultMessage}"></spring:message></li>
        </c:forEach>
      </ul>
    </div>
  </spring:hasBindErrors>
  <c:if test="${not empty message}">
    <div id="message" style="background-color: green">${message}</div></c:if>
  <spring:url value="/manage/add.do" var="action" />
  <form:form action="${action}" commandName="employee">
    <div>
      <table>
        <tr>
          <td>First Name</td>
          <td><form:input path="firstName" /><form:errors path="firstName" cssClass="error"/></td>
        </tr>
        <tr>
          <td>Last Name</td>
          <td><form:input path="lastName" /><form:errors path="lastName" cssClass="error"/></td>
        </tr>
        <tr>
          <td>Phone</td>
          <td><form:input path="phone" /><form:errors path="phone" cssClass="error"/></td>
        </tr>
        <tr>
          <td><spring:message code="employee.form.email"/> <span style="color: red">*</span></td>
          <td><form:input path="email" /><form:errors path="email" cssClass="error"/></td>
        </tr>
        <tr>
          <td colspan="1"><input type="submit" value="Submit"></td>
          <td colspan="1"><input type="button" value="list" onclick="location.href='<c:url value='/manage/list.do' />'"></td>
        </tr>
      </table>
    </div>
  </form:form>

In this demo i show you two ways to show validate error: one on top and one is beside each field. You can choose the right approach for your.

5. Run application

Run application and left some fields is blank and format is invalid you will get error as below

6. Source code

You can download source code from my github  or by click this link

3 thoughts on “Spring MVC Form Validation using Validator”

Leave a Reply