Download
FAQ
History
HomeHomeNext API
Search
Feedback
Divider

Performing Data Conversions

A typical Web application must deal with two different viewpoints of the underlying data being manipulated by the user interface:

The JavaServer Faces implementation automatically converts component data between these two views through the component's renderer. For example, a UIInput component is automatically converted to a Number when it is rendered with the Number renderer. Similarly, a UIInput component that is rendered with the Date renderer is automatically converted to a Date.

The page author selects the component/renderer combination by choosing the appropriate tag: input_number for a UIInput/Number combination and input_date for a UIInput/Date combination. It is the application developer's responsibility to ensure that the model object property associated with the component is of the same type as that generated by the renderer.

Sometimes you might want to convert a component's data to a type not supported by the component's renderer, or you might want to convert the format of the data. To facilitate this, JavaServer Faces technology allows you to register a Converter implementation on certain component/renderer combinations. These combinations are: UIInput/Text, UIInput/Secret, UIInput/Hidden, and UIOutput/Text.


Note: In a future release, the mechanism of using component/renderer combinations to perform conversions might be removed. Instead, the page author would register a converter on a component associated with an input_text, input_secret, input_hidden, or output_text tag to perform conversions.


The Converter converts the data between the two views. You can either use the standard converters supplied with the JavaServer Faces implementation or create your own custom Converter. This section describes how to use the standard Converter implementations and explains an example of a custom Converter.

Using the Standard Converters

The JavaServer Faces implementation provides a set of Converter implementations that you can use to convert your component data to a type not supported by its renderer. The page author can apply a Converter to a component's value by setting the component tag's converter attribute to the identifier of the Converter. In addition, the page author can customize the behavior of the Converter with an attribute tag, which specifies the format of the converted value. The following tag is an example of applying a Number converter to a component and specifying the format of the Number:

<h:input_text id="salePrice"
  valueRef="LoginBean.sale"
  converter="Number">
  <f:attribute name="numberStyle" value="currency"/>
</h:input_text> 

As shown in the tag above, the salePrice component's value is converted to a Number with a currency format. Table 21-16 lists all of the standard Converter identifiers, the attributes you can use to customize the behavior of the converter, and the acceptable values for the format of the data.

Table 21-16 Standard Converter Implementations 
Converter Identifier
Configuration Attributes
Pattern Defined by
Valid Values for Attributes
Boolean
none
 
 
Date
dateStyle
java.text.DateFormat
short, medium, long, full.
Default: short
timezone
java.util.TimeZone
See
java.util.TimeZone
DateFormat
formatPattern
java.text.DateFormat
See the Formatting lesson in The Java Tutorial
timezone
java.util.TimeZone
See
java.util.TimeZone
DateTime
dateStyle
java.text.DateFormat
short, medium, long, full
Default: short
timeStyle
java.text.DateFormat
short, medium, long, full.
Default: short
timezone
java.util.TimeZone
See
java.util.TimeZone
Number
numberStyle
java.text.NumberFormat
currency, integer,
number,
percent
Default: integer
NumberFormat
formatPattern
java.text.NumberFormat
See the Formatting lesson in The Java Tutorial.
Time
timeStyle
java.text.DateFormat
short, medium, long, full.
Default: short
timezone
java.util.TimeZone
See
java.util.TimeZone

Creating and Using a Custom Converter

If the standard Converter implementations don't perform the kind of data conversion you need to perform, you can easily create a custom Converter implementation for this purpose. To create and use a custom Converter, you need to perform these steps:

  1. Implement the Converter interface
  2. Register the Converter with application
  3. Use the Converter in the page

The cardemo application uses a custom Converter, called CreditCardConverter, to convert the data entered in the Credit Card Number field. It strips blanks and dashes from the text string and formats the text string so that a blank space separates every four characters. This section explains how this converter works.

Implement the Converter Interface

All custom converters must implement the Converter interface. This implementation--at a minimum--must define how to convert data both ways between the two views of the data.

To define how the data is converted from the presentation view to the model view, the Converter implementation must implement the getAsObject(FacesContext, UIComponent, String) method from the Converter interface. Here is the implementation of this method from CreditCardConverter:

