Date Validation in Spring MVC

I am using Spring MVC (Spring 2.5.1) and needed date validation in my form, with a custom error message. Reflecting my inability to R(or find)TFM, I failed miserably to find a resource that clearly outlined how to set up validation for a date. So here is my public record of a small saga.

First, I set up a date field in my JSP.

<form:errors cssClass="error"
    path="document.publishDate"/>
<form:input id="publishDate"
    path="document.publishDate"
    cssStyle="width:100px;"  />

There is a matching java.util.Date instance variable called publishDate in my Document class.

Next step is to define an object that can validate my dates. In servletName-servlet.xml, I have defined a custom date editor.

<bean id="customDateEditor"
    class="org.springframework.beans.propertyeditors.CustomDateEditor">
    <constructor-arg >
      <bean class="java.text.SimpleDateFormat">
        <constructor-arg><value>dd/MM/yyyy</value></constructor-arg>
      </bean>
    </constructor-arg>
    <constructor-arg ><value>true</value></constructor-arg>
  </bean>

The same config file defines my controller, and I inject the custom data editor into the controller through my Spring config.

<!-- Controller for ... -->
  <bean name="doJob.htm" id="jobController" class="..."
    ...
    <property name="customDateEditor" ref="customDateEditor"/>
    ...
  </bean>

This means that my controller will have an instance of CustomDateEditor ready to use, injected by Spring. I could have had my controller create its own CustomDateEditor, however. Either way, the next step is to register the data editor in the initBinder(HttpServletRequest, ServletRequestDataBinder) method of my controller.

  /**
   * {@inheritDoc}
   * @see org.springframework.web.servlet.mvc.
   *    BaseCommandController#initBinder(javax.servlet.http.HttpServletRequest, 
   *    org.springframework.web.bind.ServletRequestDataBinder)
   */
  protected void initBinder(HttpServletRequest request, 
      ServletRequestDataBinder binder) throws Exception {
    binder.registerCustomEditor(Date.class, getCustomDateEditor());
  }

The controller needs to be a subclass of org.springframework.web.servlet.mvc.BaseCommandController to have an initBinder() method. In this instance, my controller is a org.springframework.web.servlet.mvc.SimpleFormController.

This means that I have automatically defined the date format required for all dates that get validated by this controller.

Next step is to set up the error message I want. Personally, I found this the hardest part. I had to look at my logging closely to work out what was going on. In my controller's showForm(HttpServletRequest, HttpServletResponse, BindException, Map) method, I was outputting the result of a toString() call on the BindException object and I saw the following. The key things are in red.

Field error in object 'viewDocCommand' on field 'document.publishDate':
  rejected value [noWayIsThisAGoodDateValue!];
  codes [typeMismatch.viewDocCommand.document.publishDate,
  typeMismatch.document.publishDate,typeMismatch.publishDate,
  typeMismatch.java.util.Date,typeMismatch];
  arguments [org.springframework.context.support.DefaultMessageSourceResolvable:
  codes [viewDocCommand.document.publishDate,document.publishDate];
  arguments []; default message [document.publishDate]];
  default message [Failed to convert property value of type
  [java.lang.String] to required type [java.util.Date]
  for property 'document.publishDate';
  nested exception is java.lang.IllegalArgumentException:
  Could not parse date: Unparseable date: "noWayIsThisAGoodDateValue!"]

After a lot of searching in forums and javadocs I finally accumulated enough hints to get a hunch! Those dot separated values are message keys. Spring looks in the messages.properties file to find values to replace them with. I put entries into messages.properties to cover the most generic error type (typeMismatch.java.util.Date) and the field name.

typeMismatch.java.util.Date={0} is an invalid date. Use format DD/MM/YYYY.
document.publishDate=Publish Date

Now when I have a bad date value, I see the error message: Publish Date is an invalid date. Use format DD/MM/YYYY.

Links that helped me with this.

Popular Posts