I am trying to create a form to edit an existing database row. I am using the Spring MVC form tag to auto bind the html to a form backing object. The row has a many to many relationship with another table, which I am trying to represent with a multiple select box using the form:select tag;
<form:select path="rules">
<form:options items="${bundle.rules}" itemValue="name" itemLabel="name"/>
</form:select>
I am using Hibernate for persistence so the relationship is represent as a HashSet inside the Bundle pojo.
private Set<Rule> rules = new HashSet<Rule>(0);
Without the selection box on the page, the object will update to the database correctly, however with the selection box the object will not update to the database and I am getting this error in my log4j log, note that this error is not causing an exception, it is only visible in the logs;
DEBUG org.springframework.web.servlet.mvc.SimpleFormController.processFormSubmission(SimpleFormController.java:256) - Data binding errors: 1
This happens regardless of wither I deselect items inside the select box, the entire form refuses to submit correctly. Can anyone help me?
I am aware of How do I bind collection attributes to a form in Spring MVC, which is similar to this question, unfortunately none of the suggestions seemed useful to my problem.
The problem is with the submission of your form. Spring isn't able to bind an object of the command, so it doesn't submit the form, but redirects you to the formView instead.
When the binding is successfully performed, you will see this message instead:
No errors -> processing submit
To solve your problem, you will need to register a CustomCollectionEditor with your controller. (See this link). It would be something like this:
protected void initBinder(HttpServletRequest request, ServletRequestDataBinder binder) throws Exception
{
binder.registerCustomEditor(Set.class, "rules", new CustomCollectionEditor(Set.class)
{
protected Object convertElement(Object element)
{
String name = "";
if (element instanceof String)
name = (String) element;
return name != null ? new Rule(name) : null;
}
});
}