【问题标题】:JSF Converter Validation Error: Value not validJSF 转换器验证错误:值无效
【发布时间】:2013-05-20 01:31:29
【问题描述】:

我有一个rich:pickList,当提交值时它仍然显示错误:“验证错误:值无效”。我也设置断点调试(getAsobject),但系统调用后我什么都没有。

BalusC 说我会在我的实体中实现 equals() 方法,或者我在 Web 服务中拥有实体,然后我用来自该 Web 服务的数据填充选项列表的右侧。

xHTML 文件

            <h:form>
                <rich:panel>
                    <h:panelGrid columns="2" styleClass="criteresSaisie"
                        rowClasses="critereLigne" columnClasses="titreColonne,">

                        <h:outputLabel for="libelleComplement" value="           "
                            size="20" />
                        <rich:pickList id="libelleComplement" sourceCaption="Compléments"
                            targetCaption="Compléments sélectionnés"
                            value="#{listeCmpltDispoModel.listeCmpltSelect}" size="15"
                            addText="&gt;" addAllText="&gt;&gt;" removeText="&lt;"
                            removeAllText="&lt;&lt;" listWidth="270px" listHeight="110px"
                            orderable="true">
                            <f:selectItems value="#{listeCmpltDispoModel.listeCmpltDispo}"
                                var="liste" itemLabel="#{liste.libelleComplement}"
                                itemValue="#{liste}" />
                            <f:converter converterId="cmpltsTitresConcerter" />
                        </rich:pickList>
                    </h:panelGrid>

                    <h:panelGroup>
                        <div align="right">
                            <h:panelGrid columns="8">
                                <h:commandButton value="Valider"
                                    action="#{saisieCmpltsTitreCtrl.valider}" />
                            </h:panelGrid>
                        </div>
                    </h:panelGroup>

                </rich:panel>
            </h:form>

转换器

@FacesConverter(value="cmpltsTitresConcerter")
public class CmpltsTitresConcerter implements Converter
{

public Object getAsObject(FacesContext context, UIComponent component, String value)
{
    ComplementsDispoSortieDTO cmpltSelect= new ComplementsDispoSortieDTO();
    if(value != null)
    {
        cmpltSelect.setCdComplement(Long.parseLong(value));
        //cmpltSelect.setLibelleComplement("aaa");
    }

    return cmpltSelect;
}

public String getAsString(FacesContext arg0, UIComponent arg1, Object obj)
{
    String result = null;

    if(obj != null)
    {
        result = String.valueOf(((ComplementsDispoSortieDTO) obj).getCdComplement());
    }

    return result;
}
}

型号

@ManagedBean(name = "listeCmpltDispoModel")
@SessionScoped
public class ListeCmpltDispoModel implements Serializable {
private static final long serialVersionUID = 1L;

private Long cdComplement;
private String libelleComplement;
private int nbCompl;

private List<ComplementsDispoSortieDTO> listeCmpltDispo ;
private List<ComplementsDispoSortieDTO> listeCmpltSelect ;

public ListeCmpltDispoModel() {
}

public Long getCodeComplement() {
    return cdComplement;
}

public void setCodeComplement(Long cdComplement) {
    this.cdComplement = cdComplement;
}

public String getLibelleComplement1() {
    return libelleComplement;
}

public void setLibelleComplement1(String libelleCoplement) {
    this.libelleComplement = libelleCoplement;
}

public Long getCdComplement() {
    return cdComplement;
}

public void setCdComplement(Long cdComplement) {
    this.cdComplement = cdComplement;
}


public String getLibelleComplement() {
    return libelleComplement;
}

public void setLibelleComplement(String libelleComplement) {
    this.libelleComplement = libelleComplement;
}

public List<ComplementsDispoSortieDTO> getListeCmpltDispo() {
    return listeCmpltDispo;
}

public void setListeCmpltDispo(List<ComplementsDispoSortieDTO> listeCmpltDispo) {
    this.listeCmpltDispo = listeCmpltDispo;
}

public int getNbCompl() {
    return nbCompl;
}

public void setNbCompl(int nbCompl) {
    this.nbCompl = nbCompl;
}

public List<ComplementsDispoSortieDTO> getListeCmpltSelect() {
    return listeCmpltSelect;
}

public void setListeCmpltSelect(List<ComplementsDispoSortieDTO> listeCmpltSelect) {
    this.listeCmpltSelect = listeCmpltSelect;
}

@Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result
            + ((cdComplement == null) ? 0 : cdComplement.hashCode());
    result = prime
            * result
            + ((libelleComplement == null) ? 0 : libelleComplement
                    .hashCode());
    result = prime * result
            + ((listeCmpltDispo == null) ? 0 : listeCmpltDispo.hashCode());
    result = prime
            * result
            + ((listeCmpltSelect == null) ? 0 : listeCmpltSelect.hashCode());
    result = prime * result + nbCompl;
    return result;
}

