The problem arises when JSF tries to glean the selected value from Foo
during display and when it tries to get Foo
back from the selected value during a postback. As BalusC mentioned, extending SelectItem
isn't a good approach. You have one of two regular options: manually handling the selection or using converters.
Converters are wonderful for adapting pretty much any type of Object so that they can be directly referenced and presented via UI elements. Unfortunately, converters may require extra steps when a conversion isn't simple.
I noticed the @Entity
annotation, so I'm assuming you are trying to display a list of records from which the user can choose. 90% of the time, such selections are intended to get a record's primary key rather than the record itself so that it can be used in subsequent queries or business logic. For such situations a manual selection is more effective. However, if you also need to get record content, then a converter is better suited as it would handle the lookup logic and let your business logic work directly with the record.
I'm not going to dictate which method you should choose, but since your original problem was centered around the manual approach, I'll offer this solution. Let's assume your new simplified Foo
looks like this.
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;
}
}
A simple FooCntrl
bean as given below would provide presentation information and handle the selection's postback.
@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();
}
}
This in turn drives your UI selection menu.
...
<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>
...
This is just one variant. I'm certain that some will disagree with it and recommended converters all the way or even recommend another manual approach. My goal is to give you something that you can move forward with. I'll leave it up to you to refine your design methodology and style at your own pace :).