How to use JSF Converters with ICEfaces ComponentsWhy is conversion important? Conversion is the process of ensuring data is of the right object or type. This prevents erroneous information from getting into your system. In the JSF lifecycle, conversion occurs in the apply request values phase. This is before component data is bound to your backing bean model. By having it occur in the apply request values phase you can make certain assumptions that the data being sent into the backing bean will be of the correct type. This helps you to focus on business logic rather than qualifications of input data. For this tutorial we will be using a simple JSF application to demonstrate how to use JSF converters. The following screen shot is a screen shot of the application:
This tutorial will discuss the following topics related to the use of JSF converters: Single / Partial Submit and Immediate Attributes
<ice:inputText><ice:singleSubmit /></ice:inputText> <ice:inputText partialSubmit="true"/> The immediate attribute can be used to achieve the following effects:
Using the immediate attribute on a component means its value will be validated during the apply request values phase in the JSF lifecycle. Since conversion already occurs in this phase the use of this attribute does not affect conversion. The immediate attribute is used to affect validation.
How to Use Standard JSF Converters
For the standard converter tag, <f:converter/>, JSF has many standard data converters. The following is a sample of the id's of the data converters available:
To use the converter with a component, the converter must be nested inside the components tag. The following JSF code shows how to add a standard converter for an inputText component: <ice:inputText id="age" value="#{user.age}" partialSubmit="true> <f:converter converterId="javax.faces.Integer"/> </ice:inputText> This will now ensure that only integer values can be sent into the backing bean and not something else such as a character. In the screen shot below, you can see what happens when a non-integer value is entered. When dealing with date data you must use the <f:convertDateTime/> converter tag. This will convert a string to a proper Date object. If the string entered in is not convertible then an error message will be displayed. The following JSF code is an example on how to implement a date converter: <ice:inputText id="birthdate" value="#{user.birthDate}"> <f:convertDateTime dateStyle="short"/> </ice:inputText> This will convert the entered string to a short Date format. The following table displays all the standard formats available and what they look like:
In addition to converters for primitives, date, and time data types, JSF provides another converter for dealing with numbers such as percentages and currency. This converter deals with grouping, number of decimal digits, currency symbols, etc. The following JSF code shows how to add a number converter for dealing with currency: <ice:inputText id="salary" value="#{user.salary}"> <f:convertNumber maxFractionDigits="2" groupingUsed="true" currencySymbol="$" maxIntegerDigits="7" type="currency"/*> </ice:inputText> This will allow only whole numbers entered with a dollar sign and up to seven digits can only be entered at a time. Anything that breaches these conditions will cause a Conversion Error to be thrown.
How to Write Custom Converters
The following is a step-by-step walk through on how to create a custom converter. Step 1: Implement the Converter InterfaceCreate a utility class that will handle all of the conversion duties. This class must implement the Converter interface as shown below: PhoneConverter import javax.faces.convert.Converter public class PhoneConverter implements Converter { ... } Step 2: Implement the getAsObject MethodHere the getAsObject method converts a string to a PhoneNumber object PhoneConverter public class PhoneConverter implements Converter { public Object getAsObject(FacesContext context, UIComponent component, String value){ if(StringUtils.isEmpty(value)){ return null; } PhoneNumber phone = new PhoneNumber(); String [] phoneComps = StringUtils.split(value," ,()-"); String countryCode = phoneComps[0]; phone.setCountryCode(countryCode); if(countryCode.equals("1")){ String areaCode = phoneComps[1]; String prefix = phoneComps[2]; String number = phoneComps[3]; phone.setAreaCode(areaCode); phone.setPrefix(prefix); phone.setNumber(number); } else { phone.setNumber(value); } return phone; } } Step 3: Implement the getAsString methodHere the getAsString method converts a PhoneNumber object to a String. PhoneConverter public class PhoneConverter implements Converter { ... public String getAsString(FacesContext context, UIComponent component, Object value){ return value.toString(); } } For the above code to work you must implement the objects (PhoneNumber) toString() method accordingly. For example: PhoneNumber public class PhoneNumber { ... public String toString(){ if(countryCode.equals("1")){ return countryCode + "-" + areaCode + "-" + prefix + "-" + number; } else { return number; } } } Step 4: Register Custom Converter with Faces ContextThis step can be executed in two ways. Option one is to register the PhoneConverter class with a user defined id (icefaces.PhoneConverter). This id is used by <f:converter/> tags converterId attribute. To implement this, insert the following code into your faces-config.xml file: <converter> <converter-id>icefaces.PhoneConverter</converter-id> <converter-class> com.icesoft.icefaces.tutorial.component.converter.custom.PhoneConverter </converter-class> </converter> The other option is to register the PhoneConverter class to handle all PhoneNumber objects automatically. To do this insert the following code into your faces-config.xml file: <converter> <converter-for-class> com.icesoft.icefaces.tutorial.component.converter.custom.PhoneNumber </converter-for-class> <converter-class> com.icesoft.icefaces.tutorial.component.converter.custom.PhoneConverter </converter-class> </converter> Step 5:Use the Converter Tag in your PageThe last step is using the converter. This is very similar to using the standard JSF <f:converter> tag. For the first option from step four: <ice:inputText id="phone" value="#{user.phone}"> <f:converter converterId="icefaces.PhoneConverter"/> </ice:inputText> For the second option from step 4, there is no need to use the <f:converter/> tag since the PhoneConverter class handles all PhoneNumber objects automatically.
Message and Messages Tags
<ice:inputText id="age" value="#{user.age}"> <f:converter converterId="javax.faces.Integer"/> </ice:inputText> <ice:message style="color:red;" id="ageError" for="age"/> The screen shot below shows how it will look: Custom MessagesThe default messages that are supplied by JSF can be quite verbose and could cause confusion for end users. For conversion the default error message is the vague "Conversion error occurred". To change the default message you can create your own message.properties file and switch out the message resource bundle in the faces context. The following code shows how to add the properties file to the faces context: <application> <locale-config> <default-locale>en</default-locale> </locale-config> <message-bundle> com.icesoft.icefaces.tutorial.component.converter.basic.messages </message-bundle> </application> The following is the entry in the messages.properties file that will override the default converter error message: Properties File public class PhoneNumber {
...
javax.faces.component.UIInput.CONVERSION=invalid input
...
}
This will now display the message "invalid input" beside the field that is causing the error shown in the screen shot below.
Tutorial Source Code Downloads
|
Converters
© Copyright 2021 ICEsoft Technologies Canada Corp.