@Override
public boolean equals(Object obj){
    if(!(obj instanceof ComplementsDispoSortieDTO)){
        return false;
    }
    return ((ComplementsDispoSortieDTO)obj).getCdComplement()==this.cdComplement;
}
}

【问题讨论】:

  • 你自己已经给出了答案。究竟是什么问题?如果您已经知道这是可能的原因之一,为什么不显示ComplementsDispoSortieDTOequals()
  • 我实现了它,我仍然有同样的问题,问题是:如果我没有访问实体,我在哪里可以实现equals()?
  • 如果您无权访问实体,您是如何实现它的?
  • 我放到Model里面(我编辑的),是这样的吗?
  • 我调用一个网络服务来获取数据

标签: jsf richfaces


【解决方案1】:

您的实体的equals() 方法不对。它不仅在错误的类中(支持 bean 类而不是模型类),而且还在 Object 上使用了 ==(对象上的 == 只测试引用,而不是内部值;因为作为初学者,您应该已经在 String 值上遇到过这个错误)。

Long 上的 == 只会返回 trueLong 实例是由 Long#valueOf()Long#parseLong() 创建的 并且该值介于 -128 和 127 之间. 任何其他内容,包括 new Long(value) 和值超出给定“flyweight”范围的值,返回 false

与所有其他 Java 对象(例如您当前的对象)一样,您需要 equals() 代替。放到合适的类中,实现如下:

public class ComplementsDispoSortieDTO {
    
    private Long cdComplement;

    // ...

    @Override
    public boolean equals(Object obj){
        if (!(obj instanceof ComplementsDispoSortieDTO)){
            return false;
        }

        return (cdComplement != null) 
             ? cdComplement.equals(((ComplementsDispoSortieDTO) obj).cdComplement) 
             : (obj == this); 
    }

}

请注意,我还添加了缺少的反身 obj == this。有关要求列表,另请参阅 the javadoc

另见:

【讨论】:

    【解决方案2】:

    我知道这可能是解决方案。 您应该将列表和选定元素存储在属性中,并在使用组件时将它们维护在范围内。

    【讨论】:

    • OP 已经为此使用了@SessionScoped。这绝对不是问题的原因。
    • 信不信由你,我在类似的情况下删除了 equals 和 hashcode 并且它起作用了。然后我决定使用 DTO 而不是真实对象来维护我的实体哈希码和等号。但我的 dto 只有所需的属性 + 可序列化的实现。终于成功了。
    • 如果您的equals() 实现被严重破坏并且您在应用程序范围内存储对可用项目的引用而不从数据库重新加载它们,则可能会发生这种情况。一旦你开始从数据库重新加载它们,那么你的方法就会死掉。
    猜你喜欢
    • 2012-11-25
    • 2011-10-31
    • 2017-11-10
    • 2011-09-13
    • 2012-05-23
    • 2011-06-01
    • 2017-10-31
    • 2011-02-02
    相关资源
    最近更新 更多