Featured Post

Event Sourcing Video from Michael Ploed

Event Sourcing I want to share a great video I found few days ago that describes very well what Event Sourcing is.

Friday, May 11, 2012

Spring MVC Custom Validator

In this post we'll see an example of a form data validation. This form has two fields: number and type. I use a Controller to manage the request and a custom Validator to validate the form.
If some errors occur during validation, we'll show error messages just above each field that has caused the problem.

Step-1: Create a POJO class representing the object you want to validate and the JSP page containing the form

As you can see Contact is a class that has two fields: number and type. This class contains exactly the fields of the form.


package com.simonefolinojavablog.spring.bean;

public class Contact {

 private int number;

 private String type;

 public int getNumber() {
  return number;

 public void setNumber(int number) {
  this.number = number;

 public String getType() {
  return type;

 public void setType(String type) {
  this.type = type;

 public String toString() {
  return "Contact [number=" + number + ", type=" + type + "]";

The following JSP has a form with two input text: type and number. The form tag specifies both the modelAttribute (the bean that maps the form) and the action (the request URL).


<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>

<title>Form Page</title>


 <form:form id="" action="/springmvc-validator/contacts/save.htm" modelAttribute="contact"
     <td> <form:errors path="number" cssClass="error" element="div" />
     number: <input type="text" name="number" value="" /></td>
     <td> <form:errors path="type"  ssClass="error" element="div" />
      type: <input type="text" name="type" value="" /></td>
     <td><input type="submit" name="save" value="save" /></td>



Step-2: Create a Validator

In the following code is shown a subclass of Validator: CustomValidator. We have to override two methods of Validator class: supports that tells which kind of bean has to be validated and validate that contains the logic of validation.


package com.simonefolinojavablog.spring.validator;

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

import com.simonefolinojavablog.spring.bean.Contact;

public class ContactValidator implements Validator {

 public boolean supports(Class clazz) {
  return Contact.class.equals(clazz);

 public void validate(Object target, Errors errors) {
  Contact contact =(Contact)target;
  System.out.println("contact:"+contact+"  validating...");
  ValidationUtils.rejectIfEmptyOrWhitespace(errors, "type", "errors.empty.type","error occur");


Step-3: Create a Controller class

ContactController is a controller that makes use of a Validator to validate instances of Contact.
In this controller i use two annotations:
  • @InitBinder(value = "contact") to bind the object of type Contact whose name is contact and to register a custom validator for instances of Contact class.
  • @Valid to validate binding instance of Contact class with the Validator registered

If errors occur the controller returns to form View otherwise it returns to result.


package com.simonefolinojavablog.spring.controller;

import javax.validation.Valid;

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 com.simonefolinojavablog.spring.bean.Contact;
import com.simonefolinojavablog.spring.validator.ContactValidator;

@RequestMapping(value = "/contacts")
public class ContactController {

 @InitBinder(value = "contact")
 protected void initBinder(WebDataBinder binder) {
  binder.setValidator(new ContactValidator());

 @RequestMapping(value="/save",method = RequestMethod.POST)
 public String saveContact(@ModelAttribute(value = "contact") @Valid Contact contact,BindingResult errors, ModelMap modelMap) {
  if (errors.hasErrors()) {
   System.out.println("some errors occur");
   return "form";
  return "result";

Step-4: Create an errors.properties file

We have to create a file that contains error messages, and declare the location of this file in Spring configuration.

errors.empty.number=number field is empty
errors.empty.type=type field is empty
typeMismatch.contact.number=type mismatch Contact Number
typeMismatch.java.lang.NumberFormatException=5. Invalid value for {0}, accepts only numbers. 
typeMismatch.java.lang.Integer=Must specify an integer value. 
typeMismatch.java.lang.Long=Must specify an integer value. 
typeMismatch.java.lang.Float=Must specify a decimal value. 
typeMismatch.java.lang.Double=Must specify a decimal value.  
typeMismatch.int=Invalid number entered 
typeMismatch=Invalid type entered

In Spring configuration we use a special bean called ResourceBundleMessageSource that points the properties files managed by Spring context.


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
    http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

 <context:annotation-config />

 <context:component-scan base-package="com.simonefolinojavablog.spring" />

 <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
     <property name="basenames">


Step-5: Put into web.xml the information to load the root web application context

As you can see, we have to declare ContextLoaderListener because we need to load the root application context and not just the web application context. I'm going to speak about the difference between root application context and web application context in another post.


<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


No comments :

Post a Comment