A Custom Property Editor for Binding Calendar Fields in Spring

The Date class in Java is getting quite old, and we see the Calendar class and its subclasses being used more and more. In my day job, using POJOs and Hibernate, we tend to use Calendars. When we started using the Spring Framework, and its superb spring:bind method to bind HTML elements to backing objects, we quickly stumbled across issues with binding Calendar fields to HTML form elements. In many cases, we caved in and either refactored our fields to Dates, or converted strings to Calendars manually in our Controllers. It was only today when I began to refactor an established web app to accomodate some new requirements, that I ran into this issue but with no desire to change to Dates or use Strings. I thus turned to the CustomDateEditor class that comes with Spring to see if it could be tuned for Calendars. I found, it can with just a couple of lines. The Spring Custom Property Editors work by being provided with a String value through setAsText and return a String value through getAsText. When you use spring:bind, Spring will take a look at your form backing object fields and see how to convert the real field object into a String to show on the web form. Let's start with the spring:bind of the Calendar field
${status.errorMessage}
So, if our form backing object has a Calendar field, we need to make sure that the getAsText method converts our Calendar instance to a String. This is done as follows;
public String getAsText() {
  Calendar value = (Calendar) getValue();
  return (value != null ?
    this.dateFormat.format(value.getTime()) :
    ""
  );
}
getValue() is a method inherited from the superclass PropertyEditorSupport provided by Spring. It just gets a handle to our form backing object's field, in this case a Calendar, or null (which is why the null check). We're also taking advantage of SimpleDateFormat so that when we register the proeprty editor, we can tell it how we want to format our Calendars. When you submit your form back to Spring, it binds the other way around, the form element String values back to your object's field types, in this case a Calendar. The setAsText method looks like this
public void setAsText(String text) throws IllegalArgumentException {
    if (this.allowEmpty && !StringUtils.hasText(text)) {
      setValue(null);
    } else {
      try {
        Calendar cal = Calendar.getInstance();
        cal.setTime(this.dateFormat.parse(text));
        setValue(cal);
    } catch (ParseException ex) {
      throw new IllegalArgumentException();
    }
  }
So, first an empty String is checked, and if matched, the value for the field (the true object now) gets set to null. If a value exists, a Calendar instance is acquired, and using SimpleDateFormat the value is parsed into a Date before getting set into the Calendar. The final thing to do is register this property editor in your form controller's initBinder method
protected void initBinder(HttpServletRequest request,
    ServletRequestDataBinder binder)
    throws Exception {
    binder.registerCustomEditor(
      Calendar.class,
      new CustomCalendarEditor(
        new SimpleDateFormat("dd/MM/yyyy"), true));
  }
That's it. I am not quite sure why a Calendar property editor is not already included in the Spring distribution, I'm not aware of any pitfalls here, it works and it means I can use proper Calendars rather than messing around.

Visitor Comments

  • Hi, I was talking about this with a mate and he reckoned it was better to use Date in the form as you generally only manipulate dates with Calendar. I wasn't so sure and thought it more convenient to have a Calendar from the start. What do you think?

    by Fraser on 14 Jul 2008 11:07 GMT

  • E.g. John, or BlueFrog
  • Your email will not be shown with your comment.
  • Please keep this relevant.