0

我只是在尝试 JSF 并遇到了一个丑陋的ClassCastException.

我有一个托管 Bean ( CustomerBean),它有一个 POJO ( Customer),用于存储用户数据。POJO 的属性之一是List<CathegoryType.Type> preferredCathegories(带有getter 和setter)。CathegoryType是一个模型类,它提供分类(通过嵌套enum Type)及其本地化名称(通过方法getCathegory(Type type))。

现在,我有一个 JSF 页面来输入一些用户数据 ( editCustomer.xhtml)。有一个部分可以选择首选类别。选择类别的 JSF 代码如下所示:

<h:selectManyListbox 
        id="pcat"
        value="#{customerBean.customer.preferredCathegories}"
        styleClass="form-control">
    <f:selectItems 
            value="#{customerBean.cathegoryTypes}">
    </f:selectItems>
</h:selectManyListbox>

渲染组件如下所示: 渲染 <code>selectMAnyListBox</code>

该字段List<SelectItem> CustomerBeand.cathegoryTypes提供枚举文字到它们的名称的映射,例如new SelectItem(type, CathegoryType.getCathegory(type)). 现在有一个棘手的部分抛出ClassCastException(在我的理解中无缘无故!)

当我提交表单时,另一个 JSF 页面 ( showCustomer.xhtml) 应该会显示刚刚输入的用户数据。但是创建视图会以抛出以下 ClassCastException 终止:

SCHWERWIEGEND: Servlet.service() for servlet [Faces Servlet] in context with path [/...] threw exception [java.lang.String cannot be cast to ...CathegoryType$Type] with root cause
java.lang.ClassCastException: java.lang.String cannot be cast to ...CathegoryType$Type
    at ...CustomerBean.getNamedPreferredCathegories(CustomerBean.java:247)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    ...

要呈现所选类别,showCustomer.xhtml请调用方法String CustomerBean.getNamedPreferredCathegories()

<h:outputText value="#{customerBean.namedPreferredCathegories}" />

此方法计算String所选类别的 a:

def String getNamedPreferredCathegories() {
    val StringBuilder names = new StringBuilder
    val List<CathegoryType.Type> cathegories = customer.preferredCathegories
    val ListIterator<CathegoryType.Type> iter = cathegories.listIterator
    var boolean first = true
    while (iter.hasNext) {
        val CathegoryType.Type cat = iter.next
        val String name = cathegoryType.getCathegory(cat)
        if(first) first = false else names.append(', ')
        names.append(name)
    }
    return names.toString
}

我正在使用Xtend编程语言。它是一种 JVM 语言(编译为 Java 代码),因此与Java 类型系统完全兼容。我尝试尽可能将这种方法编写为 Java,通常它可以在一行中完成:

def String getNamedPreferredCathegories() {
    '''«FOR name : customer.preferredCathegories.map[cathegory] SEPARATOR ', '»«name»«ENDFOR»'''.toString
}

因为我对列表进行了任何迭代,所以ClassCastException抛出了......但正如人们所看到的,我没有在我的代码中执行任何强制转换操作!那么异常从何而来?

我在 Tomcat 8.5.9 上运行该项目。

编辑: 好的,我的 Xtend 方法生成的 Java 方法如下:

public String getNamedPreferredCathegories() {
    final StringBuilder names = new StringBuilder();
    final List<CathegoryType.Type> cathegories = this.customer.getPreferredCathegories();
    final ListIterator<CathegoryType.Type> iter = cathegories.listIterator();
    boolean first = true;
    while (iter.hasNext()) {
        {
            final CathegoryType.Type cat = iter.next(); // Exception is thrown here!
            final String name = this.cathegoryType.getCathegory(cat);
            if (first) {
                first = false;
            } else {
                names.append(", ");
            }
            names.append(name);
        }
    }
    return names.toString();
}

异常在标记行 ( final CathegoryType.Type cat = iter.next();) 中引发。Customer此外,相关类的生成的 Java 部分是这样的:

public class Customer {

    private List<CathegoryType.Type> preferredCathegories;

    public List<CathegoryType.Type> getPreferredCathegories() {
        return this.preferredCathegories;
    }

    public void setPreferredCathegories(final List<CathegoryType.Type> preferredCathegories) {
        this.preferredCathegories = preferredCathegories;
    }
}

此外,我将查看可能讨论完全相同问题的链接问题。

4

0 回答 0