2

The situation: I have a JavaServer Faces page and a session-scoped managed bean that has two ArrayList<Integer> properties: one for holding a list of possible values and another for holding a list of selected values. On the JSF page there is a <h:selectManyListBox> component with these two properties bound.

The problem: after submitting the form the selected values will be converted to string (the property of type ArrayList actually holds a couple of strings!); however, when I use a converter, I get an error message like this:

Validation Error: Value is not valid

The question: How can I bind an ArrayList<Integer> property to the <h:selectManyListBox> component properly?

Thank you for your kind helping me.

The concrete codes

The JSF page:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
    <h:body>
        <h:form>
            <h:selectManyListbox value="#{testBean.selection}">
                <f:selectItems value="#{testBean.list}"></f:selectItems>
            </h:selectManyListbox>
            <h:commandButton action="#{testBean.go}" value="go" />
            <ui:repeat value="#{testBean.selection}" var="i">
                #{i}: #{i.getClass()}
            </ui:repeat>
        </h:form>
    </h:body>
</html>

And the managed bean:

import java.io.Serializable;
import java.util.ArrayList;

@javax.faces.bean.ManagedBean
@javax.enterprise.context.SessionScoped
public class TestBean implements Serializable
{
    private ArrayList<Integer> selection;
    private ArrayList<Integer> list;

    public ArrayList<Integer> getList()
    {
        if(list == null || list.isEmpty())
        {
            list = new ArrayList<Integer>();
            list.add(1);
            list.add(2);
            list.add(3);
        }
        return list;
    }

    public void setList(ArrayList<Integer> list)
    {
        this.list = list;
    }

    public ArrayList<Integer> getSelection()
    {
        return selection;
    }

    public void setSelection(ArrayList<Integer> selection)
    {
        this.selection = selection;
    }

    public String go()
    {
            // This throws an exception: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
            /*for (Integer i : selection)
            {
                System.out.println(i);
            }*/
        return null;
    }
}
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Márton
  • 473
  • 7
  • 13

1 Answers1

8

The generic type information of List<Integer> is lost during runtime and therefore JSF/EL who sees only List is not able to identify that the generic type is Integer and assumes it to be default String (as that's the default type of the underlying HttpServletRequest#getParameter() call during apply request values phase).

You need either to explicitly specify a Converter, you can use JSF builtin IntegerConverter:

<h:selectManyListbox ... converter="javax.faces.Integer">

or just to use Integer[] instead, whose type information is clearly known during runtime:

private Integer[] selection;
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thank you! The code is working properly with the added IntegerConverter. I did not know about [type erasure](http://docs.oracle.com/javase/tutorial/java/generics/erasure.html) until now... – Márton Dec 14 '12 at 09:08
  • @BalusC, thanks, this actually turned out to be the answer to my question [here](http://stackoverflow.com/q/14048382/516433). This can be a painful one to figure out as it presents in strange ways. However, I should have just known better... – Lucas Dec 27 '12 at 21:21
  • Thanks, this is a nice pitfall one has to take care of! Just ran into the same problem with a `Set`- giving strange errors at runtime! – Dominik Sandjaja Jan 25 '13 at 12:46
  • 1 day to figure out about the `ClassCastException` issue arisen when using `List` object in `SelectManyMenu`. thanks alot @BalusC from saving of madness – Nwawel A Iroume Sep 28 '15 at 20:39