【问题标题】:JSF with Enum 'Validation Error: Value is not valid'带有枚举“验证错误:值无效”的 JSF
【发布时间】:2011-02-02 16:21:31
【问题描述】:

我有一个枚举,它的代码是这样的 -

public enum COSOptionType {

    NOTAPPLICABLE,
    OPTIONAL,
    MANDATORY;

    private String[] label = { "Not Applicable", "Optional", "Mandatory"};

    @Override
    public String toString() {

        return label[this.ordinal()];
    }

    public static COSOptionType getCOSOption(String value) {
        int ivalue = Integer.parseInt(value);
        switch(ivalue) {
        case 0:
            return NOTAPPLICABLE;
        case 1: 
            return OPTIONAL;
        case 2:
            return MANDATORY;
         default:
                throw new RuntimeException("Should not get this far ever!");
        }
    }

}

我有转换器来转换枚举类型

public class COSEnumConverter implements Converter {

    public Object getAsObject(FacesContext context, UIComponent comp, String value) {

        return COSOptionType.getCOSOption(value);
    }

    public String getAsString(FacesContext context, UIComponent comp, Object obj) {
        if (obj instanceof String) {
            return (String) obj;
        }
        COSOptionType type = (COSOptionType) obj;
        int index = type.ordinal();
        return ""+index;
    }

}

视图是这样的

 <h:selectOneMenu value="#{controller.type}" id="smoking">                                           
   <f:selectItems value="#{jnyController.choices}" />
 </h:selectOneMenu>

这里是创建选择的代码

private List<SelectItem> createChoicies() {
    List<SelectItem> list = new ArrayList<SelectItem>();
    for (COSOptionType cos : COSOptionType.values()) {
        SelectItem item = new SelectItem();
        item.setLabel(cos.toString());
        item.setValue("" + cos.ordinal());
        list.add(item);
    }
    return list;
}

我不明白为什么这会一直抛出“验证错误”?我可以调试一下,发现转换器工作正常。

NOTE: I am using JSF 1.1

【问题讨论】:

    标签: jsf


    【解决方案1】:

    根本原因是转换器返回了一个完整的COSOptionType 对象,而不是getAsObject() 中的字符串"" + cos.ordinal(),因此在现有选项中根本不会出现。

    无论如何,这种方法过于复杂,尤其是枚举和转换器。我建议您重新考虑这种方法,如下所示:

    Option:

    package com.example;
    
    public enum Option {
    
        NOTAPPLICABLE("Not Applicable"),
        OPTIONAL("Optional"),
        MANDATORY("Mandatory");
    
        private String label;
    
        private Option(String label) {
            this.label = label;
        }
    
        public String getLabel() {
            return label;
        }
    
    }
    

    Bean:

    package com.example;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.faces.model.SelectItem;
    
    public class Bean {
    
        private List<SelectItem> options = new ArrayList<SelectItem>();
        private Option option;
    
        public Bean() {
            for (Option option : Option.values()) {
                options.add(new SelectItem(option, option.getLabel()));
            }
        }
    
        public void submit() {
            System.out.println(option);
        }
    
        public List<SelectItem> getOptions() {
            return options;
        }
    
        public Option getOption() {
            return option;
        }
    
        public void setOption(Option option) {
            this.option = option;
        }
    
    }
    

    OptionConverter:

    package com.example;
    
    import javax.faces.component.UIComponent;
    import javax.faces.context.FacesContext;
    import javax.faces.convert.Converter;
    
    public class OptionConverter implements Converter {
    
        @Override
        public Object getAsObject(FacesContext context, UIComponent component, String value) {
            return Option.valueOf(value);
        }
    
        @Override
        public String getAsString(FacesContext context, UIComponent component, Object value) {
            return ((Option) value).name();
        }
    
    }
    

    faces-config.xml:

    <managed-bean>
        <managed-bean-name>bean</managed-bean-name>
        <managed-bean-class>com.example.Bean</managed-bean-class>
        <managed-bean-scope>request</managed-bean-scope>
    </managed-bean>
    
    <converter>
        <converter-class>com.example.OptionConverter</converter-class>
        <converter-for-class>com.example.Option</converter-for-class>
    </converter>
    

    JSF页面的相关部分:

    <h:form>
        <h:selectOneMenu value="#{bean.option}">                                           
            <f:selectItems value="#{bean.options}" />
        </h:selectOneMenu>
        <h:commandButton value="submit" action="#{bean.submit}" />
        <h:messages />
    </h:form>
    

    无需与被认为是邪恶的Enum#ordinal() 纠缠。

    如果您使用的是 JSF 1.2 或更新版本,它带有内置的通用 EnumConverterOptionConverter 完全是多余的,可以安全地删除。

    【讨论】:

      【解决方案2】:

      尝试item.setValue(cos) 而不是item.setValue("" + cos.ordinal())

      【讨论】:

      • 很奇怪,你的转换器的getAsString() 完全一样。
      • 啊,我明白了,根本原因是转换器在getAsObject() 中返回了一个完整的COSOptionType 而不是"" + cos.ordinal(),因此在现有选项中根本不会出现。跨度>
      猜你喜欢
      • 2021-11-22
      • 2017-11-10
      • 2011-09-13
      • 2013-05-20
      • 2011-06-01
      • 1970-01-01
      • 2017-10-31
      • 2010-09-06
      相关资源
      最近更新 更多