Multiple select with Spring MVC

During our coding night (there’s be a separate blog for it), we committed ourselves to use only Spring technologies. But a simple requirement had a rather dramatic effect.

Update (2011-11-10): With Spring 3.0 things will be a lot easier, take a look at the comment from Antti Andreimann for details.

How do you create a multiple select box with Spring MVC? You should be able to select multiple elements, which then get added to a collection of the backing bean.

We are implementing a simple time tracking application. The domain model contains projects, which can have staff members assigned. Projects have tasks, which also have staff members assigned to. So in the task creation view we need a select box that contains all available employees.


Here are the most important extracts from Tasks and Staff members:


public class Task implements Serializable {
	private long id;
	private Set<Staff> staffs = new HashSet<Staff>(0);


@NamedQuery(name = "staff.activeStaff", query = "select s from Staff s where s.disabled = false")
public class Staff extends Person {


@NamedQuery(name = "person.findByUsername", query = "from Person p where p.login.username = :username")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING)
public abstract class Person implements Serializable {
	private long id;


In the task creation view, we need a select box that shows all available employees. The selected employees shall then be assigned to the task when the form is submitted.

public class ProjectController {
	@RequestMapping(method = RequestMethod.GET, value = "/project/createTask.action")
	public void createTaskView(@ModelAttribute Task task, Model model) {
		List<Staff> activeStaff = timetrackingService.getActiveStaff();
		model.addAttribute("activeStaff", activeStaff);

The JSP that belongs to the controller contains this snippet for the select box:

<td><label for="staffs">Chose Staff: </label></td>
<td><form:select path="staffs" multiple="true" items="${activeStaff}" itemLabel="fullName" itemValue="id"/></td>
<td><form:errors path="staffs" /></td>

The problem is, as soon as you submit the form, you will get a ServletRequestBindingException, because Spring has no idea how to map a String (or String[] when multiple staff members have been selected) to a Set.

org.springframework.web.bind.ServletRequestBindingException: Errors binding onto object 'task'; nested exception is org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'task' on field 'staffs': rejected value [3]; codes [typeMismatch.task.staffs,typeMismatch.staffs,,typeMismatch]; arguments [ codes [task.staffs,staffs]; arguments []; default message [staffs]]; default message [Failed to convert property value of type [java.lang.String] to required type [java.util.Set] for property 'staffs'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [java.lang.String] to required type [de.codecentric.timetracking.model.Staff] for property 'staffs[0]': no matching editors or conversion strategy found]

Additionally, the generated HTML is missing the ID for staff members!

<select id="staffs" multiple="multiple" name="staffs">
<option value="">firstname lastname</option>
<option value="">aaaa aaaa</option>
<option value="">firstname lastName</option>
<option value="">firstname aaaa</option>
<option value="">firstname lastname</option>
<input type="hidden" value="1" name="_staffs"/>

Id as String

In order to have the staff member ID in the value attribute of the option element, we can create a new getter in the Person class that returns the id as String, and then use that in the JSP:

public abstract class Person implements Serializable {
	public String getIdAsString() {
		return new Long(id).toString();
<form:select path="staffs" itemValue="idAsString" multiple="true" items="${activeStaff}" itemLabel="fullName"/>


The solution to the binding problem is more difficult. We need a PropertyEditor for the attribute ‘staffs’. Spring contains a number of PropertyEditors, so we can use the CustomCollectionEditor. It is expected that the property editor can map the string from options value back to the element, so we need to store that mapping somewhere, in a map for example.

public class ProjectController {
private Map<String, Staff> staffCache;
@RequestMapping(method = RequestMethod.GET, value = "/project/createTask.action")
public void createTaskView(@ModelAttribute Task task, Model model) {
	List<Staff> activeStaff = timetrackingService.getActiveStaff();
	staffCache = new HashMap<String, Staff>();
	for (Staff staff : activeStaff) {
		staffCache.put(staff.getIdAsString(), staff);
	model.addAttribute("activeStaff", activeStaff);
protected void initBinder(WebDataBinder binder) throws Exception {
	binder.registerCustomEditor(Set.class, "staffs", new CustomCollectionEditor(Set.class) {
		protected Object convertElement(Object element) {
			if (element instanceof Staff) {
				System.out.println("Converting from Staff to Staff: " + element);
				return element;
			if (element instanceof String) {
				Staff staff = staffCache.get(element);
				System.out.println("Looking up staff for id " + element + ": " + staff);
				return staff;
			System.out.println("Don't know what to do with: " + element);
			return null;

The code still contains some debug output to System.out, which has to be removed. But it shows that the method is called very frequently. Only for showing the select box with 5 employees, the method is caller 15 times. 10 times the id is passed in as a String, and 5 times the object is passed in. I have found no good documentation what exact behaviour is expected from that PropertyEditor, this is the best working solution I could come up with.

Looking up staff for id 1: Staff(firstname lastname)
Looking up staff for id 1: Staff(firstname lastname)
Converting from Staff to Staff: Staff(firstname lastname)
Looking up staff for id 2: Staff(aaaa aaaa)
Looking up staff for id 2: Staff(aaaa aaaa)
Converting from Staff to Staff: Staff(aaaa aaaa)
Looking up staff for id 3: Staff(firstname lastName)
Looking up staff for id 3: Staff(firstname lastName)
Converting from Staff to Staff: Staff(firstname lastName)
Looking up staff for id 4: Staff(firstname aaaa)
Looking up staff for id 4: Staff(firstname aaaa)
Converting from Staff to Staff: Staff(firstname aaaa)
Looking up staff for id 5: Staff(firstname lastname)
Looking up staff for id 5: Staff(firstname lastname)
Converting from Staff to Staff: Staff(firstname lastname)

After selecting an employee and submitting the form, expectedly there’s only one line in the log, converting the id back to the staff member.:

Looking up staff for id 3: Staff(firstname lastName)


With the massive amount of web frameworks around, I find it surprisingly complicated to achieve something as simple as a multiple select box in Spring MVC. But, I just leard Spring MVC yesterday, so I might not know all details yet. So if there’s a more elegant and simpler solution to achieve the same as described above, I very much welcome your feedback.

  • Facebook
  • Delicious
  • Digg
  • StumbleUpon
  • Reddit
  • Blogger
  • LinkedIn
Andreas Ebbert-Karroum

28 Responses to Multiple select with Spring MVC

  1. Chandresh says:

    Many thanks to you Andreas ! Yours is the best explanation of how to get this multiple select going – for use to set a “Collection” into a bean.

  2. Glad you found it helpful, it indeed took a few hours to figure that out.

  3. Maarten Donders says:

    Ein Hinweis dazu:

    Die Anmeldung eines CustomCollectionEditor ist, wenn die anzubindenden Collections mittels Generics typisiert sind, nicht erforderlich. Hier reicht ein PropertyEditor für den jeweiligen Typ. Spring kümmert sich dann darum, daß auch die Collections korrekt gebunden werden.

    Allerdings führt die Modifizierung von Klassen mittels CGLIB, wie sie beispielsweise von Hibernate durchgeführt wird, dazu, daß die Typisierung der Collections verlorengeht. In diesem Fall kann Spring sie nicht mehr auflösen und ist ein explizites Anmelden eines CustomCollectionEditors notwendig.

    Eigentlich ist es also ganz einfach mit Spring-MVC eine multiple select box zu implementieren. Nur wenn die Typinformationen nicht zur Verfügung stehen, wird es schwierig. Wie soll es auch ohne Typinformationen gehen?

  4. Madhuri says:

    Just Perfect! I have read many blogs/documents for the multi select, but no luck. This worked just right in a few minutes! You made my day. Thank you so much!!!

  5. Pingback: Confluence: Development Space

  6. lance says:

    This sounded great. I tried it verbatim but didn’t have success. The form:select tag worked as expected but it would never bind the user’s selections to the List. Spring can be too finicky. It must be version dependent.

  7. I lance, sorry to hear that the instructions did not work for you. I documented what I did to get it working. What error message are you getting now? I doubt that this behaviour is dependant on the spring version.

  8. Karl Minor says:

    Nothing pleases me more than Googling a problem I’ve run into and finding a kind soul like yourself who has already seen the problem, solved it, and documented the solution for the benefit of perfect strangers. Thank you much, sir.

    And remember that for every person that responds, there are probably ten others you’ve helped that were in too much of a hurry to say thanks.

    Please forward this to your parents to remind them that they done good.


  9. Hi Karl,

    thanks for your kind words! I will forward them to my parents and also my boss 😉


  10. john says:

    can you update this leveraging spring 3 (type-conversion)?

  11. Hi John,

    thanks for asking. When we run into this problem again with Spring 3 we will certainly update the blog. In the meantime, you might do so and link to your results? :)


  12. Sudheendra says:

    Thanks. I was struggling for a while but now have finally got it working.

  13. Aruna says:

    Hi Andreas,

    This guide help let.
    Is there any way to register the editor without specifying the field name? Bcoz when I registering with field name, i cannot use the editor globally.

  14. ugender says:

    Found interesting that if your bean/object has a constructor with String argument, everything works seamlessly (working with Spring 3).
    Also, multiple=”true” is not required if you are mapping it to a List, spring will consider those options as multiple :)

  15. Creative says:

    Is there another way to get this done without the use of Custom editors?
    Seems like a very cumbersome process!

  16. I can confirm that with Spring 3.0 it’s a lot easier.

    Just use something like:

    <form:select path="bears" multiple="true" items="${allbears}" itemLabel="name" itemValue="id" />

    And binded object’s setBears method will be called with a collection populated from selected members (looked up by ID-s of course).

    However, if using JPA entities, relation objects must be properly managed. Eg for ManyToOne relation, a setter must take care that changes are propagated to objects that manage the relation (hold the foreign key).

    	public void setBears(Collection<Bear> bears) {
    		if(bears == null) {
    			this.bears = new ArrayList<Bear>();
    		} else {
    			this.bears = bears;
    		for(Bear b: this.bears) {
    			if(b.getCage() != this) {
    • Hi Antti,

      thanks a lot for your update regarding Spring 3! I will mention your answer in the article :)


    • Draco says:

      Can you give a full example please?
      I tried the your method with Spring 3.0 but i get the same conversion error.

    • Rick says:

      I’m not seeing your solution work either.
      Can someone confirm that Antti’s solution should work (Spring 3.1) ?

      For example I have

      int key
      String descr
      private List biaItems; 

      When this form submits however I end up with:

      [Failed to convert property value of type ‘java.lang.String[]’ to required type ‘java.util.List’ for property ‘biaItems'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [java.lang.String] to required type [com.foot.domainmodel.Dim] for property ‘biaItems[0]': no matching editors or conversion strategy found]

  17. Neha says:

    I am trying to by default select all the values populated in the list.

    I want all the countries to be selected by default.
    Could you help me with this?

  18. Neha says:

    I am using the form:select tag.I could not find any way to select all the options by default.


    I want to select all the countries by default.
    Please advise.

  19. cyril says:

    Excellent tutorial!

  20. matiangul says:

    This is great. I’m new with Spring and it helps me a lot.
    Thank you.

  21. Andrei Asmarandei says:

    @Rick & Draco:

    To solve this you need to add a Converter where you create a new Dim object from the id of type String.

    public class StringToDim implements Converter
    public Dim convert(String source) {
    Dim d = new Dim ();
    return d;

    The Converter must be mapped in like this:
    public void addFormatters(FormatterRegistry registry) {
    registry.addConverter(new StringToDim ());

    Also it’s a good ideea to create equals and hashset methods for class Dim :)

    • Mikko Suonio says:

      @Andrei: Thanks for mentioning the usefulness of equals method here.

      I found that it seems to be necessary for the entity class (Dim in the example above) to have equals defined. Otherwise, the selected attribute of the options is not generated and the current values are not shown as selected. Therefore, it cannot decide to which options the current value is equal to.

    • Keith says:

      This comment unlocked my hours-long problem. All working now. Thanks Andrei.

  22. Tanja Schmidt says:


  23. ammy says:

    Awesome! thanks sooo much for gr8 tutorial.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>