具有2个成员变量的元组作为唯一ID的对象列表的转换器

时间:2019-06-23 16:45:20

标签: jsf primefaces selectonemenu converters

我正在尝试将list of objects映射到<p:selectOneMenu(如下所示的代码):

Attribute.java

public class Attribute implements Serializable {
 private String name;
 private String type;
 private String value; //getters setters constructors ommitted

@Override
public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Attribute attribute = (Attribute) o;
    return Objects.equals(name, attribute.name) &&
            Objects.equals(type, attribute.type);
}

@Override
public int hashCode() {
    return Objects.hash(name, type, value);
}

p:selectOneMenu代码

 <p:selectOneMenu label="Existing Attributes" value="#{cellBean.selectedAttributeFromExistings}"
                                                 converter="attrConverter">
      <f:selectItem itemLabel="Existing attribute" itemValue="#{null}" itemDisabled="true"/>
      <f:selectItems value="#{cellBean.allAttributes}" var="attr" itemLabel="#{attr.name}" itemValue="#{attr}"/>
  <p:ajax event="change" update="@form" process="@form"/>
  </p:selectOneMenu>

属性转换器(attrConverter)代码

@FacesConverter(forClass=Attribute.class,  value = "attrConverter")
public class AttributeConverter implements Converter {

@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
    String type = s.substring(s.indexOf(":") + 2, s.indexOf(","));
    String name = s.substring(s.indexOf("name: ") + 6 , s.length());
    Attribute attribute = new Attribute(type, name);
    return attribute;
}

@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
    if(attr == null) {
        return null;
    }
    else{
        Attribute attribute = new Attribute();
        String s = "";
        Iterator iterator = ((LinkedTreeMap)attr).keySet().iterator();
        while(iterator.hasNext()){
            String key = (String) iterator.next();
            String value = (String) ((LinkedTreeMap)attr).get(key);
            if(key.equals("name")){
                attribute.setName(value);
            }
            else if(key.equals("type")){
                attribute.setType(value);
            }

        }
        return attribute.toString();
    }
}

但是,当我从下拉菜单中选择一个值时,出现以下异常

  

验证错误:值无效:验证错误:值无效

error message

紧随其后的是错误消息/在屏幕右上角弹出,您知道我在做什么错吗?

PS:我已经看到许多示例,它们使用unique id来通过getAsObject方法中的DTO检索对象,在我的示例中,{ uniqueness对象的{1}}是Attribute个成员变量的组合。

在此先感谢您的帮助:)

2 个答案:

答案 0 :(得分:2)

我不知道为什么将attr强制转换为LinkedTreeMap类,您需要将其强制转换为Attribute类。所以您的转换器类应该是:

@FacesConverter(forClass=Attribute.class,  value = "attrConverter")
public class AttributeConverter implements Converter {

 @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {

        if (value != null && value.trim().length() > 0 && !value.isEmpty()) {
         /*I take your bean as ViewScoped */
            CellBean cellBean = (CellBean) context.getViewRoot().getViewMap().get("cellBean");
            for(Attribute a : cellBean.getAllAttributes()){
                String combined = a.getType()+a.getValue();
                if(combined.equals(value)){
                    return a;
                }
            }
        }
        return null;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value)            {
        if (value != null) {
            Attribute a = (Attribute) value;
            return a.getType()+a.getValue();
        }
        return null;
    }
}

更新

面向问询者:

@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
    String[] typeAndName = s.split("#");
    return new Attribute(typeAndName[0], typeAndName[1]);

}

@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
    if(attr == null) {
        return null;
    }
    else{
        /* I assume your type and name don't contain '#' charachter */
        return ((Attribute)attr).getType()+"#"+((Attribute)attr).getName();
    }
}

答案 1 :(得分:0)

问题的根源是我使用gson进行了错误的序列化,我将Attribute对象转换为LinkedTreeMap,这也是注释部分中提到的缺点。当我正确进行序列化时,getAsObjectgetAsString函数具有以下形式:

@Override
public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String s) {
    String type = s.substring(s.indexOf("type=") + 5, s.indexOf(" "));
    String name = s.substring(s.indexOf("name=") + 5 , s.length());
    Attribute attribute = new Attribute(type, name);
    return attribute;

}

@Override
public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object attr) {
    if(attr == null) {
        return null;
    }
    else{
        return "type="+((Attribute)attr).getType()+" name="+((Attribute)attr).getName();
    }
}