具有POJO和转换器问题的Facelet selectOneMenu

时间:2010-03-23 14:28:08

标签: jsf facelets converter selectonemenu

我希望有一个带有公式和下拉菜单的facelet页面。使用下拉菜单,用户可以选择Lieferant类型的POJO:

public class Lieferant extends AbstractPersistentWarenwirtschaftsObject {

    private String firma;

    public Lieferant(WarenwirtschaftDatabaseLayer database, String firma) {
        this(database, null, firma);
    }

    public Lieferant(WarenwirtschaftDatabaseLayer database, Long primaryKey, String firma) {
        super(database, primaryKey);
        this.firma = firma;
    }

    public String getFirma() {
        return firma;
    }

    @Override
    public String toString() {
        return getFirma();
    }

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

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Lieferant other = (Lieferant) obj;
        if (firma == null) {
            if (other.firma != null)
                return false;
        } else if (!firma.equals(other.firma))
            return false;
        return true;
    }

}

这是我写的facelet代码:

<h:selectOneMenu> 

标签。此标记应显示Lieferant类型的POJO(非bean)列表。这是facelet代码:

<h:selectOneMenu id="lieferant" value="#{lieferantenBestellungBackingBean.lieferant}">
 <f:selectItems var="lieferant" value="#{lieferantenBackingBean.lieferanten}" itemLabel="#{lieferant.firma}" itemValue="#{lieferant.primaryKey}" />
 <f:converter converterId="LieferantConverter" />
</h:selectOneMenu>

这是refenrenced托管支持bean

@ManagedBean
@RequestScoped
public class LieferantenBackingBean extends AbstractWarenwirtschaftsBackingBean {

    private List<Lieferant> lieferanten;

    public List<Lieferant> getLieferanten() {
        if (lieferanten == null) {
            lieferanten = getApplication().getLieferanten();
        }
        return lieferanten;
    }

}

据我所知,我需要一个自定义转换器来交换POJO和Lieferant对象的String表示之间的交换。这是转换器的样子:

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

 @Override
 public Object getAsObject(FacesContext context, UIComponent component, String value) {
  long primaryKey = Long.parseLong(value);
  WarenwirtschaftApplicationLayer application = WarenwirtschaftApplication.getInstance();
  Lieferant lieferant = application.getLieferant(primaryKey);
  return lieferant;
 }

 @Override
 public String getAsString(FacesContext context, UIComponent component, Object value) {
  return value.toString();
 }

}

页面加载时没有任何错误。当我填写公式并提交时,页面上会显示一条错误消息:

Bestellung:lieferantenBestellungForm:lieferant: Validierungsfehler: Wert ist keine gültige Auswahl
translated: validation error: value is not a valid selection

不幸的是,它没有说出它所谈论的价值。转换器似乎正常工作。

我发现了similar question from stackoverflow这个 article about selectOneMenu and converters,但我无法在代码中找到问题。为什么

List<SelectItem> 

在第二个链接的示例中使用。给我同样的错误。

任何帮助将不胜感激。提前谢谢。

2 个答案:

答案 0 :(得分:2)

  

验证错误:值不是有效选择

此错误表示所选项目与列表中的任何选项都不匹配。在您的情况下,这可能有两个原因:Object#equals()被错误地实现,或者<f:selectItems>后面的getter不会在后续请求中(在提交表单期间)返回相同的列表。初始请求(在提交表单之前,在选择值时)。

要排除其中一个:您可以使用“普通的vanilla”测试用例轻松测试Object#equals(),并且可以通过将bean放在会话范围内来测试列表的一致性。

要清楚,您的转换器看起来很好并且似乎工作正常(否则您将无法获得此类错误消息;因此转换步骤已成功完成)。

答案 1 :(得分:0)

我真的很确定转换器工作正常,但最后的错误是在转换器中。也许这在调试的几个小时内发生了。这是转换器的固定getAsString方法。 Ñ

@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
    if (value != null && value instanceof Lieferant) {
        Lieferant lieferant = (Lieferant) value;
        return "" + lieferant.getPrimaryKey();
    }
    return "";
}

现在它返回primaryKey,它被用作selectOneMenu列表的值。另外,我从selectItems标签中更改了此属性:

 itemValue="#{lieferant}"

现在,如果最后一次改变是必要的,我并不感到害羞。但现在谎言被正确转换了。