Converters

Table of Contents

How to use JSF Converters with ICEfaces Components

Why 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:





Single / Partial Submit and Immediate Attributes


When ICEfaces' single submit (2.x/3.x) or partial submit (1.x) is enabled on a component, after the component loses focus it will attempt to convert the data, rather than waiting for a full form submit. If the data is not of the correct type an error message will be displayed. The following JSF code shows how to set single/partial submit on a component:

<ice:inputText><ice:singleSubmit /></ice:inputText>

<ice:inputText partialSubmit="true"/>

The immediate attribute can be used to achieve the following effects:

  • Allow a commandLink or commandButton to navigate the user to another page without processing data currently in input fields of the current screen. In particular, this allows navigation to occur even when there are currently validation errors. Ex: a "Cancel" button.
  • Allows a commandLink or commandButton to trigger back-end logic while ignoring validation for some of the fields on the screen.
  • Makes one or more input components "high priority" for validation, so that if any of these are invalid then validation is not performed for any "low priority" components on the same page. This can reduce the number of error messages shown.

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


There are three standard JSF converters. The following is a list of the converters with their attributes:

  • <f:converter/>: Adds an arbitrary converter to a component.
    • converterId: The id of the converter.
  • <f:convertDateTime>: Adds a date/time converter to a component.
    • type: date(default), time, or both.
    • dateStyle: default, short, medium, long, or full.
    • timeStyle: default, short, medium, long, or full.
    • pattern: Formatting pattern as defined in java.text.SimpleDateFormat.
    • locale: Locale whose preferences are to be used for parsing and formatting.
    • timeZone: Time zone to use for parsing and formatting.
  • <f:convertNumber>:Adds a number converter to a component.
    • type: number(default), currency, percent.
    • pattern: Formatting pattern, defined by java.text.DecimalFormat.
    • maxFractionDigits: Max number of digits in the fraction part.
    • minFractionDigits: Min number of digits in the fraction part.
    • maxIntegerDigits: Max number of digits in the integer part.
    • minIntegerDigits: min number of digits in the integer part.
    • integerOnly: True if only the integer part is parsed.
    • groupingUsed: True if grouping separators are used.
    • locale: Locale whose preferences are to be used for parsing and formatting.
    • currencyCode: ISO 4217 currency code to use when converting currency values.
    • currencySymbol: Currency symbol to use when converting currency values.

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:

  • javax.faces.Double
  • javax.faces.Integer
  • javax.faces.Float
  • javax.faces.Boolean

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:

Style Format
DEFAULT 26-Apr-99
SHORT 4/26/99
MEDIUM 26-Apr-99
LONG April 26, 1999
FULL Monday, April 26, 1999

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


Custom converters are nessesary if you need to convert field data into an application-specific object. There are five main steps in creating a custom converter.

  1. Implement the Converter instance (javax.faces.convert.Converter).
  2. Implement the getAsObject method, which converts a field (String) to an object.
  3. Implement the getAsString method, which converts an object to a String.
  4. Register your custom converter in faces-config.xml.
  5. Insert the converter into your page with the <f:converter/> tag.

The following is a step-by-step walk through on how to create a custom converter.

Step 1: Implement the Converter Interface

Create 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 Method

Here 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 method

Here 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 Context

This 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 Page

The 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


So far we have been using the <ice:messages/> tag to display all error messages at the bottom of the form. We use the <ice:message/> (singular, not plural) tag for component specific messages. By assigning this tag to a component with the for attribute, it will only display error messages for that component. If we locate the tag beside the component then it will be evident to the user hey have made a mistake in that input field. The following shows how to implement this with an inputText component:

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

The 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


Example Source Notes
converter-basic converter-basic source code Simple example of how to use the standard JSF converters.
converter-custom converter-custom source code A custom converter is added to the converter-basic application.
Enter labels to add to this page:
Please wait 
Looking for a label? Just start typing.

© Copyright 2021 ICEsoft Technologies Canada Corp.