JSF : Convertors

Converters in JSF are used to easily convert a value from one data type to other. The JavaServer Faces implementation provides a set of Converter implementations that you can use to convert component data. The purpose of conversion is to take the String-based data coming in from the Servlet API and convert it to strongly typed Java objects suitable for the business domain. 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.

Using the Standard Converters

The standard Converter implementations are located in the javax.faces.convert package. Normally, converters are implicitly assigned based on the type of the EL expression pointed to by the value of the component. However, these converters can also be accessed by a converter ID. For eg.

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

A standard error message is associated with each of these converters. If you have registered one of these converters onto a component on your page and the converter is not able to convert the component’s value, the converter’s error message will display on the page.

To use a particular converter to convert a component’s value, you need to register the converter onto the component. You can register any of the standard converters in one of the following ways.

  • Bind the value of the component to a managed bean property of the same type as the converter. This is the most common technique.
  • Refer to the converter from the component tag’s converter attribute, specifying the ID of the converter class.
  • Nest one of the standard converter tags inside the component’s tag. These tags are f:convertDateTimeand f:convertNumber, which are described in Using DateTimeConverter and Using NumberConverter, respectively.
  • Nest an f:converter tag inside of the component tag, and use either the f:converter tag’s converterId attribute or its binding attribute to refer to the converter.

If you want a component’s data to be converted to an Integer, you can simply bind the component’s value to a managed bean property.
<h:inputText value=”#{convertorBasicForm.age}” id=”age”></h:inputText> //xhtml
private int age; //In your convertorBasicForm bean with getters and setters

Two of the standard converters (DateTimeConverter and NumberConverter) have their own tags, which allow you to configure the format of the component data using the tag attributes.

 Using DateTimeConverter

You can convert a component’s data to a java.util.Date by nesting the convertDateTime tag inside the component tag. The convertDateTime tag has several attributes that allow you to specify the format and type of the data.

Lets see this by example :


<h:form>
<h:panelGrid columns="2">
<h:outputLabel for="age" value="Age: "></h:outputLabel>
<h:inputText value="#{convertorBasicForm.age}" id="age"></h:inputText>
<h:outputLabel for="date1" value="Todays Date 1: "></h:outputLabel>
<h:outputText value="#{convertorBasicForm.date1}" id="date1">
<f:convertDateTime type="date" dateStyle="full" />
</h:outputText>
<h:outputLabel for="date2" value="Todays Date 2: "></h:outputLabel>
<h:outputText value="#{convertorBasicForm.date2}" id="date2">
<f:convertDateTime pattern="EEEEEEEE, MMM dd, yyyy" />
</h:outputText>
<h:outputLabel for="date3" value="Todays Date 3 Esp: "></h:outputLabel>
<h:outputText value="#{convertorBasicForm.date3}" id="date3">
<f:convertDateTime dateStyle="full" locale="es" timeStyle="long"
type="both" />
</h:outputText>
<h:outputLabel for="date4"
value="Enter a date in dd/mm/yyyy format: "></h:outputLabel>
<h:inputText id="date4" required="true"
requiredmessage="Please enter a date !!!"
value="#{convertorBasicForm.date4}">
<f:convertDateTime pattern="dd/MM/yyyy" type="date">
</f:convertDateTime>
</h:inputText>
<h:message for="date4" style="color: red; font-weight: bold;"></h:message>
<h:commandButton value="Submit"
action="#{converterBasicAction.submit}"></h:commandButton>

</h:panelGrid>
</h:form>

ConvertorBasicForm snippet-


private int age;
private Date date1=new Date();
private Date date2=new Date();
private Date date3=new Date();
private Date date4;

//with getters an setters

date1 – is an simple example of a convertDateTime tag. Ensure that the managed bean property to which the component is bound is of type java.util.Date.
date2 – is an example to show that you can change the format using pattern attribute.
date3 – shows that you can display the  date in Spanish, you can use the locale attribute.
date4 – is an input text where we have specified the format. If the user enters anything else, an error message will be displayed

Sample output –

conterterDateTime

Using NumberConverter

You can convert a component’s data to a java.lang.Number by nesting the convertNumber tag inside the component tag. The convertNumber tag has several attributes that allow you to specify the format and type of the data. Lets see by an example-


