1

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
Jai
  • 352
  • 2
  • 18
  • Please create a [mcve] as requested in [ask]. IMPOSSIBLE for us to help with this piece of code. And the java tag attracts people that might not know JSF or EL. And try with a plain JSF counterpart instead of the PrimeFaces one. Does that work? – Kukeltje Feb 27 '19 at 11:29
  • Error of this link. reversely happening for me after upgrade JSF 2.2 to JSF 2.3. https://stackoverflow.com/questions/21446068/listinteger-received-liststring – Jai Feb 27 '19 at 11:33
  • I understand what is happening, but please, please, please create a [mcve] with a backingbean etc... – Kukeltje Feb 27 '19 at 12:22

2 Answers2

3

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.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
1

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());
  }
}

Adam
  • 1,724
  • 13
  • 16
  • No. As I mentioned The basisList type is . List basisList = new ArrayList(); – Jai Feb 27 '19 at 11:24
  • Well it can't be, otherwise you'd never get that class cast exception. There are Long types in your list. – Adam Feb 27 '19 at 11:26
  • No Adam. Its working fine in JSF 2.2 right. Please read this link https://stackoverflow.com/questions/21446068/listinteger-received-liststring. The error of the link reversely happening for me. – Jai Feb 27 '19 at 11:29
  • Yes, but like the answers say the generic types vanish during compilation and everything is an Object and cast to the different types at run time. That class cast exception indicates to me that the list you presume contains only actually has some Long values in there. I'm not familiar with how JSF works under the hood, but if you add some type checking to your method you might be able to debug what is going on. – Adam Feb 27 '19 at 11:33
  • 1
    @Adam: EL and passing from a webpage to a server might result in 'lists' being interpreted as strings. And yes, there might be something not explicit as a long but it does not have to be the list itself. OP should create a [mcve] and not have used the java tag since this cannot be reproduced in a plain jdk – Kukeltje Feb 27 '19 at 11:33
  • Your debug just confirms what I said in my answer. Your list contains Long types. You need to iterate it as an Object list since you can't guarantee what types you are getting and perform the appropriate checks on your types before operating on them. – Adam Feb 27 '19 at 11:39
  • I understand that. But why its not happen in JSF 2.2 and why am facing error in JSF 2.3. That was my question. – Jai Feb 27 '19 at 11:41
  • @Jai: First show exactly what you did in a [mcve] There might be several reasons behaviour changed including a bug fix which you by accident (unintentionally or by some lack of knowledge) used. – Kukeltje Feb 27 '19 at 12:25