2017-01-13 5 views
0

Я пытаюсь найти, почему это не работает.Конвертер JSF/Primefaces Enum в SelectManyCheckbox

У меня есть 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> 

Контроллер геттеры/сеттеры и списки объявляются и инициализируются следующим образом:

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); 
} 

перечисление является основной материал:

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(); 
    } 
} 

И, наконец, вот конвертер, который я получил из другой справки stackoverflow ...

@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)); 
    } 
} 

} 

Так как вид и контроллер inits, это сделать, как ожидалось, и getAsString вызывается для каждого значения компонента, отпечатков нормально. Выход:

value: Cool but Hot Off the Road 
value: Holy moly a Monster Truck 
... 

Но, когда я отправить форму, и getAsObject называется, он бросает IllegalArgumentException на Enum.valueOf (enumType, значение).

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 

Странная вещь ... это: CarType.valueOf(value) Works ...

Но это: Enum.valueOf(enumType, value) не делать.

Мне нужно было сделать явный конвертер для моего перечисления CarType вместо Generic для работы selectManyCheckbox.

Может ли кто-нибудь объяснить это мне? Заранее спасибо.

+0

Работает ли простой компонент jsf вместо обычного? Что делать, если вы изолируете этот код и просто используете его в классе с «основным»? Те же ошибки? – Kukeltje

+0

Совет по использованию темы: Начало использования OmniFaces: http: //showcase.omnifaces.org/converters/GenericEnumConverter (и множество других полезных инструментов) – Kukeltje

+0

с jsf-html h: selectManyCheckbox, та же ошибка ... такое же поведение ... Я запускаю веб-приложение с tomcat, hibernate, jsf и primefaces. –

ответ

1

Это основная проблема Java. Класс Enum CarType имеет абстрактный метод, и каждое значение перечисления является экземпляром подкласса CarType. См: Java Enum getDeclaringClass vs getClass

Решение заключается в установлении ((Enum)value).getDeclaringClass() вместо value.getClass() в качестве атрибута ATTRIBUTE_ENUM_TYPE в getAsString(...) методе.

Совет: Я предполагаю, что это проблема с классом сразу, потому что я замечаю номер в классе my.project.enums.CarType$120.