Using Standard Validators

Using Standard Converters

In the following sections, we cover the converters and validators that are part of the JSF library. Later in this chapter, you learn how to supply your own validation code if your needs go beyond the basics.

Conversion of Numbers and Dates

A web application stores data of many types, but the web user interface deals exclusively with strings. For example, suppose the user needs to edit a Date object that is stored in the business logic. First, the Date object is converted to a string that is sent to the client browser to be displayed inside a text field. The user then edits the text field. The resulting string is returned to the server and must be converted back to a Date object.

The same situation holds, of course, for primitive types such as int, double, or boolean. The user of the web application edits strings, and the JSF container needs to convert the string to the type required by the application.

To see a typical use of a built-in converter, imagine a web application that is used to process payments (see Figure 6-2). The payment data includes

Figure 6-2. Processing payments


  • The amount to be charged

  • The credit card number

  • The credit card expiration date

We attach a converter to the text field and tell it to format the current value with at least two digits after the decimal point:

  <h:inputText value="#{payment.amount}">      <f:convertNumber minFractionDigits="2"/>   </h:inputText>

The f:convertNumber converter is one of the standard converters supplied by the JSF implementation.

The second field in this screen does not use a converter. (Later in this chapter, we attach a custom converter.) The third field uses an f:convertDateTime converter whose pattern attribute is set to the string MM/yyyy. (The pattern string format is documented in the API documentation for the java.text.SimpleDateFormat class.)

  <h:inputText value="#{payment.date}">      <f:convertDateTime pattern="MM/yyyy"/>   </h:inputText>

In the result.jsp page, we show the inputs that the user provided, using a different converter for the payment amount:

  <h:outputText value="#{payment.amount}">       <f:convertNumber type="currency"/>   </h:outputText>

This converter automatically supplies a currency symbol and decimal separators (see Figure 6-3).

Figure 6-3. Displaying the payment information


Converters and Attributes

Tables 6-1 and 6-2 show the standard converters and their attributes.

Table 6-1. Attributes of the f:convertNumber Tag
Attribute Type Value
type String number (default), currency, or percent
pattern String Formatting pattern, as defined in java.text.DecimalFormat
maxFractionDigits int Maximum number of digits in the fractional part
minFractionDigits int Minimum number of digits in the fractional part
maxIntegerDigits int Maximum number of digits in the integer part
minIntegerDigits int Minimum number of digits in the integer part
integerOnly boolean True if only the integer part is parsed (default: false)
groupingUsed boolean True if grouping separators are used (default: true)
locale java.util.Locale Locale whose preferences are to be used for parsing and formatting
currencyCode String ISO 4217 currency code to use when converting currency values
currencySymbol String Currency symbol to use when converting currency values


Table 6-2. Attributes of the f:convertDateTime Tag
Attribute Type Value
type String date (default), time, or both
dateStyle String default, short, medium, long, or full
timeStyle String default, short, medium, long, or full
pattern String Formatting pattern, as defined in java.text.SimpleDateFormat
locale java.util.Locale Locale whose preferences are to be used for parsing and formatting
timeZone java.util.TimeZone Time zone to use for parsing and formatting


Note

If you use a value expression whose type is either a primitive type, or, starting with JSF 1.2, an enumerated type or BigInteger/BigDecimal, then you do not need to specify any converter. The JSF implementation automatically picks a standard converter. However, you need to specify an explicit converter for Date values.


The converter Attribute

An alternate syntax for attaching a converter to a component is to add the converter attribute to the component tag. You specify the ID of the converter like this:

  <h:outputText value="#{payment.date}" converter="javax.faces.DateTime"/>

This is equivalent to using f:convertDateTime with no attributes:

  <h:outputText value="#{payment.date}">      <f:convertDateTime/>   </h:outputText>

A third way of specifying the converter would be as follows:

  <h:outputText value="#{payment.date}">      <f:converter converter/>   </h:outputText>

All JSF implementations must define a set of converters with predefined IDs:

  • javax.faces.DateTime (used by f:convertDateTime)

  • javax.faces.Number (used by f:convertNumber)

  • javax.faces.Boolean, javax.faces.Byte, javax.faces.Character, javax.faces.Double, javax.faces.Float, javax.faces.Integer, javax.faces.Long, javax.faces.Short (automatically used for primitive types and their wrapper classes)

  • javax.faces.BigDecimal, javax.faces.BigInteger (automatically used for BigDecimal/BigInteger)

