How do I bind collection attributes to a form in Spring MVC


How do I bind collection attributes to a form in Spring MVC



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?




Integration Test with Spring: Cannot convert value of type error

1:



EJB vs Spring + POJO
I think it has to be an ordered collection.


Startup performance of Spring @Configurable with Compile Time Weaving
For example,there's a chart in the Spring reference that talks about how to reference properties.


In Spring with jpa/hibernate, how do I keep a session open to avoid lazy initialization exceptions?
It says:.
Spring 3.0 and SOAP - What's best practice?
account[2] Indicates the third element of the indexed property account.


Portlets - Keeping session alive from server side
Indexed properties can be of type array, list or other naturally ordered collection (emphasis theirs).
Use of getBean as opposed to method injection in Spring
Perhaps one approach would be to add a getter to your object that, rather than returning your Set, returns Set.toArray().


SWFUpload and Java: Session is lost
Then your items attribute would reference the array.

Of course, you can't depend on the ordering..


2:


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..


3:


found perfect solution here: http://forum.springsource.org/showthread.php?45312-Submitting-arrays . general idea - using commons-collections methods to init list:.
private List someList = LazyList.decorate(new ArrayList(), FactoryUtils.instantiateFactory(com.abc.xyz.SomeClass.class)); 


4:


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" /> 


5:


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..


6:


You can use a semi-colon-delimited list if you're using numeric references to the IDs of objects, and an appropriate Converter implementation registered.. POST data leaderboards=1,2. Converter implementation (ignore the JSON stuff).
    public final class LeaderboardConverter extends JsonDeserializer<Leaderboard> implements Converter<String, Leaderboard>     {         public Leaderboard convert(String source) throws IllegalArgumentException         {             Leaderboard activity = new Leaderboard();             activity.setId(new Integer(source));             return activity;         }           public Leaderboard deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException         {             return convert(jp.getText());         }  } 



76 out of 100 based on 86 user ratings 286 reviews