0

私はちょうど醜いに遭遇したJSFを試していClassCastExceptionます。

ユーザーデータを格納CustomerBeanする POJO ( ) を持つManaged Bean ( ) があります。CustomerPOJO のプロパティの 1 つにList<CathegoryType.Type> preferredCathegories(getter と setter を使用) があります。CathegoryTypeは、カテゴリ (ネストされた を使用enum Type) とそのローカライズされた名前 ( メソッドを使用getCathegory(Type type)) を提供するモデル クラスです。

これで、ユーザー データを入力するための 1 つの JSF ページができました ( editCustomer.xhtml)。優先カテゴリを選択するセクションがあります。カテゴリを選択する JSF コードは次のようになります。

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

renderes コンポーネントは次のようになります。 renderes <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は、選択されたカテゴリを計算します。

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 のように記述しようとしましたが、通常は 1 行で記述できます。

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

リストに対して反復処理を行っているため、ClassCastExceptionがスローされます ... しかし、ご覧のとおり、コード内でキャスト操作を実行していません! では、例外はどこから来るのでしょうか?

Tomcat 8.5.9 でプロジェクトを実行します。

編集: OK、私の 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();ます。さらに、関連するクラスの生成された Java 部分は次のCustomerとおりです。

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