Easy way of handling dates in a Struts form

Posted Thu, 02 Feb 2006 18:43:00 GMT

It’s bit unfashionable to write about Struts now, what with all the JSF, Tapestry, etc frameworks, but most projects I’ve seen still use Struts, and I often end up having to re-invent how to deal with the dates and other non-standard fields in the forms. So this time I’ll write it down. Especially as this time it seems relatively neat and simple.

So here’s how you do it:

The form bean

Say we’ve got the following date fields:

  private Date dob;
  private Date memorableDate;

public Date getDob() { return dob; } public void setDob(Date dob) {
this.dob = dob ; } ...

Struts can’t populate these fields. One option is to keep your dates as String, but have a go and you’ll see why that’s awkward.

So what we do is

add these getters and setters for the dates:

  public String getDobString() {
    return dateToString(dob);
  }

public void setDobString(String dobString) { this.dob = stringToDate(dobString); } ...

The two conversion methods are up to the application’s requirements, but a simple implementation would be:

  private SimpleDateFormat simpleDateFormat = 
      new SimpleDateFormat("dd/MM/yyyy");

Date stringToDate(String string) throws ParseException { return simpleDateFormat.parse(string); }

String dateToString(Date date) { return simpleDateFormat.format(date); }

Note that SimpleDateFormat is a fairly heavy object and not thread-safe. Luckily the form can not be shared anyway, so at least the thread safety is not an issue, unless someone decides to make it static in a feat of efficiency. So, yeah, don’t make it static.

Now, let’s go back to the setter and handle the ParseException. If one occurs, we will keep the name of the field that caused it in a List.

  List unparseableFields = new ArrayList(1);

public void setDobString(String dob) { try { this.dob = stringToDate(dob); } catch (ParseException e) { this.unparseableFields.add("dob"); } }

Note - the list must be re-instatiated in the reset() method, because Struts may reuse the forms.

This means, that after the initial setting of fields by the framework, we’ll have no flying exceptions, but a list of the unparseable fields. This means we can use that in the validate() method (the next thing to execute) like this:

  public validate(...) {
    ....
    Iterator unparseableFieldsIterator = 
        this.unparseableFields.iterator();
    while (unparseableFieldsIterator.hasNext()) {
      String brokenFieldName = 
         (String) unparseableFieldsIterator.next();
      errors.add(new ActionError(fieldName, "date.parse.error");
    }
    ...
  }

This means that for each field that failed to parse, an error will be created and that error will be attached to the same field.

The view

In the view (JSP) we use the dobString property, instead of the dob. This, obviously is still stored in the dob Date field, which means it can be accessible as a normal date from the Action others. Here’s a snippet of the JSP:

  ...
  <errors property="dobString" />
  <label for="dob">Date of birth</label>
  <html:text property="dobString" styleId="dob"/>
  ...

The errors tag achieves the display of the error associated with this field just before it.

Further possibilities

What I have been doing recently is using one longer field where the user can enter comma-separated values when I need to receive a list. In the form I have the List object and get/setListString methods. In the view I use the listString “dummy” property and instruct the user to separate the entries with commas. Then in the form, following the same pattern, I parse the string using the StringTokenizer and throw a ParseException if there’s an error.

Comments

(leave url/email »)

  

Home

Who's George?

Recent entries