28
OmniFaces Converters Constantin Alin

OmniFaces Converters

Embed Size (px)

Citation preview

Page 1: OmniFaces Converters

OmniFaces ConvertersConstantin Alin

Page 2: OmniFaces Converters

What we will cover ?

• JSF Converters – short overview• OmniFaces Converters – short overview• GenericEnumConverter • ValueChangeConverter • SelectItemsConverter • SelectItemsIndexConverter • ListConverter• ListIndexConverter

Page 3: OmniFaces Converters

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.

Page 4: OmniFaces Converters

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).

Page 5: OmniFaces Converters

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).

Page 6: OmniFaces Converters

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.

Page 7: OmniFaces Converters

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.

Page 8: OmniFaces Converters

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.

Page 9: OmniFaces Converters

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>

Page 10: OmniFaces Converters

OmniFaces GenericEnumConverter (IV)

Sample of using GenericEnumConverter - screenshots from Showcase

Page 11: OmniFaces Converters

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.

Page 12: OmniFaces Converters

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.

Page 13: OmniFaces Converters

OmniFaces ValueChangeConverter (III)

• Sample of using ValueChangeConverter - screenshots from Showcase

Note: the getAsString() method of your converter doesn't need to be changed.

Page 14: OmniFaces Converters

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.

Page 15: OmniFaces Converters

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:

Page 17: OmniFaces Converters

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>.

Page 18: OmniFaces Converters

OmniFaces SelectItemsConverter (V)

• Sample of using SelectItemsConverter - screenshots from Showcase

Page 19: OmniFaces Converters

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>.

Page 20: OmniFaces Converters

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.

Page 21: OmniFaces Converters

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).

Page 22: OmniFaces Converters

OmniFaces SelectItemsIndexConverter (IV)

• Sample of using SelectItemsIndexConverter - screenshots from Showcase

Page 23: OmniFaces Converters

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.

Page 24: OmniFaces Converters

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.

Page 25: OmniFaces Converters

OmniFaces ListConverter (III)

• Sample of using ListConverter - screenshots from Showcase

Page 26: OmniFaces Converters

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.

Page 27: OmniFaces Converters

OmniFaces ListIndexConverter (II)

• Sample of using ListIndexConverter - screenshots from Showcase

Page 28: OmniFaces Converters

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