私はちょうど醜いに遭遇したJSFを試していClassCastException
ます。
ユーザーデータを格納CustomerBean
する POJO ( ) を持つManaged Bean ( ) があります。Customer
POJO のプロパティの 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>
このフィールド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;
}
}
さらに、まったく同じ問題について説明している可能性のあるリンクされた質問を見ていきます。