1

我想要一个带有公式和下拉菜单的 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>

这是参考的托管支持bean

@ManagedBean
@RequestScoped
public class LieferantenBackingBean extends AbstractWarenwirtschaftsBackingBean {

    private List<Lieferant> lieferanten;

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

}

据我所知,我需要一个自定义转换器来交换 Lieferant 对象的 POJO 和字符串表示。这是转换器的外观:

@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

不幸的是,它没有说明它在谈论哪个值。转换器似乎工作正常。

从 stackoverflow这篇关于 selectOneMenu 和转换器的文章中找到了类似的问题,但我无法在我的代码中找到问题。为什么是

List<SelectItem> 

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

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

4

2 回答 2

2

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

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

要排除一个或另一个:您可以Object#equals()使用“plain vanilla”测试用例轻松进行测试,并且可以通过将 bean 置于会话范围内来测试列表的一致性。

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

于 2010-03-23T15:52:50.703 回答
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 "";
}

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

 itemValue="#{lieferant}"

现在,我不确定最后一次更改是否必要。但现在副官已经正确转换了。

于 2010-03-23T16:32:29.550 回答