Additional converter IDs can be configured in an application configuration file (see "Specifying Converters" on page 243 for details).

Caution

When the value of the converter attribute is a string, then the value indicates the ID of a converter. However, if it is a value expression, then its value must be a converter object an object of a class that implements the Converter interface. That interface is introduced under "Programming with Custom Converters and Validators" on page 240.


Note

As of JSF 1.2, the f:convertNumber, f:convertDateTime, and f:converter tags have an optional binding attribute. This allows you to tie a converter instance to a backing bean property of type javax.faces.convert.Converter.


Conversion Errors

When a conversion error occurs, the following actions are the result:

  • The component whose conversion failed posts a message and declares itself invalid. (You will see in the following sections how to display the message.)

  • The JSF implementation redisplays the current page immediately after the Process Validations phase has completed. The redisplayed page contains all values that the user provided no user input is lost.

This behavior is generally desirable. If a user provides an illegal input for, say, a field that requires an integer, then the web application should not try to use that illegal input. The JSF implementation automatically redisplays the current page, giving the user another chance to enter the value correctly.

However, you should avoid overly restrictive conversion options for input fields. For example, consider the "Amount" field in our example. Had we used a currency format, then the current value would have been nicely formatted. But suppose a user enters 100 (without a leading $ sign). The currency formatter will complain that the input is not a legal currency value. That is too strict for human use.

To overcome this problem, you can program a custom converter. A custom converter can format a value prettily, yet be lenient when interpreting human input. Custom converters are described later in this chapter under "Programming with Custom Converters and Validators" on page 240.

Tip

When gathering input from the user, you should either use a lenient converter or redesign your form to be more user friendly. For example, rather than forcing users to format the expiration date as MM/yyyy, you can supply two input fields, one for the month and another for the year.


Displaying Error Messages

Of course, it is important that the user be able to see the messages that are caused by conversion and validation errors. You should add h:message tags whenever you use converters and validators.

Normally, you want to show the error messages next to the components that reported them (see Figure 6-4). Give an ID to the component and reference that ID in the h:message tag. As of JSF 1.2, you also need to supply a component label that is displayed in the error message.

   <h:inputText  label="#{msgs.amount}" value="#{payment.amount}"/>    <h:message for="amount"/>     

Figure 6-4. Displaying a conversion error message


For JSF 1.1, omit the label attribute.

The h:message tag takes a number of attributes to describe the appearance of the message (see "Messages" on page 157 of Chapter 4 for details). Here, we discuss only the attributes that are of particular interest for error reporting.

A message has two versions: summary and detail.

For the number converter, the detail error message shows the label of the component, the offending value, and a sample of a correct value, like this:

Amount: 'too much' is not a number. Example: 99

The summary message omits the example.

Note

In JSF 1.1, the converters displayed a generic message "Conversion error occurred."


By default, the h:message tag shows the detail and hides the summary. If you want to show the summary message instead, use these attributes:

  <h:message for="amount" showSummary="true" showDetail="false"/>

Caution

If you use a standard converter, display either the summary message or the detail message, but not both the messages are nearly identical. You do not want your users to ponder an error message that reads "...is not a number ... is not a number. Example: 99".


Tip

If you do not use an explicit f:convertNumber converter but instead rely on the standard converters for numeric types, use the summary message and not the detail message. The detail messages give far too much detail. For example, the standard converter for double values has this detail message: "... must be a number between 4.9E-324 and 1.7976931348623157E308 Example: 1999999".


Usually, you will want to show error messages in a different color. You use the styleClass or style attribute to change the appearance of the error message:

   <h:messages style/>

or

   <h:message for="amount" style="color:red"/>

We recommend that you use styleClass and a style sheet instead of a hardcoded style.

Displaying All Error Messages

It is uncommon to have multiple messages for one component, but it can happen. The h:message tag produces only the first message. Unfortunately, you do not know whether the first message is the most useful one for the user. While no tag shows all messages for a particular component, you can show a listing of all messages from all components with the h:messages tag.

By default, the h:messages tag shows the message summary instead of the message detail. This behavior is opposite from that of the h:message tag.

