Rich Hightower explains how he set up JSF to use Java Enums but his code can be greatly simplified.
First, instead of manually mapping keys to enum constants, you could add a key parameter to each constant which gets passed to the constructor. See Sun's Enum guide for more info. And then you could loop through MyEnumClass.values() to find what you need for the reverse mapping.
But you don't need to specify keys at all. Using .toString() and Enum.valueOf() work just fine as a key in JSF. (You'll see them used later in the converter.) Besides, putting keys in your Enum just so JSF can use them is mixing presentation and logic. Your Enum class doesn't need anything special to work with JSF.
The backing bean still needs to provide a list of choices for each select box. But we can do it with a generic method.
/** provide all choices from the ColorType enum */
public Map getColorTypeChoices() {
Map<String,ColorType> choices = new HashMap<String,ColorType>();
for (ColorType type : ColorType.values()) {
choices.put(type.getLabel(), type);
}
return choices;
}
And the converter can be improved to a single one-size-fits-all Enum converter.
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
public class EnumTypeConverter implements Converter {
public Object getAsObject(FacesContext context, UIComponent comp,
String value) throws ConverterException {
Class enumType = comp.getValueBinding("value").getType(context);
return Enum.valueOf(enumType, value);
}
public String getAsString(FacesContext context, UIComponent component,
Object object) throws ConverterException {
if (object == null) {
return null;
}
Enum type = (Enum) object;
return type.toString();
}
}
For each enum class, use this as the <converter-class> in faces-config.xml
The JSF tags are straightforward:
<h:selectOneListbox id="colorType" required="true" value="#{formbean.form.colorType}">
<f:selectItems value="#{formbean.colorTypeChoices}" />
</h:selectOneListbox>
Based on all the improvements made here, I'm pretty sure they could be further simplified by creating a selectItemsFromEnum facet. More on that later, hopefully.
name() or ordinal() over a mutable toString(). However, displaying the fully qualified class name to the world is a bit troubling. Is there a fast and lightweight symmetric encryption/hashing/obfuscation algorithm that can be employed to prevent browsers from displaying this?
| Mon | Tue | Wed | Thu | Fri | Sat | Sun |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 |