I noticed that date binding is a recurrent problem.
Here is a simple solution :
1- Define a custom Date object, depending on your needs. Here is an example with year, month and day.
2- Use the above object wherever you need a date in your command/domain beansCode:public class DateDay implements Comparable<DateDay>, Serializable { private static final long serialVersionUID = 1L; private static SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); private Date date = new Date(); /** * Public constructor, default to current date */ public DateDay() { } /** * Private constructor, used for parsing * @param date */ private DateDay(Date date) { this.date = date; } /** * Returns the current 'date' object * @return */ public Date getDate() { return date; } /** * Set the date, from a date object * @param date */ public void setDate(Date date) { this.date = date; // Force parsing, to strip hours, minutes, seconds try { this.date = dbFormat.parse(this.getDbString()); } catch(ParseException e) { throw new RuntimeException(e); } } /** * Default String representation of this date (yyyy/mm/dd) * @return */ public String toString() { return format.format(getDate()); } /** * Default parser for a DateDay object * @param source * @return */ public static DateDay parse(String source) { try { return new DateDay(format.parse(source)); } catch(ParseException e) { throw new RuntimeException(e); } } /** * Comparable implementation * @param dateDay * @return */ public int compareTo(DateDay dateDay) { return getDate().compareTo(dateDay.getDate()); } }
3- Use the 'virtual' field in JSPs :Code:public class MyBean { private DateDay startDate = new DateDay(); /** * Default constructor */ public MyBean() { } /** * Returns the start date * @return */ public DateDay getStartDate() { return startDate; } /** * Set the start date * @param startDate */ public void setStartDate(DateDay startDate) { this.startDate = startDate; } /** * Getter for virtual field 'startDateText' (yyyy/dd/mm representation of the startDate) * @return */ public String getStartDateText() { return startDate.toString(); } /** * Setter for virtual field 'startDateText' (yyyy/dd/mm representation of the startDate) * @param startDateText */ public void setStartDateText(String startDateText) { this.startDate = DateDay.parse(startDateText); } }
4- Done !Code:... <form:input path="startDateText" /> ...
There's no need for a custom PropertyEditor and it's perfectly extensible. Let's say I need the same field in a different format (for a database binding), all I need is to define an additionnal SimpleDateFormat in the DateDay object, an additionnal parse method (for database => object mapping), an additionnal toString method (for object => database mapping) and associated virtual fields in the MyBean object (getStartDateDb() and setStartDateDb()).
Hope this will help those who think date binding is a pain in...
PS : for date validation, and custom error messages you could use in your messages.properties :
where 'command' is the name of your command object.Code:methodInvocation.command.startDateText=Invalid date format, try yyyy/mm/dd


Reply With Quote