【问题标题】:JSF2.0 converter need for SelectItems?JSF2.0转换器需要SelectItems吗?
【发布时间】:2014-03-13 13:36:15
【问题描述】:

我收到以下消息:

Value is no String (class=org.xxx.Foo, value=org.xxx.Foo@366d5595) and component j_id17:j_id114:j_id125with path: {Component-Path : [Class: org.ajax4jsf.framework.ajax.AjaxViewRoot,ViewId: /foo.xhtml][Class: org.ajax4jsf.ajax.html.Include,Id: j_id17][Class: javax.faces.component.html.HtmlForm,Id: j_id114][Class: javax.faces.component.html.HtmlSelectOneMenu,Id: j_id125]} does not have a Converter.

Xhtml:

<h:selectOneMenu value="#{bar.foo}">
     <f:selectItem itemValue="#{bar.foos}" />
</h:selectOneMenu>

Foo 是:

import javax.faces.model.SelectItem;
@Audited
@Entity
@Table(name= "foo")
@AccessType("property")
public class Foo extends SelectItem implements Serializable{
     ....
}

为什么我需要一个转换器来将 SelectItem 转换为 SelectItem?

【问题讨论】:

  • 因为 HTML 和 HTTP 不能传递 Java 对象。它们只能传递由String 表示的Java 字符。 Converter 可以在 String 和所需的 Java 对象之间进行转换。顺便说一句,extends SelectItem 是不必要且无意义的。

标签: java jsf-2 converter selectonemenu


【解决方案1】:

当 JSF 在显示期间尝试从 Foo 收集所选值以及在回发期间尝试从所选值返回 Foo 时,就会出现问题。正如 BalusC 所提到的,扩展 SelectItem 不是一个好方法。您有两个常规选项之一:手动处理选择或使用转换器。

转换器非常适合适应几乎任何类型的对象,以便可以通过 UI 元素直接引用和呈现它们。不幸的是,当转换不简单时,转换器可能需要额外的步骤。

我注意到@Entity 注释,所以我假设您正在尝试显示用户可以从中选择的记录列表。 90% 的情况下,此类选择旨在获取记录的主键而不是记录本身,以便在后续查询或业务逻辑中使用它。对于这种情况,手动选择更为有效。但是,如果您还需要获取记录内容,那么转换器更适合,因为它可以处理查找逻辑并让您的业务逻辑直接处理记录。

我不会规定您应该选择哪种方法,但由于您最初的问题集中在手动方法上,因此我将提供此解决方案。假设您的新简化 Foo 看起来像这样。

public class Foo {
    private long id;
    private String label;

    public Foo( long id, String label ) {
        this.id = id;
        this.label = label;
    }

    public long getId() {
        return id;
    }

    public void setId( long id ) {
        this.id = id;
    }

    public String getLabel() {
        return label;
    }

    public void setLabel( String label ) {
        this.label = label;
    }
}

下面给出的简单FooCntrl bean 将提供演示信息并处理选择的回发。

@Named
@ViewScoped
public class FooCntrl implements Serializable {
private long selected = 0;

    // Stub for what an EntityManager would normally provide.
    public List<Foo> getRecords () {
        List<Foo> fooList = new ArrayList<Foo>();
        fooList.add( new Foo( 11, "Paul" ) );
        fooList.add( new Foo( 23, "John" ) );
        fooList.add( new Foo( 32, "George" ) );
        fooList.add( new Foo( 47, "Ringo" ) );
        return fooList;
    }

    public long getSelected() {
        return selected;
    }

    public void setSelected( long selected ) {
        this.selected = selected;
        System.out.println( "You picked record id: " + selected );
    }

    public List<Foo> getFooList() {
        return getRecords();
    }
}

这反过来又会驱动您的 UI 选择菜单。

...
<h:form>
    <h:selectOneMenu value="#{fooCntrl.selected}">
        <f:selectItem itemValue="0" itemLabel="Select One..." />
        <f:selectItems value="#{fooCntrl.fooList}" var="r" itemLabel="#{r.label}" itemValue="#{r.id}"/>
    </h:selectOneMenu>
    <h:commandButton value="Submit" />
</h:form>
...

这只是一种变体。我敢肯定,有些人会不同意它并一直推荐转换器,甚至推荐另一种手动方法。我的目标是给你一些你可以继续前进的东西。我会让你按照自己的节奏来完善你的设计方法和风格:)。

【讨论】:

    猜你喜欢
    • 2015-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多