【问题标题】:JSF/Primefaces Enum Converter in SelectManyCheckboxSelectManyCheckbox 中的 JSF/Primefaces 枚举转换器
【发布时间】:2017-01-13 15:09:11
【问题描述】:

我正在努力寻找为什么这不起作用。

我有一个 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>

控制器有getter/setter,列表的声明和初始化如下:

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

}

因此,当视图和控制器初始化时,它会按预期进行,并且为组件的每个值调用 getAsString,正常打印。 输出:

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

但是,当我提交表单并调用 getAsObject 时,它会在 Enum.valueOf(enumType, value) 上引发 IllegalArgumentException。

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) 有效……

但是这个:Enum.valueOf(enumType, value) 不要。

我必须为我的枚举 CarType 而不是通用的一个显式转换器,以便 selectManyCheckbox 工作。

谁能给我解释一下?提前致谢。

【问题讨论】:

  • 它是否可以使用普通的 jsf 组件而不是 primefaces 组件?如果您隔离此代码并仅在带有“main”的类中使用它怎么办?那么同样的错误呢?
  • 离题提示:开始使​​用 OmniFaces:showcase.omnifaces.org/converters/GenericEnumConverter(以及许多其他有用的工具)
  • 使用 jsf-html h:selectManyCheckbox,同样的错误......同样的行为......我正在运行一个带有 tomcat、hibernate、jsf 和 primefaces 的 Web 应用程序。
  • 所以它与 PrimeFaces 无关,但很可能是普通的 jsf 或其他相关(使用 spring?)。通常,通常的做法是制作一个普通的 jsf xhtml 并删除 PrimeFaces 标签(因为标签是针对问题所在的位置,而不是用于使用什么)。题外话:在process="@this, @form" ,@这是多余的
  • true dat,我忘了删除它,因为我从另一个具有 f:setPropertyActionListener 的按钮复制...感谢您的说明...我没有使用 spring,将尝试一个孤立的 jsf 实验...谢谢。

标签: java jsf primefaces enums converter


【解决方案1】:

这是核心 Java 问题。枚举类CarType 具有抽象方法,每个枚举值都是CarType 子类的实例。见:Java Enum getDeclaringClass vs getClass

解决方法是在getAsString(...)方法中设置((Enum)value).getDeclaringClass()而不是value.getClass()作为属性ATTRIBUTE_ENUM_TYPE

提示:我认为这是类的问题,因为我注意到类名 my.project.enums.CarType$120 中有一个数字。

【讨论】:

    猜你喜欢
    • 2014-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-23
    相关资源
    最近更新 更多