2

我目前正在将 Scala 与 JSF 一起使用,这两者配合得很好。但是有时 JSF 需要重新实例化(通过 Class.newInstance)一个数据结构,比如一个列表。例如,在托管 bean 中,我有:

@BeanProperty
var countries: java.util.List[String] = List("US").asJava

直到你进入 JSF 的流程验证阶段,它运行到 java.lang.InstantiationException:

java.lang.InstantiationException: scala.collection.JavaConversions$SeqWrapper
at java.lang.Class.newInstance0(Class.java:340)
at java.lang.Class.newInstance(Class.java:308)
at com.sun.faces.renderkit.html_basic.MenuRenderer.createCollection(MenuRenderer.java:906)
at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValuesForModel(MenuRenderer.java:366)
at com.sun.faces.renderkit.html_basic.MenuRenderer.convertSelectManyValue(MenuRenderer.java:128)
at com.sun.faces.renderkit.html_basic.MenuRenderer.getConvertedValue(MenuRenderer.java:314)
at org.primefaces.component.selectcheckboxmenu.SelectCheckboxMenuRenderer.getConvertedValue(SelectCheckboxMenuRenderer.java:34)
...

从根本上讲,Wrapper 可能不会从头开始重新实例化是有道理的,因此在这里使用 JavaConverters 将无法正常工作。我的问题是有没有包装器已经提供完整的数据结构映射/转换的库?如果没有,我只会写我自己的内部的。

4

1 回答 1

4

使用JavaArrayList作为var,然后在您的代码中使用JavaConverters/JavaConversions来操作。这是我用于需要 Java 集合的 API(如 Hibernate、JAX-WS、JSR-303 等)的常用方法。

import collection.JavaConversions._

@BeanProperty
var countries: java.util.List[String] = new java.util.ArrayList[String] += "US"

或者

import collection.JavaConverters._

@BeanProperty
var countries: java.util.List[String] = new java.util.ArrayList[String]
countries.asScala += "US"
countries.asScala ++= List("US", "MX")

如果您真的只想来回转换而不是包装它很容易,而无需创建自己的类:

import collection.JavaConverters._
import collection.mutable.ArrayBuffer

@BeanProperty
var countries: java.util.List[String] = new java.util.ArrayList[String]

val countriesBuff = new ArrayBuffer.empty[String]
countriesBuff ++= countries.asScala     // Convert from ArrayList to ArrayBuffer
// ...
countries.addAll(countriesBuff.asJava)  // Convert the other direction

但是您必须担心复制成本以及何时需要进行同步。包装/装饰更方便。

于 2012-12-19T03:45:10.497 回答