The omnifaces.SelectItemsConverter allows you to populate a selection component with complex Java model objects (entities) as value of
<f:selectItems> and have Faces convert those automatically back without the need to provide a custom converter which may need to do the
job based on possibly expensive service/DAO operations. This converter automatically converts based on the Object.toString() of the selected item.
Usage
This converter is available by converter ID omnifaces.SelectItemsConverter. Just specify it in the converter attribute of the
selection component holding <f:selectItems>.
<h:selectOneMenu value="#{bean.selectedItem}" converter="omnifaces.SelectItemsConverter">
<f:selectItems value="#{bean.availableItems}" />
</h:selectOneMenu>
Since OmniFaces 4.5 it's also available by <o:selectItemsConverter> tag.
<h:selectOneMenu value="#{bean.selectedItem}">
<f:selectItems value="#{bean.availableItems}" />
<o:selectItemsConverter />
</h:selectOneMenu>
Make sure that your entity has a good toString() implementation
The base converter uses by default the toString() method of the entity to uniquely identify the instance during the conversion. This is
sufficient if your (abstract base) entity has a toString() implementation which looks something like this:
@Override
public String toString() {
return String.format("%s[id=%d]", getClass().getSimpleName(), getId());
}
By the way, you should also make sure that your entity has a good equals() and
hashCode() implementation, otherwise Faces won't be able to set the right entity back in the model. Please note that this problem is in turn
unrelated to the SelectItemsConverter, you would have faced the same problem when using any other converter.
If your entity can't have a good toString() implementation
However, if the entity doesn't have a toString() implementation (and thus relies on the default fqn@hashcode implementation), or
the existing implementation doesn't necessarily uniquely identify the instance, and you can't implement/change it, then it is recommended to extend the
SelectItemsConverter class and override only the getAsString method wherein the desired implementation is provided. For
example:
@FacesConverter("exampleEntitySelectItemsConverter")
public class ExampleEntitySelectItemsConverter extends SelectItemsConverter {
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
Long id = (value instanceof ExampleEntity) ? ((ExampleEntity) value).getId() : null;
return (id != null) ? String.valueOf(id) : null;
}
}
Again, you do not need to override the getAsObject() method which would only need to perform possibly expensive service/DAO
operations. The SelectItemsConverter base converter will already do it automatically based on the available items and the
getAsString() implementation.
An alternative is to switch to SelectItemsIndexConverter, which will convert based on the position (index) of the selected item in the list instead
of the Object.toString() of the selected item.
- Author:
- Arjan Tijms
- See Also:
-
Field Summary
Fields inherited from interface jakarta.faces.convert.Converter
DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE_PARAM_NAME -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptiongetAsObject(FacesContext context, UIComponent component, String value) getAsString(FacesContext context, UIComponent component, Object value)
-
Constructor Details
-
SelectItemsConverter
public SelectItemsConverter()
-
-
Method Details
-
getAsObject
- Specified by:
getAsObjectin interfaceConverter<Object>
-
getAsString
- Specified by:
getAsStringin interfaceConverter<Object>
-