I'm struggling to find why this don't works.
I have a selectManyCheckbox
<h:form>
<p:selectManyCheckbox id="listCars" value="#{controller.listSelectedCarTypes}" converter="genericEnumConverter">
<f:selectItems value="#{controller.listCarTypeValues}" />
</p:selectManyCheckbox>
<p:commandButton value="Pesquisar" action="#{controller.filter}" process="@this, @form" update="panelResults" icon="ui-icon-search"/>
</h:form>
The controller has getters/setters and the Lists are declared and initialized as follows:
private List<CarType> listSelectedCarTypes = null;
private List<CarType> listCarTypeValues = null;
@PostConstruct
public void init(){
listSelectedCarTypes = new ArrayList<CarType>();
listCarTypeValues = new ArrayList<CarType>();
listCarTypeValues.add(CarType.OFF_ROAD);
listCarTypeValues.add(CarType.CONVERSIBLE);
listCarTypeValues.add(CarType.TRUCK);
}
The Enum is basic stuff:
public enum CarType {
OFF_ROAD {
@Override
public String getDescription() {
return "Cool but Hot Off the Road"
}
},
TRUCK {
@Override
public String getDescription() {
return "Holy moly a Monster Truck"
}
}
// lots of enums...
;
public abstract String getDescription();
@Override
public String toString() {
return getDescription();
}
}
And finally, here is the converter I got from another stackoverflow reference...
@FacesConverter(value="genericEnumConverter")
public class GenericEnumConverter implements Converter {
private static final String ATTRIBUTE_ENUM_TYPE = "GenericEnumConverter.enumType";
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
System.out.println("value: "+value);
if (value instanceof Enum) {
component.getAttributes().put(ATTRIBUTE_ENUM_TYPE, value.getClass());
return ((Enum<?>) value).name();
} else {
throw new ConverterException(new FacesMessage("Value is not an enum: " + value.getClass()));
}
}
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public Object getAsObject(FacesContext context, UIComponent component, String value) {
Class<Enum> enumType = (Class<Enum>) component.getAttributes().get(ATTRIBUTE_ENUM_TYPE);
try {
System.out.println("enumType: "+enumType+ " value: "+value);
System.out.println("CarType.valueOf(value): "+CarType.valueOf(value));
System.out.println("Enum.valueOf(enumType, value): "+Enum.valueOf(enumType, value));
return Enum.valueOf(enumType, value);
} catch (IllegalArgumentException e) {
throw new ConverterException(new FacesMessage("Value is not an enum of type: " + enumType));
}
}
}
So as the view and the controller inits, it do as expected and getAsString is called for each value of the component, prints normally. Output:
value: Cool but Hot Off the Road
value: Holy moly a Monster Truck
...
But, when I submit the form, and getAsObject is called, it throws IllegalArgumentException on Enum.valueOf(enumType, value).
enumType: class my.project.enums.CarType$120 value: TRUCK
CarType.valueOf(value): Holy moly a Monster Truck
Value is not an enum of type: class my.project.enums.CarType$120
The weird thing is... this: CarType.valueOf(value) Works...
But this: Enum.valueOf(enumType, value) Don't.
I had to make an explicit converter for my enum CarType instead of the Generic one in order for the selectManyCheckbox to works.
Can anyone explain that to me? Thanks in advance.
process="@this, @form", @this is superfluous - Kukeltje