我想在<h:selectManyCheckbox>使用枚举值。该复选框被正确填充,但是,选择一些值,并利用他们的时候,他们的运行时类型String,而不是枚举。我的代码:

<h:selectManyCheckbox value="#{userController.roles}" layout="pageDirection">
     <f:selectItems value="#{userController.rolesSelectMany}" />
</h:selectManyCheckbox>

UserController类(SecurityRole是枚举类型):

public SelectItem[] getRolesSelectMany() {
    SelectItem[] items = new SelectItem[SecurityRole.values().length];

    int i = 0;
    for (SecurityRole role : SecurityRole.values()) {
        items[i++] = new SelectItem(role, role.toString());
    }
    return items;
}     

public List<SecurityRole> getRoles() {
     getCurrent().getRoles();
}

public void setRoles(List<SecurityRole> roles) {
     getCurrent().setRoles(roles);
}

当JSF调用setRoles方法,它包含String类型的列表,而不是枚举类型。有任何想法吗?谢谢!

有帮助吗?

解决方案

此问题并没有特别涉及到枚举。你将不得不与这些JSF已经内置转换器等List类型,例如同样的问题List<Integer>List<Double>,等等。

的问题是,EL操作运行时和运行时期间一般类型信息丢失。因此,在本质上,JSF / EL并不知道即将List参数化类型的String,默认的东西,除非明确Converter另有规定。从理论上讲,它会用肮脏的反射黑客用的 ParameterizedType#getActualTypeArguments() ,但JSF / EL开发者可具有其对于不这样做的原因。

您真的需要显式定义转换这个。由于JSF已经附带了一个内置的 EnumConverter (这是不是在该特定情况下可使用的独立的,因为你必须指定运行期间,枚举类型),如下你可以只延伸它:

package com.example;

import javax.faces.convert.EnumConverter;
import javax.faces.convert.FacesConverter;

@FacesConverter(value="securityRoleConverter")
public class SecurityRoleConverter extends EnumConverter {

    public SecurityRoleConverter() {
        super(SecurityRole.class);
    }

}

和使用它如下所示:

<h:selectManyCheckbox value="#{userController.roles}" converter="securityRoleConverter">
    <f:selectItems value="#{userController.rolesSelectMany}" />
</h:selectManyCheckbox>

<h:selectManyCheckbox value="#{userController.roles}">
    <f:converter converterId="securityRoleConverter" />
    <f:selectItems value="#{userController.rolesSelectMany}" />
</h:selectManyCheckbox>

一个位更通用的(和哈克)的解决办法是存储枚举类型作为组分属性。

package com.example;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;

@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) {
        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 {
            return Enum.valueOf(enumType, value);
        } catch (IllegalArgumentException e) {
            throw new ConverterException(new FacesMessage("Value is not an enum of type: " + enumType));
        }
    }

}

这是对使用转换器ID List<Enum>各种genericEnumConverter的可用。对于List<Double>List<Integer>等人会使用内置的转换器javax.faces.Doublejavax.faces.Integer等。内置的枚举转换器是由方式不适合,因为不能以指定从上观看侧目标枚举类型(一个Class<Enum>)。 JSF的工具库 OmniFaces 提供的正是这种转换器的开箱

注意,对于一个正常的Enum属性,内建EnumConverter已经足够了。 JSF将与正确的目标枚举类型自动地实例化。

其他提示

在某些情况下的列表也可以同样是阵列的 SOMETYPE [] 下,并且在这种情况下,不需要显式转换器。

通用擦除是把仿制药到语言没有打破旧的东西的一个聪明的办法,但现在我们该决定...

的后果永远活
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top