I don't know if there is a direct way to do it in spring, but the way I have done it is a combination of jQuery's DatePicker and InitBinder.
In the JS side, you create a:
<form:input cssClass="datepicker" path="someProperty" readonly="true" />
Then in the JS:
$(document).ready(function() {
$('.datepicker').datepicker();
});
On the Controller side, create a method like thus:
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
sdf.setLenient(true);
binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
}
From here you can create typeMismatch messages in your resource bundle to create a nice, pretty message. The user will not be able to manually type into the field, but instead will only be able to use the jQuery DatePicker, which will format the date as needed (I think the default is MM/dd/yyyy). In the case where they DO manage to enter a date, Spring will use the configured CustomEditor to convert the String from the view to the Date expected. If it fails, you get a error in the BindingResults (if you include it in your method signature). You can customize this method, as I stated before, but setting up a custom typeMismatch message in your resource bundle.
Edit: Adding additional details as my explaination above was obviously not clear enough...
First, create a Bean or something to act as your Model Attribute (what you send back and forth from View to Controller). Ensure it has at least one date in it.
public class SomeBean {
private Date someDate;
// ...additional properties, getters, setters...
public Date getSomeDate() { return someDate; }
public void setSomeDate(Date date) { somedate = date; }
}
Now you need a controller. I like to make my Model Attributes session attributes via the
@SessionAttribute.
@Controller
@RequestMapping("/somePath")
@SessionAttributes({"someFormBean"})
public class SomeController {
/**
* Handler method
*/
@RequestMapping()
public String defaultView(@ModelAttribute("someFormBean") SomeBean someFormBean, Model uiModel) {
// Do something in your default view
return "someDefaultView"; // Assuming you have a ViewResolver, like JspViewResolver or Tiles
}
/**
* Submission Handler method
*/
@RequestMapping(method = RequestMethod.POST
public String submit(
@ModelAttribute("someFormBean") SomeBean someFormBean,
BindingResult bindingResults,
Model uiModel) {
// bindingResults will have your errors from binding
if(bindingResults.hasErrors()) {
return "errorView";
} else {
return "successView";
}
}
/**
* Will be called to create your Model Attribute when its missing
*/
@ModelAttribute("someFormBean")
public SomeBean createSomeBean() {
return new SomeBean();
}
/**
* register property editors
*/
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy");
sdf.setLenient(true);
binder.registerCustomEditor(Date.class, new CustomDateEditor(sdf, true));
// You can register other Custom Editors with the WebDataBinder, like CustomNumberEditor for Integers and Longs, or StringTrimmerEditor for Strings
}
}
Then you need some view ("someDefaultView" above in the controller, my code is JSP in this example, using the Spring JSTL tag library)
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<html>
<head>
<script type="text/javascript" src="/resources/jquery/1.7.1/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="resources/jquery.ui/1.8.13/jquery.ui.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('.datepicker').datepicker();
};
</script>
</head>
<body>
<form:form modelAttribute="someFormBean">
<form:input cssClass="datepicker" path="someDate" readonly="true" /><br />
<form:errors path="a"/><br /><br />
<input type="submit" value="Submit" />
</form:form>
</body>
</html>
Again, I would suggest Google'ing Spring Init Binders, cusomizing binding errors (typeMismatch), and JSR 303 for additional options for validation, most of when is well documentet here. Also, if you don't want the error below to the field, as I have done here there are ways to iterate all the errors in one spot, like putting all the errors at the top of the page. Its very configurable, and I could type probably another 20 pages worth going over all of it in depth. This should be plenty to get you started in finding good examples and documentation.