Я знаю, что этот вопрос немного старше, но у меня возникла та же проблема, и я нашел другое решение, которым хочу поделиться:
Создайте пользовательский EL-Resolver и используйте перечисления и java-константы в качестве объектов в jsf el:
<h:graphicImage name="error.png" library="images"
rendered="#{viewController.current.status == Status.ERROR}" />
Но прежде чем вы сможете использовать перечисления таким образом, вы должны сделать 3 шага.
1. шаг - скопируйте этот класс и замените «MY_ENUM» через ваш enumClass (в приведенном выше примере это будет «Status»)
public class EnumCache {
private Map<String, Object> propertCache = new HashMap<String, Object>();
private Map<String, Class> baseCache = new HashMap<String, Class>();
private static EnumCache staticEnumCache = null;
public static EnumCache instance() {
if (staticEnumCache == null) { staticEnumCache = new EnumCache(); }
return staticEnumCache;
}
private EnumCache() {
List<Class<?>> classes = new ArrayList<Class<?>>();
classes.add(MY_ENUM.class);
for(Class clazz : classes) {
try {
baseCache.put(clazz.getSimpleName(), clazz);
Method m = clazz.getMethod("values", (Class[]) null);
Enum<?>[] valueList = (Enum[]) m.invoke(null, (Object[]) null);
for (Enum<?> en : valueList) {
propertCache.put(clazz.getSimpleName() + "." + en.name(), en);
}
} catch (Exception e) {
System.err.println(clazz.getSimpleName(), e);
}
}
}
public Object getValueForKey(String key) {
return propertCache.get(key);
}
public Class getClassForKey(String key) {
return baseCache.get(key);
}
}
2. шаг - добавьте этот EnumResolver - этот класс сопоставит ваше выражение JSF с перечислением в кэше (шаг 1)
public class MyEnumResolver extends ELResolver {
public Object getValue(ELContext context, Object base, Object property) {
Object result = null;
if (base == null) {
result = EnumCache.instance().getClassForKey(property + "");
} else if (base instanceof Class) {
result = EnumCache.instance().getValueForKey(((Class) base).getSimpleName() + "." + property);
}
if (result != null) {
context.setPropertyResolved(true);
}
return result;
}
public Class<?> getCommonPropertyType(ELContext context, Object base) {
return null;
}
public Iterator<FeatureDescriptor> getFeatureDescriptors(ELContext context, Object base) {
return null;
}
public Class<?> getType(ELContext context, Object base, Object property) {
return null;
}
public boolean isReadOnly(ELContext context, Object base, Object property) {
return false;
}
public void setValue(ELContext context, Object base, Object property, Object arg3) {
}
}
3. шаг - зарегистрируйте EnumResolver в face-config.xml
<faces-config>
<application>
<el-resolver>com.asd.MyEnumResolver</el-resolver>
</application>
</faces-config>
Примечание:
Если вы хотите получить доступ к своим Java-константам таким образом, вам просто нужно расширить конструктор класса enumCache.
Этот (непроверенный) пример должен работать:
baseCache.put(CLASS_WITH_CONSTANTS.getSimpleName(), clazz);
for (Field field : CLASS_WITH_CONSTANTS.getDeclaredFields()) {
try {
propertCache.put(CLASS_WITH_CONSTANTS.getSimpleName() + "."
+ field.getName(), field.get(null));
} catch (Exception e) { }
}
Надеюсь, этот сокращенный, но работающий код может кому-нибудь помочь.
Обновление
Я вижу это преимущество:
Если вы используете строки в jsf (viewController.current.status == 'ERROR_abcdefg'), вы можете неправильно ввести значение и не сможете его быстро распознать.
С моим решением вы получите ошибку при загрузке файла jsf, потому что enum не может быть разрешен.
Вы можете видеть в исходном коде, что "ERROR" является значением перечисления "STATUS".
Когда вы сравниваете два значения в el, класс перечислений тоже будет сравниваться.
Так, например, PersonState.ACTIV отличается от AccounState.ACTIV.
Когда мне нужно изменить значение моего перечисления с PersonState.ACTIV на PersonState.ACTIVATED, я могу найти строку «PersonState.ACTIV» в моем исходном коде. поиск "ACTIV" будет иметь гораздо больше совпадений.