使用SelectOneMenu的JSF(PrimeFaces)转换器:验证错误

3
我正在使用PrimeFaces和JSF制作一个项目,在<p:SelectOneMenu>上遇到了问题,具体来说是从一个对象转换为字符串时出现的问题。我编写了必要的转换器类,并实现了toString()equals()方法,我认为这些都相当正确。然而,在<h:messages />组件中却不停地给我报错:

j_idt7:j_idt92: 验证错误:值无效
j_idt7:j_idt98: 验证错误:值无效

我需要选择属于同一大表单的值。然后,根据所选所有者(właściciel)和公司(firma),将它们添加到数据库中。

这是我的<p:SelectOneMenu>代码(两个菜单):

<p:selectOneMenu value="#{wniosek.selectedWl}" var="w">
<f:selectItem itemLabel="Wybierz" itemValue=""/>
   <f:selectItems value="#{wniosek.listaWl}" var="wlasciciel" 
      itemLabel="#{wlasciciel.nazwisko}" itemValue="#{wlasciciel}" />

      <p:column>
          #{w.nazwisko}
      </p:column>
      <f:converter converterId="WlascicielConverter" />
</p:selectOneMenu>                      
 <h:outputText value="Nazwa firmy: "/>

 <p:selectOneMenu value="#{wniosek.selectedFi}"  var="f">
      <f:selectItem itemLabel="Wybierz" itemValue=""/>
      <f:selectItems value="#{wniosek.listaFi}" var="firma" 
           itemLabel="#{firma.nazwa}" itemValue="#{firma}" />
      <f:converter converterId="FirmaConverter" />
      <p:column>
           #{f.nazwa}
      </p:column>
 </p:selectOneMenu>

这是我的转换器类,用于所有者的<p:SelectOneMenu>(我也对公司的做了同样的处理):
public class WlascicielConverter implements Converter {

int i = 0;
@Override
public Object getAsObject(FacesContext arg0, UIComponent arg1, String arg2) {
    try {           
        if (arg2 == null || arg2.isEmpty()) {
            return null;
        }
        String owner = arg2;
        return WlascicielBean.findAnOwner(owner);

    } catch (SQLException e) {
        e.printStackTrace();
        return null;
    }
}

@Override
public String getAsString(FacesContext arg0, UIComponent arg1, Object arg2) {

    if(arg2 == null) return null;

    Wlasciciel owner = new Wlasciciel();

    if(arg2 instanceof Wlasciciel) {
        owner = (Wlasciciel)arg2;
        System.out.println(owner.getNazwisko());
        String surname = owner.getNazwisko();
        return (surname != null) ? String.valueOf(surname) : null;
    } else throw new ConverterException("Something wrong!" + arg2.hashCode() + arg2.toString());

}

一个 equals() 方法:

@Override
public boolean equals(Object obj) {
    if (obj == this) return true;
    if (!(obj instanceof Wlasciciel)) return false;

    Wlasciciel wl = (Wlasciciel)obj;
    if (this.id_w != wl.getId_w()) return false; 
    if (!this.nazwisko.equals(wl.getNazwisko())) return false; 
    if (!this.imie.equals(wl.getImie())) return false;      
    if (!this.ulica.equals(wl.getUlica())) return false; 
    if (this.nr != wl.getNr()) return false; 
    if (this.lokal != wl.getLokal()) return false; 
    if (this.id_n != wl.getId_n()) return false; 

    return true;
}

你能给我一些关于解决这个问题的提示吗?我已经阅读了很多关于JSF转换器的教程,尝试了很多方法来改进它,但它仍然没有起作用。我不知道...也许问题出现在我的代码中的其他地方?由于它的长度,我不会在这里粘贴它(当然,如果需要,我会这样做)。

1个回答

7
总的来说,我认为你走在正确的道路上,尽管非英语代码使得真正理解你在那里做什么变得非常困难...
发生的情况是:你有一个集合。你的转换器遍历该集合并在每个对象上调用getAsString()。在浏览器中选择了某个值后,该值(即getAsString()的返回值)将被传输到转换器,并调用getAsObject()。这是一个全新的对象,不一定是以前的集合中的一个(除非你的转换器实际访问该集合并从中取出它)。之后,JSF将采用用于生成selectOneMenu的集合,并将每个项目与转换器返回的项目进行比较。
这可能是通过equals()或hashCode()完成的,具体取决于使用的集合。因此,您需要同时重写两者(您实际上应该总是这样做)。
如果JSF找不到与转换器返回的对象(等于为true或hashCode相同)匹配的集合中的任何对象,则会收到验证错误:值无效。
我希望这澄清了一些流程。我猜你要么必须实现hashCode(),要么你的equals()方法有问题。总体设置是正确的。您需要调试并检查为什么JSF无法在列表中找到对象。

另一个可能的原因是,在表单提交期间<f:selectItems value>列表已更改。另请参阅https://dev59.com/DGox5IYBdhLWcg3wpF35#9069660 感谢您解密波兰代码 :) - BalusC
我仍在与这个问题作斗争。我试图检查转换器为什么无法正常工作,我发现getAsString方法中的arg2对象是一个String,而不是一个Wlascicel对象(但它应该是,不是吗?)。所以我收到了一个ClassCastException - 它无法将String转换为Wlasciciel。我已经编辑了之前的列表,并插入了最新的转换器。我真的不知道出了什么问题。 - smiechu_skce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接