我收到了以下信息:
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?
答案 0 :(得分:1)
当JSF在显示期间尝试从Foo
收集所选值并且在回发期间尝试从所选值中获取Foo
时,会出现问题。正如BalusC所说,延长SelectItem
并不是一个好方法。您有两种常规选项之一:手动处理选择或使用转换器。
转换器非常适合调整任何类型的Object,以便可以通过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>
...
这只是一个变种。我确信有些人会不同意它并推荐转换器,甚至推荐另一种手动方法。我的目标是给你一些你可以继续前进的东西。我会按照你自己的节奏来完善你的设计方法和风格:)。