1) Introduction
Java Server Faces provides a component-based event-driven model for User Interface Layer in a Web Application. JSF UI Components behave very similar to Swing Components in which case Events are made to trigger by the User and they are handled by appropriate Listeners. In this article, we will focus on Converters which remains an important aspect in converting the user input to the one that is stored in the Mode. This article won’t provide the introductory details related to JSF and novice users are advised to have to a glance over this Introduction to Java Server Faces article on JavaBeat. This article will begin with explaining the need to have Converters in JSF Framework and then continue to discuss about the various Standard Converters that are available in-built with JSF. Then the final section will show you how to develop and register Custom Converters to a JSF Application.
2) Converters in JSF
Before getting into details, let us study the need and advantage of having JSF Converters in place. Let us take an example of a Web Application in which the User will be presented with a Web Page for entering the input values. The values entered by the User in all cases will be in string format. Even, when asked to enter numerical values like age or salary whatever is being passed on to the Server end will still be in String format. So, there must be some intermediary which will do the job of converting the string values into the type that is appropriate for the particular field value.
also read:
Say, for example, if the User Form contains fields for name, age, salary and date of birth. Obviously, the model object for this form will contain string, integer, double and date data-types for storing name, age, salary and date of birth respectively. So the Converters do the job of converting the user input. JSF already comes with a bunch of Standard Converters (which will be covered shortly) for most of the common conversion process. If you can’t find a suitable converter that is very specific to your Application, then still you can define a Customized Converter that will do the job for you.
In technical terms, the Apply Request Value Phase is the phase during which the conversion of values to their appropriate type will happen. If the conversion process succeeds, then the submitted values are validated against the Validators defined. If either Conversion or the Validation fails, then the form is re-displayed in which case the model values that are associated for each UI Component would not be updated. It gives a chance to the user to re-enter the values. If the user enters the right value, and if the Conversion and the validation succeeds, then the Model values are updated.
3) Standard Converters
3.1) Introduction
In this section, let us see the different standard Converters that comes bundled with JSF Implementation along with some sample code snippets.
The following are the standard Converters available in JSF.
- BigDecimalConverter – Used to convert the user input string values into values of type java.math.BigDecimal
- BigIntegerConverter – Used to convert the user input string values into values of type java.math.BigInteger
- BooleanConverter – Used to convert the user input string values into values of type java.lang.Boolean
- ByteConverter – Used to convert the user input string values into values of type java.lang.Byte
- CharacterConverter – Used to convert the user input string values into values of type java.lang.Character
- DateTimeConverter – Used to convert the user input string values into values of type java.util.Date with a default format.
- DoubleConverter – Used to convert the user input string values into values of type java.lang.Double
- EnumConverter – Used to convert the user input string values into values of type java.lang.Enum
- FloatConverter – Used to convert the user input string values into values of type java.lang.Float
- IntegerConverter – Used to convert the user input string values into values of type java.lang.Integer
- LongConverter – Used to convert the user input string values into values of type java.lang.Long
- NumberConverter – Used to convert the user input string values into values of type java.lang.Number
- ShortConverter – Used to convert the user input string values into values of type java.lang.Short
3.2) Code Snippets
In this section, let us see code snippets that make use of the standard converters.
The following code defines a Number Converter which formats and displays the number in currency format. Depending on the locale set for this Application, it displays the currency symbol along with value. For example, it may display $1999, if the locale is pointing to US.
<h:inputText id="salary" value="#{testBean.salary}" required="true"> <f:convertNumber type="currency"/> </h:inputText>
By specifying the type as 'percentage'
, the display value will have a '%'
symbol followed by the original value.
<h:inputText id="discount" value="#{testBean.discount}" required="true"> <f:convertNumber type="percent"/> </h:inputText>
For formatting date and time, we have to set the type as 'date'
. Whether the style of the date to displayed (short
, medium
, long
) is specified in the 'dateStyle'
attribute.
<h:inputText id="date" value="#{testBean.date}" required="true"> <f:convertDateTime type="date" dateStyle="long"/> </h:inputText>
<h:inputText id="population" value="#{testBean.population}" required="true"> <f:convertNumber type="#,###.00"/> </h:inputText>
The above converter formats the number based on the pattern '#, ###.00'
. For example, if the original value is 1234.00
, then the value displayed in the view might look like '1,234.00'
.
4) Developing Custom Converters
4.1) Introduction
In most of the situations, the Converter Implementations that are bundled with JSF implementation is often enough. However, for application specific purposes, there may be a need to customize and convert the user entered string into some other data-type. This can be achieved with ease by using JSF Pluggable Converter architecture.
4.2) Phone Number
Let us assume that our Web Application prompts the user to enter phone number which is of the format ‘CountryCode-AreaCode-Number’. Note that whatever user enters is just a string and we want this string to be converted into some kind of format so that it can be stored in the model.
PhoneNumber.java
package net.javabeat.articles.jsf.converters; import java.io.Serializable; public class PhoneNumber implements Serializable { private int countryCode; private int areaCode; private long number; public PhoneNumber() { } public PhoneNumber(int countryCode, int areaCode, long number) { this.setCountryCode(countryCode); this.setAreaCode(areaCode); this.setNumber(number); } public int getCountryCode() { return countryCode; } public void setCountryCode(int countryCode) { this.countryCode = countryCode; } public int getAreaCode() { return areaCode; } public void setAreaCode(int areaCode) { this.areaCode = areaCode; } public long getNumber() { return number; } public void setNumber(long number) { this.number = number; } }
The above model class for Phone Number encapsulates 'countryCode'
, 'areaCode'
and 'number'
properties. The rest of the code merely contains setters and getters for setting and getting the appropriate values.
4.3) Phone Number Converter
All the Converter classes in JSF must implement the Converter
interface and they should override the getAsObject()
and getAsString()
methods. The method getAsObject() will be called as soon as the user enters the data and conforms it by clicking the submit button. This triggers the Apply Request Values Phase and this method will be called with the user-entered value as one of its arguments. Here we can parse and format the data entered by the user and store it in some model object and return it so that it will be set to the appropriate UI Component.
The getAsString()
method will be called during Render Response Phase. Now, it’s time to display the data in the view from the model object. And usually this method will contain logic for extracting the data from the model, format it and return it to the view.
PhoneNumberConverter.java
package net.javabeat.articles.jsf.converters; import java.util.StringTokenizer; import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.convert.Converter; import javax.faces.convert.ConverterException; public class PhoneNumberConverter implements Converter { public PhoneNumberConverter() { } public Object getAsObject(FacesContext context, UIComponent component, String value) { if (value == null || (value.trim().length() == 0)) { return value; } PhoneNumber phoneNumber = new PhoneNumber(); boolean conversionError = false; int hyphenCount = 0; StringTokenizer hyphenTokenizer = new StringTokenizer(value, "-"); while (hyphenTokenizer.hasMoreTokens()) { String token = hyphenTokenizer.nextToken(); try { if (hyphenCount == 0) { phoneNumber.setCountryCode(Integer.parseInt(token)); } if (hyphenCount == 1) { phoneNumber.setAreaCode(Integer.parseInt(token)); } if (hyphenCount == 2) { phoneNumber.setNumber(Long.parseLong(token)); } hyphenCount ++; } catch (Exception exception) { conversionError = true; } } if (conversionError || (hyphenCount != 3)) { throw new ConverterException(); } return phoneNumber; } public String getAsString(FacesContext context, UIComponent component, Object value) { PhoneNumber phoneNumber = null; if (value instanceof PhoneNumber) { phoneNumber = (PhoneNumber)value; StringBuilder phoneNumberAsString = new StringBuilder(); phoneNumberAsString.append(phoneNumber.getCountryCode() + "-"); phoneNumberAsString.append(phoneNumber.getAreaCode() + "-"); phoneNumberAsString.append(phoneNumber.getNumber()); return phoneNumberAsString.toString(); } return ""; } }
4.4) Registering the Custom Converter
To make the Custom Converter visible to JSF Application, we have to register the Converter
class by making an entry in the Faces Configuration file. The following is the xml code snippet for the same,
<converter> <description>A Converter for phone number</description> <converter-id>PhoneNumberConverter</converter-id> <converter-class> net.javabeat.articles.jsf.converters.PhoneNumberConverter </converter-class> </converter>
We have given an identifier 'PhoneNumberConverter'
for the PhoneNumberConverter
class and this identifier should be referenced elsewhere in the Application.
4.5) Using the Custom Converter
To set this Phone Number Converter to a component, make use of the 'converter'
tag as the following listing does,
<h:inputText id="phoneNumberInput" value="#{phoneNumberBean.phoneNumber}" required="true"> <f:converter converterId="PhoneNumberConverter"></f:converter> </h:inputText>
5) Conclusion
This article made an attempt in explaining the concepts related to Converters in JSF. Converters which are used to convert the user-entered values to the one that is required by its model can also be customized. This article focused on two types of Converters namely, the Standard Converters and Custom Converters. A complete example has been given for developing a Custom Converter at the latter part of the article.