我已将我的项目从JSFContainer 2.2升级到JSFContainer 2.3
<p:selectManyListbox id="acl" value="#{controller.process.basisList}" >
<f:selectItems value="#{controller.filinglist}" />
</p:selectManyListbox>
filinglist有类对象,如ob(1L,'data1');带有泛型类型String的basisList
使用JSFContainer 2.2,CDI 1.2和EL 3.0时。它的工作正常,Long数据已作为String存储在基础列表列表中。我在下面的URL中理解了这个概念
但在JSFContainer 2.3,CDI 2.0和EL 3.0中。我得到了以下错误
当我运行代码
for(String i : basisList) {
System.out.println(i);
}
java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String.
我使用下面的代码调试
for(Object i : basisList) {
System.out.println(i.getClass() + " > " + i);
}
得到的结果如下
class java.lang.Long > 3
从JSF 2.2升级到JSF 2.3时,此行为是正确的。以前,JSF 2.2及更早版本没有自动转换这些实际上不是预期行为的值。
它在UISelectMany
javadoc for JSF 2.3中指定。
使用以下算法获取
Converter
:
- 如果组件附有
Converter
,请使用它。- 如果没有,请查找
ValueExpression
的值(如果有的话)。ValueExpression
必须指向以下内容: 一组基元(如int[]
)。查找已注册的类Converter
以获取此原始类型。 一组对象(例如Integer[]
或String[]
)。查找注册的类Converter
以获取基础元素类型。 一个java.util.Collection
。不要转换值。相反,将提供的可用选项集转换为字符串,与呈现响应期间完全相同,并且对于与提交的值的任何匹配,将可用选项作为对象添加到集合中。如果由于任何原因无法找到
Converter
,则假定该类型为String数组。
自JSF 2.3(比较,here's the JSF 2.2 variant of UISelectMany
javadoc)以来,上述blockquote的重点部分是新的。
你需要修复你的basisList
变成与filinglist
完全相同的类型,否则你需要附加一个明确的Converter
。
你的basisList可能是<Object>
类型,所以当你使用String
创建你的for循环时,Java会尝试将该值转换为String变量i
。在你的情况下,似乎你有一个部分列表,或完全填充原始long
类型,不能只是强制转换为字符串。您可以编写一些这样的代码来支持这两种情况。
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());
}
}