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.