public Object getAsObject(FacesContext context, 
    UIComponent component, String newValue) 
      throws ConverterException {
  String convertedValue = null;
  if ( newValue == null ) {
    return newValue;
  }
  convertedValue = newValue.trim();
  if ( ((convertedValue.indexOf("-")) != -1) || 
    ((convertedValue.indexOf(" ")) != -1)) {
    char[] input = convertedValue.toCharArray();
    StringBuffer buffer = new StringBuffer(50);
    for ( int i = 0; i < input.length; ++i ) {
      if ( input[i] == '-' || input[i] == ' '  ) {
        continue;
      } else {
        buffer.append(input[i]);
      }
    }
    convertedValue = buffer.toString();
  }
  return convertedValue;
} 

During the Apply Request Values phase, when the components' decode methods are processed, the JavaServer Faces implementation looks up the component's local value in the request and calls the getAsObject method. When calling this method, the JavaServer Faces implementation passes in the current FacesContext, the component whose data needs conversion, and the local value as a String. The method then writes the local value to a character array, trims the dashes and blanks, adds the rest of the characters to a String, and returns the String.

To define how the data is converted from the model view to the presentation view, the Converter implementation must implement the getAsString(FacesContext, UIComponent, Object) method from the Converter interface. Here is the implementation of this method from CreditCardConverter:

public String getAsString(FacesContext context, 
  UIComponent component,Object value) 
    throws ConverterException {
  String inputVal = null;
  if ( value == null ) {
    return null;
  }
  try {
    inputVal = (String)value;
  } catch (ClassCastException ce) {
    throw new ConverterException(Util.getExceptionMessage(
      Util.CONVERSION_ERROR_MESSAGE_ID));
    }
    char[] input = inputVal.toCharArray(); 
    StringBuffer buffer = new StringBuffer(50);
    for ( int i = 0; i < input.length; ++i ) {
      if ( (i % 4) == 0 && i != 0) {
        if (input[i] != ' ' || input[i] != '-'){
          buffer.append(" "); 
        } else if (input[i] == '-') {
            buffer.append(" "); 
        } 
      }
      buffer.append(input[i]);
    } 
    String convertedValue = buffer.toString();
    return convertedValue;
  } 

During the Render Response phase, in which the components' encode methods are called, the JavaServer Faces implementation calls the getAsString method in order to generate the appropriate output. When the JavaServer Faces implementation calls this method, it passes in the current FacesContext, the UIComponent whose value needs to be converted, and the model object value to be converted. Since this Converter does a String-to-String conversion, this method can cast the model object value to a String. It then reads the String to a character array and loops through the array, adding a space after every four characters.

Register the Converter

When you create a custom Converter, you need to register it with the application. Here is the converter declaration from the application configuration file:

<converter>
  <description>CreditCard Converter</description>
  <converter-id>creditcard</converter-id>
  <converter-class>
    cardemo.CreditCardConverter
  </converter-class>
</converter> 

The converter element represents a Converter implementation. The converter element contains required converter-id and converter-class elements.

The converter-id element identifies an ID that is used by the converter attribute of a UI component tag to apply the converter to the component's data.

The converter-class element identifies the Converter implementation.

Use the Converter in the Page

To apply the data conversion performed by your Converter to a particular component's value, you need to set the converter attribute of the component's tag to the Converter implementation's identifier. You provided this identifier when you registered the Converter with the application, as explained in the previous section.

The identifier for the CreditCardConverter is creditcard. The CreditCardConverter is attached to the ccno component, as shown in this tag from the Customer.jsp page:

<h:input_text id="ccno" size="16"
  converter="creditcard" >
  ...
</h:input_text> 

By setting the converter attribute of a component's tag to the identifier of a Converter, you cause that component's local value to be automatically converted according to the rules specified in the Converter.

A page author can use the same custom Converter for any similar component by simply supplying the Converter implementation's identifier to the converter attribute of the component's tag.

Divider
Download
FAQ
History
HomeHomeNext API
Search
Feedback
Divider

All of the material in The Java(TM) Web Services Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.