For h:messages, you usually want to set the layout attribute to "table" so that the messages are lined up vertically. Otherwise they are concatenated.

   <h:messages layout="table"/>

Tip

Whenever you create a message, make sure it ends with a period and a space, to ensure a neat appearance when messages are concatenated.


Tip

The h:messages tag is useful for debugging. Whenever your JSF application stalls at a particular page and is unwilling to move on, add a <h:messages/> tag to see if a failed conversion or validation is the culprit.


Caution

In JSF 1.1, the error messages did not include the message label. That made the h:messages tag far less useful because users were left wondering which of their inputs caused an error.


Using a Custom Error Message

Starting with JSF 1.2, you can provide a custom converter error message for a component. Set the converterMessage attribute of the component whose value is being converted. For example,

  <h:inputText ... converterMessage="Not a valid number."/>

Caution

Unlike the message strings of the next section, these message attributes are taken literally. Placeholders such as {0} are not replaced.


Changing the Text of Standard Error Messages

Sometimes, you may want to change the standard conversion messages for your entire web application. Table 6-3 shows the most useful standard messages. Note that all detail message keys end in _detail. To save space, the table does not list separate summary and detail strings when the summary string is a substring of the detail string. Instead, the additional detail phrase is set in italics. In most messages, {0} is the invalid value, {1} is a sample valid value, and {2} is the component label; however, for the Boolean converter, {1} is the component label.

Table 6-3. Standard Conversion Error Messages
Resource ID Default Text

javax.faces.converter.IntegerConverter. INTEGER

{2}: "{0}" must be a number consisting of one or more digits.

javax.faces.converter.IntegerConverter. INTEGER_detail

{2}: "{0}" must be a number between -2147483648 and 2147483647.

Example: {1}

javax.faces.converter.DoubleConverter. DOUBLE

{2}: "{0}" must be a number consisting of one or more digits.

javax.faces.converter.DoubleConverter. DOUBLE_detail

{2}: "{0}" must be a number between 4.9E-324 and 1.7976931348623157E308.

Example: {1}

javax.faces.converter.BooleanConverter. BOOLEAN_detail

{1}: "{0}" must be 'true' or 'false'. Any value other than 'true' will evaluate to 'false'.

javax.faces.converter.NumberConverter. NUMBER_detail

{2}: "{0}" is not a number.

Example: {1}

javax.faces.converter.NumberConverter. CURRENCY_detail

{2}: "{0}" could not be understood as a currency value.

Example: {1}

javax.faces.converter.NumberConverter. PERCENT_detail

{2}: "{0}" could not be understood as a percentage.

Example: {1}

javax.faces.converter.DateTimeConverter. DATE_detail

{2}: "{0}" could not be understood as a date.

Example: {1}

javax.faces.converter.DateTimeConverter. TIME_detail

{2}: "{0}" could not be understood as a time.

Example: {1}

javax.faces.converter.DateTimeConverter. PATTERN_TYPE

{1}: A 'pattern' or 'type' attribute must be specified to convert the value "{0}".

javax.faces.converter.EnumConverter. ENUM

{2}: "{0}" must be convertible to an enum.

javax.faces.converter.EnumConverter. ENUM_detail

{2}: "{0}" must be convertible to an enum from the enum that contains the constant "{1}".

javax.faces.converter.EnumConverter. ENUM_NO_CLASS

{1}: "{0}" must be convertible to an enum from the enum, but no enum class provided.

javax.faces.converter.EnumConverter. ENUM_NO_CLASS_detail

{1}: "{0}" must be convertible to an enum from the enum, but no enum class provided.


To replace a standard message, set up a message bundle, as explained in Chapter 2. Add the replacement message, using the appropriate key from Table 6-3.

Suppose you do not want to fuss with input labels or example values when the f:convertNumber converter reports an error. Add the following definition to a message bundle:

  javax.faces.converter.NumberConverter.NUMBER_detail=''{0}'' is not a number.     

Then set the base name of the bundle in a configuration file (such as faces-config.xml):

  <faces-config>      <application>         <message-bundle>com.corejsf.messages</message-bundle>      </application>      ...   </faces-config>

You need only specify the messages that you want to override.

Note

In JSF 1.1, the generic message "Conversion error occurred" has key javax.faces.component.UIInput.Conversion.


A Complete Converter Example

We are now ready for our first complete example. Figure 6-5 shows the directory structure of the application. This web application asks the user to supply payment information (Listing 6-1) and then displays the formatted information on a confirmation screen (Listing 6-2). The messages are in Listing 6-3 and the bean class is in Listing 6-4.

Figure 6-5. Directory structure of the converter sample


Listing 6-1. converter/web/index.jsp

  1. <html>   2.    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>   3.    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>   4.    <f:view>   5.       <head>   6.          <link href="styles.css" rel="stylesheet" type="text/css"/>   7.          <title><h:outputText value="#{msgs.title}"/></title>   8.       </head>   9.       <body>  10.          <h:form>  11.             <h1><h:outputText value="#{msgs.enterPayment}"/></h1>  12.             <h:panelGrid columns="3">  13.                <h:outputText value="#{msgs.amount}"/>  14.                <h:inputText  label="#{msgs.amount}"   15.                      value="#{payment.amount}">   16.                   <f:convertNumber minFractionDigits="2"/>   17.                </h:inputText>  18.                <h:message for="amount" style/>  19.  20.                <h:outputText value="#{msgs.creditCard}"/>  21.                <h:inputText  label="#{msgs.creditCard}"  22.                      value="#{payment.card}"/>  23.                <h:panelGroup/>  24.  25.                <h:outputText value="#{msgs.expirationDate}"/>  26.                <h:inputText  label="#{msgs.expirationDate}"  27.                      value="#{payment.date}">  28.                   <f:convertDateTime pattern="MM/yyyy"/>  29.                </h:inputText>  30.                <h:message for="date" style/>  31.             </h:panelGrid>  32.             <h:commandButton value="#{msgs.process}" action="process"/>  33.          </h:form>  34.       </body>  35.    </f:view>  36. </html>     

Listing 6-2. converter/web/result.jsp

  1. <html>   2.    <%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>   3.    <%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>   4.    <f:view>   5.       <head>   6.          <link href="styles.css" rel="stylesheet" type="text/css"/>   7.          <title><h:outputText value="#{msgs.title}"/></title>   8.       </head>   9.       <body>  10.          <h:form>  11.             <h1><h:outputText value="#{msgs.paymentInformation}"/></h1>  12.             <h:panelGrid columns="2">  13.                <h:outputText value="#{msgs.amount}"/>  14.                <h:outputText value="#{payment.amount}">   15.                   <f:convertNumber type="currency"/>  16.                </h:outputText>  17.  18.                <h:outputText value="#{msgs.creditCard}"/>  19.                <h:outputText value="#{payment.card}"/>  20.  21.                <h:outputText value="#{msgs.expirationDate}"/>  22.                <h:outputText value="#{payment.date}">   23.                   <f:convertDateTime pattern="MM/yyyy"/>  24.                </h:outputText>  25.             </h:panelGrid>  26.             <h:commandButton value="Back" action="back"/>  27.          </h:form>  28.       </body>  29.    </f:view>  30. </html>     

Listing 6-3. converter/src/java/com/corejsf/messages.properties

  1. title=An Application to Test Data Conversion   2. enterPayment=Please enter the payment information   3. amount=Amount   4. creditCard=Credit Card   5. expirationDate=Expiration date (Month/Year)   6. process=Process   7. paymentInformation=Payment information

Listing 6-4. converter/src/java/com/corejsf/PaymentBean.java

  1. package com.corejsf;   2.   3. import java.util.Date;   4.   5. public class PaymentBean {   6.    private double amount;   7.    private String card = "";   8.    private Date date = new Date();   9.  10.    // PROPERTY: amount  11.    public void setAmount(double newValue) { amount = newValue; }  12.    public double getAmount() { return amount; }  13.  14.    // PROPERTY: card  15.    public void setCard(String newValue) { card = newValue; }  16.    public String getCard() { return card; }  17.  18.    // PROPERTY: date  19.    public void setDate(Date newValue) { date = newValue; }  20.    public Date getDate() { return date; }  21. }



Core JavaServerT Faces
Core JavaServer(TM) Faces (2nd Edition)
ISBN: 0131738860
EAN: 2147483647
Year: 2004
Pages: 84

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net