Upload
constantin-alin
View
173
Download
3
Embed Size (px)
Citation preview
OmniFaces ConvertersConstantin Alin
What we will cover ?
• JSF Converters – short overview• OmniFaces Converters – short overview• GenericEnumConverter • ValueChangeConverter • SelectItemsConverter • SelectItemsIndexConverter • ListConverter• ListIndexConverter
JSF Converters – short overview (I)
• JSF developers are familiar with JSF built-in converters (which are tag handlers) and JSF custom converters (implementations of
javax.faces.convert.Converter interface).
• JSF converters can be attached to input components (e.g. <h:inputText>) via converter attribute or <f:converter>/
<f:convertXxx> tags.
JSF Converters – short overview (II)
• By default, JSF converters are processed in the Process Validations phase and in the Render Response phase.
• The getAsObject() is invoked in Process Validations phase (submitted data -> converter -> data model).
• The getAsString() is invoked in Render Response phase (data model -> converter -> rendered data).
JSF Converters – short overview (III)
• If conversion fails, the JSF lifecycle “jumps” to the Render Response phase and redisplays the current page. You will need to add <h:messages>/<h:message> tags to display the conversion error.
• For UIOutput, the conversions happens in the Render Response phase only (obviously, this is not an input component).
OmniFaces Converters – short overview (I)
• Some OmniFaces converters fixes a suite of gaps of the JSF standard convertors, while others are totally new.
• The OmniFaces converters are implementations of javax.faces.convert.Converter interface.
• OmniFaces converters are easy to use and the OmniFaces Showcase provides complete and dedicated examples.
OmniFaces GenericEnumConverter (I)
• The built-in JSF EnumConverter allows developers to use an E[] property instead of List<E> (e.g. Role[] in case of a Role enum) in
an UISelectManyXxx component.
• However, this doesn't work for a List<E> property as the generic type information E is lost during runtime.
OmniFaces GenericEnumConverter (II)
• OmniFaces GenericEnumConverter is intended for use in
UISelectManyXxx components whose value is been bound to a
List<E> property where E is an enum.
• This will save us to create a new converter for every single enum type, only and only for use in UISelectMany.
OmniFaces GenericEnumConverter (III)
• The GenericEnumConverter converter is available by converter ID omnifaces.GenericEnumConverter and it can be specified in the converter attribute of the multi-selection component holding <f:selectItems>.
<h:selectManyCheckbox value="#{bean.selectedEnums}" converter="omnifaces.GenericEnumConverter"> <f:selectItems value="#{bean.availableEnums}" /> </h:selectManyCheckbox>
OmniFaces GenericEnumConverter (IV)
Sample of using GenericEnumConverter - screenshots from Showcase
OmniFaces ValueChangeConverter (I)
• JSF built-in converters run by default on every request regardless of whether the submitted value has changed or not.
• Because of this, problems appear in cases of conversion against the DB on complex objects which are already stored in the model in a broader scope, such as the view scope, and it may result in unnecessarily expensive service/DAO calls.
• Ideal will be to perform the expensive service/DAO call only when the submitted value is really changed as compared to the model value.
OmniFaces ValueChangeConverter (II)
• OmniFaces ValueChangeConverter is a custom converter that does this job for us and it offers a template to do it transparently.
• To use it, replace implements Converter from your custom converter by extends ValueChangeConverter and rename the method from getAsObject() to getAsChangedObject().
• The getAsChangedObject() method will be invoked by OmniFaces only when the submitted value is not equal with the model value passed through getAsString() method.
OmniFaces ValueChangeConverter (III)
• Sample of using ValueChangeConverter - screenshots from Showcase
Note: the getAsString() method of your converter doesn't need to be changed.
OmniFaces SelectItemsConverter (I)
• When working with UISelectItems (e.g. <h:selectOneMenu>, <h:selectManyListbox>) and using complex Java model objects (entities) as value of <f:selectItems>, the conversion of the submitted strings to the corresponding objects can be accomplished only if we indicate a custom converter.
• OmniFaces SelectItemsConverter provides a custom converter for solving this problem, and JSF will convert the selected value(s) automatically back without the need to create a custom converter.
OmniFaces SelectItemsConverter (II)
• This converter automatically converts based on the Object#toString() of the selected item.
• So, make sure that your entity has a good toString() implementation to uniquely identify the instance during the conversion.
• Something like below should be sufficient:
OmniFaces SelectItemsConverter (III)
• You should also make sure that your entity has a good equals() and hashCode() implementation. Otherwise JSF won't be able to set the right entity back in the model.
• This problem is in turn unrelated to the SelectItemsConverter, you would have faced the same problem when using any other converter.
OmniFaces SelectItemsConverter (IV)
• This converter is available by ID, omnifaces.SelectItemsConverter.
• Just specify it in the converter attribute of the selection component holding <f:selectItems>.
OmniFaces SelectItemsConverter (V)
• Sample of using SelectItemsConverter - screenshots from Showcase
OmniFaces SelectItemsIndexConverter (I)
• OmniFaces SelectItemsIndexConverter is a variant of the SelectItemsConverter which automatically converts based on the position (index) of the selected item in the list instead of the Object#toString() of the selected item.
• This converter is available by converter ID omnifaces.SelectItemsIndexConverter. Just specify it in the converter attribute of the selection component holding <f:selectItems>.
OmniFaces SelectItemsIndexConverter (II)
This converter has the following advantages over SelectItemsConverter:
• No need to rely on Object#toString() method of the object.
• No need to extend the SelectItemsConverter when Object#toString() method of the object cannot be used.
• No need to expose the object's unique key in its Object#toString(), if that's a problem.
OmniFaces SelectItemsIndexConverter (III)
This converter has the following disadvantage over SelectItemsConverter:
• The Validation Error: value is not valid will never occur anymore for the case that the available select items has incompatibly changed during the postback due to a developer's mistake.
• The developer should make absolutely sure that exactly the same list is preserved on postback (e.g. by making it a property of a view scoped or broader scoped bean).
OmniFaces SelectItemsIndexConverter (IV)
• Sample of using SelectItemsIndexConverter - screenshots from Showcase
OmniFaces ListConverter (I)
• OmniFaces ListConverter is intented for use in specialized selection components which doesn't use SelectItems as the source for their selectable items, but work directly via a List of entities.
• It allows you to populate a selection component with complex Java objects and JSF will convert those automatically back without the need to create a custom converter.
OmniFaces ListConverter (II)
• Just like SelectItemsConverter, it automatically converts based on the Object#toString() of the selected item. Again, make sure that your entity has a good toString() implementation.
• This converter is available by converter ID, omnifaces.ListConverter and should be used in combination with <o:converter> in order to be able to pass the List source to it, which it can use for conversion.
OmniFaces ListConverter (III)
• Sample of using ListConverter - screenshots from Showcase
OmniFaces ListIndexConverter (I)
• OmniFaces ListIndexConverter is a variant of the ListConverter which automatically converts based on the position (index) of the selected item in the list instead of the Object#toString() of the selected item.
• This converter is available by converter ID, omnifaces.ListIndexConverter and should be used in combination with <o:converter> in order to be able to pass the List source to it, which it can use for conversion.
OmniFaces ListIndexConverter (II)
• Sample of using ListIndexConverter - screenshots from Showcase
References
• Bauke Scholtz - http://balusc.blogspot.com/• Arjan Tijms - http://arjan-tijms.omnifaces.org/• JSF ZEEF page - https://jsf.zeef.com/bauke.scholtz• OmniFaces ZEEF page - https://omnifaces.zeef.com/bauke.scholtz• OmniFaces Wikipedia - http://en.wikipedia.org/wiki/OmniFaces