<h3>Number Converter</h3>
<table border="1" cellspacing="2" cellpadding="2">
<tr>
<th>Parameter</th>
<th>Value Passed</th>
<th>Output</th>
</tr>
<tr>
<td>maxFractionDigits="2"</td>
<td>100.12345</td>
<td><h:outputText value="100.12345">
<f:convertNumber maxFractionDigits="2" />
</h:outputText></td>
</tr>
<tr>
<td>pattern="##,###.##"</td>
<td>1000.12345</td>
<td><h:outputText value="1000.12345">
<f:convertNumber pattern="##,###.##" />
</h:outputText></td>
</tr>
<tr>
<td>locale France from Form</td>
<td>value from form 32112323.132</td>
<td><h:outputText value="#{convertorBasicForm.bigdecimal}">
<f:convertNumber type="currency" locale="#{convertorBasicForm.locale}"/>
</h:outputText></td>
</tr>
</table>


private BigDecimal bigdecimal=new BigDecimal(32112323.132);
private Locale locale= Locale.FRANCE;

//with getters and setters

Output –

conterterNumber

Using a Custom Converter

If the standard converters do not fulfill yours needs then you may want to create your own. There are several steps to creating a custom converter including…

  1. Create a converter class that implements the “javax.faces.convert.Converter” interface.
  2. Implement the getAsObject() and getAsString() methods within your converter class.
  3. Register your converter in faces-config.xml  (using <converter>) or use annotations.
  4. Use the <f:converter> tag in your page view.

This is where the two methods are invoked into the JSF lifecycle:

converterFlowImage

This example is a custom converter that formats an Credit card number by inserting ‘-‘ separators for output display, and stripping the ‘-‘ separators when retrieving the Credit card number from UIInput component. CreditCardConverter.java:


package mynotes.jsf.util;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;

@FacesConverter("ccno")
public class CreditCardConverter implements Converter {

@Override
public Object getAsObject(FacesContext context, UIComponent component,String value) {
System.out.println("Inside getAsObject");
System.out.println("Inside getAsObject value=>" + value);
if (value == null) {
return null;
}
// Since this is only a String to String conversion,
// this conversion does not throw ConverterException.

return value.replaceAll("-", "").trim();
}

@Override
public String getAsString(FacesContext context, UIComponent component,Object value) {
System.out.println("Inside getAsString");
if (value == null) {
return null;
}
System.out.println("Inside getAsString value=>" + value.toString());

String ccno = value.toString();
StringBuffer formattedBuffer = new StringBuffer();
String part1 = ccno.substring(0, 4);
String part2 = ccno.substring(4, 8);
String part3 = ccno.substring(8, 12);
String part4 = ccno.substring(12, 16);

formattedBuffer.append(part1);
formattedBuffer.append("-");
formattedBuffer.append(part2);
formattedBuffer.append("-");
formattedBuffer.append(part3);
formattedBuffer.append("-");
formattedBuffer.append(part4);

return formattedBuffer.toString();
}

}

The identifier for the credit card converter class is ccno, the value specified in the @FacesConverter annotation.

ConverterCustomFormAndAction.java


package mynotes.jsf.bean;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

@ManagedBean(name="converterCustomFormAndAction")
@SessionScoped
public class ConverterCustomFormAndAction {

private String creditCardNumber="1234567812345678";

public String getCreditCardNumber() {
return creditCardNumber;
}

public void setCreditCardNumber(String creditCardNumber) {
this.creditCardNumber = creditCardNumber;
}

public String submit(){
System.out.println("Inside Submit");
System.out.println("CCno="+this.creditCardNumber);
return "covertersCustom";
}

}

Displaying in html-


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>Converter Custom</title>
</head>
<h:body>
<h:form>
<h:inputText id="creditCard" size="19"
value="#{converterCustomFormAndAction.creditCardNumber}">
<f:converter converterId="ccno" />
</h:inputText>
<h:commandButton value="Submit" action="#{converterCustomFormAndAction.submit}"></h:commandButton>
</h:form>
</h:body>
</html>

Output in logs –


Inside getAsString
Inside getAsString value=>1234567812345678
Inside getAsObject
Inside getAsObject value=>1234-5678-1234-9999
Inside Submit
CCno=1234567812349999
Inside getAsString
Inside getAsString value=>1234567812349999

When the page is forst called the getAsString() method is called to display the value in out custom format. Then we submitted a changed value which is captured as a String object in  getAsObject() method and is converted to another String object stripping off the ‘-‘. Because we are redirecting to the same page again, getAsString() is again called.

conterterCustom

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: