I'm just trying out JSF an ran into an ugly ClassCastException.
I have a Managed Bean (CustomerBean) that has a POJO (Customer) where I store the user data. One of the POJO's properties is List<CathegoryType.Type> preferredCathegories (with getter and setter). CathegoryType is a model class which provides cathegories (through a nested enum Type) and their localized names (through a method getCathegory(Type type)).
Now, I have one JSF page to enter some user data (editCustomer.xhtml). There is a section to select preferred cathegories. The JSF code to select the cathegories looks like this:
<h:selectManyListbox
id="pcat"
value="#{customerBean.customer.preferredCathegories}"
styleClass="form-control">
<f:selectItems
value="#{customerBean.cathegoryTypes}">
</f:selectItems>
</h:selectManyListbox>
The renderes component looks like this:

The field List<SelectItem> CustomerBeand.cathegoryTypes provides the mapping of the enum literals to their names like new SelectItem(type, CathegoryType.getCathegory(type)). Now there comes the tricky part that throws the ClassCastException (in my understanding for no reason!)
When I submit the form an other JSF page (showCustomer.xhtml) is should present the just entered user data. But creating the view terminates with throwing the following 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)
...
To present the chosen cathegories, showCustomer.xhtml calls a method String CustomerBean.getNamedPreferredCathegories():
<h:outputText value="#{customerBean.namedPreferredCathegories}" />
This method calculates a String of the chosen cathegories:
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
}
I'm using the Xtend programming languate. It is a JVM language (compiles to Java code) and thus fully compatible with the Java typesystem. I tried to write this method as Java like as possible, normally it can be done in one single line:
def String getNamedPreferredCathegories() {
'''«FOR name : customer.preferredCathegories.map[cathegory] SEPARATOR ', '»«name»«ENDFOR»'''.toString
}
Since I do any iteration over the list, the ClassCastException is thrown ... but as one can see, I do not perform any cast operation in my code! So where does the exception comes from?
I run the project on Tomcat 8.5.9.
Edit: Ok, the generated Java method of my Xtend method is theo following:
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();
}
The exception is thrown in the marked line (final CathegoryType.Type cat = iter.next();). Additionally the generated Java parts of the related Customer class are this:
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;
}
}
Additionally, I will have a look at the linked question that might discuss the exact same problem.