Jai
Jai

Reputation: 352

List<String> Received List<Long> in JSF 2.3

I have Upgrade my project from JSFContainer 2.2 to JSFContainer 2.3

<p:selectManyListbox id="acl" value="#{controller.process.basisList}" >  
    <f:selectItems value="#{controller.filinglist}" />  
</p:selectManyListbox> 

filinglist has class object like ob(1L, 'data1'); basisList with generic type String

when working with JSFContainer 2.2, CDI 1.2 and EL 3.0. it's working fine the Long data has been stored as String in basisList List. I understand the this concept in below URL

Java Reflection API

But in JSFContainer 2.3, CDI 2.0 and EL 3.0. I got the below error

when I run the code

for(String i : basisList) {
    System.out.println(i);
}

java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String.

I debug using below code

for(Object i : basisList) {
        System.out.println(i.getClass() + " > " + i);
    }

The output what am getting is below

class java.lang.Long > 3

Upvotes: 1

Views: 820

Answers (2)

BalusC
BalusC

Reputation: 1108642

This behavior is correct when you upgrade from JSF 2.2 to JSF 2.3. Previously, JSF 2.2 and older didn't auto-convert these values which was actually not the expected behavior.

It's specified in UISelectMany javadoc for JSF 2.3.

Obtain the Converter using the following algorithm:

  • If the component has an attached Converter, use it.

  • If not, look for a ValueExpression for value (if any). The ValueExpression must point to something that is:

    • An array of primitives (such as int[]). Look up the registered by-class Converter for this primitive type.

    • An array of objects (such as Integer[] or String[]). Look up the registered by-class Converter for the underlying element type.

    • A java.util.Collection. Do not convert the values. Instead, convert the provided set of available options to string, exactly as done during render response, and for any match with the submitted values, add the available option as object to the collection.

If for any reason a Converter cannot be found, assume the type to be a String array.

The emphasized section of the above blockquote is new since JSF 2.3 (to compare, here's the JSF 2.2 variant of UISelectMany javadoc).

You need to fix your basisList to become of exactly same type as filinglist, or else you'll need to attach an explicit Converter.

Upvotes: 3

Adam
Adam

Reputation: 1754

You basisList is probably of type <Object> so when you create your for loop with a String Java tries to cast that value into the String variable i. In your case it seems that you have a list partially, or fully filled with primitive long types which can't just be cast to a string. You could write some code like this which would support both cases.

List<Object> basisList = new ArrayList<>();

for (Object o : basisList) {
  if (o instanceof String) {
    System.out.println(o.toString());
  } else if(o instanceof Long){
    System.out.println(Long.toString((Long) o));
  } else {
    System.out.println("Some other type = " + o.toString());
  }
}

Upvotes: 1

Related Questions