views:

7839

answers:

4

I'm trying to bind one of my model objects to the fields of a form, using Spring-MVC. Everything works fine, except that one of the attributes of the model object is an unordered collection. Doing something like

    <c:forEach items="${m.items}" var="i" varStatus="itemsRow">
      <form:input path="items[${itemsRow.index}]"/>
    </c:forEach>
    <form:errors path="items" />

would work fine for a List-type property, but for a Set throws an error when, upon submit, it tries to bind input field content to object attributes.

Is there something in Spring that works out of the box with Sets?

+1  A: 

I think it has to be an ordered collection. For example,there's a chart in the Spring reference that talks about how to reference properties. It says:

account[2] Indicates the third element of the indexed property account. Indexed properties can be of type array, list or other naturally ordered collection (emphasis theirs)

Perhaps one approach would be to add a getter to your object that, rather than returning your Set, returns Set.toArray(). Then your items attribute would reference the array. Of course, you can't depend on the ordering.

JacobM
I could use a Decorator around the model object... looks like a good idea.
agnul
A: 

I am not crystal clear on how exactly this gets bound, but it works for my purposes.

 <c:forEach items="${items}" var="i" varStatus="itemsRow">
        <input name="items[${itemsRow.index}].fieldName" type="text"/>
    </c:forEach>
 <form:errors path="items" />
zmf
funny how avoiding the form:/path stuff avoids the error.
bmargulies
+1  A: 

I think the reason that it doesn't work with a Set is because a the order of a Set is not guaranteed. When you try to bind to the first object on post, it may not have been the first object in that list to render out. For example, items[0] may not be the same between the GET and the POST.

So it should work fine if you use an implementation of Set that is ordered, such as a SortedSet or TreeSet.

Just gave this a try. SortedSet is an interface, so you can't use that and TreeSet doesn't appear to fix the issue.
James McMahon
I just had this same problem, found this question, changed my form element to be a TreeSet, and it works! Thanks for saving me alot of time!
nont
A: 

You could try writing your own custom Editor to do the job, and then registering the editor with the controller for the form. You wouldn't have to bother with indexing the elements in the Set that way. And as previously mentioned, if there's a way of sorting the elements, you could ensure their order in the set using SortedSet.

Alex Marshall