Download
FAQ
History
PrevHomeNext API
Search
Feedback
Divider

Performing Validation

JavaServer Faces technology provides a set of standard classes and associated tags that page authors and application developers can use to validate a component's data. Table 21-15 lists all of the standard validator classes and the tags that allow you to use the validators from the page.

Table 21-15 The Validator Classes 
Validator Class
Tag
Function
DoubleRangeValidator
validate_doublerange
Checks if the local value of a component is within a certain range. The value must be floating-point or convertible to floating-point.
LengthValidator
validate_length
Checks if the length of a component's local value is within a certain range. The value must be a java.lang.String.
LongRangeValidator
validate_longrange
Checks if the local value of a component is within a certain range. The value must be anything that can be converted to a long.
RequiredValidator
validate_required
Checks if the local value of a component is not null. In addition, if the local value is a String, ensures that it is not empty.
StringRangeValidator
validate_stringrange
Checks if the local value of a component is within a certain range. The value must be a java.lang.String.

All of these validator classes implement the Validator interface. Component writers and application developers can also implement this interface to define their own set of constraints for a component's value.

This section shows you how to use the standard Validator implementations, how to write your own custom validator by implementing the Validator interface, and how to display error messages resulting from validation failures.

Displaying Validation Error Messages

A page author can output error messages resulting from both standard and custom validation failures using the output_errors tag. Here is an example of an output_errors tag:

<h:output_errors for="ccno" /> 

The output_errors tag causes validation error messages to be displayed wherever the tag is located on the page. The for attribute of the tag must match the id of the component whose data requires validation checking. This means that you must provide an ID for the component by specifying a value for the component tag's id attribute. If the for attribute is not specified, the errors resulting from all failed validations on the page will display wherever the tag is located on the page. The next two sections show examples of using the output_errors tag with the validation tags.

Using the Standard Validators

When using the standard Validator implementations, you don't need to write any code to perform validation. You simply nest the standard validator tag of your choice inside a tag that represents a component of type UIInput (or a subclass of UIInput) and provide the necessary constraints, if the tag requires it. Validation can only be performed on components whose classes extend UIInput since these components accept values that can be validated.

The Customer.jsp page of the cardemo application uses two of the standard validators: StringRangeValidator and RequiredValidator. This section explains how to use these validators. The other standard validators are used in a similar way.

Using the Required Validator

The zip input_text tag on Customer.jsp uses a RequiredValidator, which checks if the value of the component is null or is an empty String. If your component must have a non-null value or a String value at least one character in length, you should register this validator on the component. If you don't register a RequiredValidator, any other validators you have registered on the component will not be executed. This is because the other validators can only validate a non-null value or a String value of at least one character. Here is the zip input_text tag from Customer.jsp:

<h:input_text id="zip" valueRef="CustomerBean.zip" size="10">
  <f:validate_required />
  <cd:format_validator 
    formatPatterns="99999|99999-9999|### ###" />
</h:input_text>
<h:output_errors for="zip" /> 

The zip component tag contains a custom validator tag besides the validate_required tag. This custom validator is discussed in section Creating a Custom Validator. In order for other validators to be processed, the validate_required tag is needed to first check if the value is null or a String value of at least one character. However, you can register the validator tags in any order; you don't have to register the RequiredValidator first.

Because of the output_errors tag, an error will display on the page if the value is null or an empty String. When the user enters a value in response to seeing the error message, the other validators can check the validity of the value.

Using the StringRangeValidator

The middleInitial component on the Customer.jsp page uses a StringRangeValidator, which checks if the user only enters an alphabetic character in the middleInitial component. Here is the middleInitial input_text tag from Customer.jsp:

<h:input_text id="middleInitial" size="1"
  maxlength="1" valueRef="CustomerBean.middleInitial" >
  <f:validate_stringrange minimum="A" maximum="z"/>
</h:input_text>
<h:output_errors  clientId="middleInitial"/> 

The middleInitial tag uses the size attribute and the maxlength attribute. These attributes restrict the input to one character.

The validate_stringrange tag uses a StringRangeValidator whose attributes restrict the value entered to a single alphabetic character from the range A to Z, ignoring case.

Creating a Custom Validator

If the standard validators don't perform the validation checking you need, you can easily create a custom validator for this purpose. To create and use a custom validator, you need to:

  1. Implement the Validator interface
  2. Register the error messages
  3. Register the Validator class
  4. Create a custom tag or use the validator tag

The cardemo application uses a general-purpose custom validator that validates input data against a format pattern that is specified in the custom validator tag. This validator is used with the Credit Card Number field and the Zip code field. Here is the custom validator tag used with the Zip code field:

<cd:format_validator 
  formatPatterns="99999|99999-9999|### ###" /> 

According to this validator, the data entered in the Zip code field must be either:

The rest of this section describe how this validator is implemented, how it works, and how to use it in a page.

Implement the Validator Interface

All custom validators must implement the Validator interface. This implementation must contain a constructor, a set of accessor methods for any attributes on the tag, and a validate method, which overrides the validate method of the Validator interface.

The FormatValidator class implements Validator and validates the data on the Credit Card Number field and the Zip code field. This class defines accessor methods for setting the attribute formatPatterns, which specifies the acceptable format patterns for input into the fields.

In addition to the constructor and the accessor methods, the class overrides Validator.validate and provides a method called getMessageResources, which gets the custom error messages to be displayed when the String is invalid.

All custom Validator implementations must override the validate method, which takes the FacesContext and the component whose data needs to be validated. This method performs the actual validation of the data. Here is the validate method from FormatValidator:

public void validate(FacesContext context, UIComponent 
component) {

  if ((context == null) || (component == null)) {
    throw new NullPointerException();
  }
  if (!(component instanceof UIOutput)) {
    return;
  }
  if ( formatPatternsList == null ) {
    component.setValid(true);
    return;
  }
  String value =
    (((UIOutput)component).getValue()).toString();
  Iterator patternIt = formatPatternsList.iterator();
  while (patternIt.hasNext()) {
    valid = isFormatValid(((String)patternIt.next()), value);
    if (valid) {
      break;
    }
  }
  if ( valid ) {
    component.setValid(true);
  } else { 
    component.setValid(false);
    Message errMsg =
      getMessageResources().getMessage(context,
        FORMAT_INVALID_MESSAGE_ID, 
        (new Object[] {formatPatterns}));
    context.addMessage(component, errMsg);
  }
} 

This method gets the local value of the component and converts it to a String. It then iterates over the formatPatternsList list, which is the list of acceptable patterns as specified in the formatPatterns attribute of the format_validator tag. While iterating over the list, this method checks the pattern of the local value against the patterns in the list. If the value's pattern matches one of the acceptable patterns, this method stops iterating over the list and marks the components value as valid by calling the component's setValid method with the value true. If the pattern of the local value does not match any pattern in the list, this method: marks the component's local value invalid by calling component.setValid(false), generates an error message, and queues the error message to the FacesContext so that the message is displayed on the page during the Render Response phase.

The FormatValidator class also provides the getMessageResources method, which returns the error message to display when the data is invalid:

public synchronized MessageResources getMessageResources() {
  MessageResources carResources = null;
  ApplicationFactory aFactory = (ApplicationFactory)
    FactoryFinder.getFactory(
    FactoryFinder.APPLICATION_FACTORY);
  Application application =
    aFactory.getApplication();
  carResources =
    application.getMessageResources("carDemoResources");
  return (carResources);
} 

This method first gets an ApplicationFactory, which returns Application instances. The Application instance supports the getMessageResources(String) method, which returns the MessageResources instance identified by carResources. This MessageResources instance is registered in the application configuration file. This is explained in the next section.

Register the Error Messages

If you create custom error messages, you need to make them available at application startup time. You do this by registering them using the application configuration file.


Note: This technique for registering messages is not utilized in the version of cardemo shipped with this release. The cardemo application will be updated to use this technique in future releases.


Here is the part of the file that registers the error messages:

<message-resources>
  <message-resources-id>
    carDemoResources
  </message-resources-id>
  <message>
    <message-id>cardemo.Format_Invalid</message-id>
     <summary xml:lang="en">
      Input must match one of the following patterns
      {0}
    </summary>
    <summary xml:lang="de">
      Eingang mu? eins der folgenden Muster
      zusammenbringen {0}
    </summary>
    <summary xml:lang="es">
      La entrada debe emparejar uno de los
      patrones siguientes {0}
    </summary>
    <summary lang="fr">
      L'entrée doit assortir un des modèles
      suivants {0}
    </summary>
  </message>
</message-resources> 

The message-resources element represents a set of localizable messages, which are all related to a unique message-resources-id. This message-resources-id is the identifier under which the MessageResources class must be registered. It corresponds to a static message ID in the FormatValidator class:

public static final String FORMAT_INVALID_MESSAGE_ID = 
  "cardemo.Format_Invalid"; 

The message element can contain any number of summary elements, each of which defines the localized messages. The lang attribute specifies the language code.

This is all it takes to register message resources. Prior to this release, you had to write an implementation of the MessageResources class, create separate XML files for each locale, and add code to a ServletContextListener implementation. Now, all you need are a few simple lines in the application configuration file to register message resources.

Register the Custom Validator

Just as the message resources need to be made available at application startup time, so does the custom validator. You register the custom validator in the application configuration file with the validator XML tag:

<validator>
  <description>FormatValidator Description</description>
  <validator-id>FormatValidator</validator-id>
  <validator-class>cardemo.FormatValidator</validator-class>
  <attribute>
    <description>
      List of format patterns separated by '|'
    </description>
    <attribute-name>formatPatterns</attribute-name>
    <attribute-class>java.lang.String</attribute-class>
  </attribute>
</validator> 

The validator-id and validator-class are required subelements. The validator-id represents the identifier under which the Validator class should be registered. This ID is used by the tag class corresponding to the custom validator tag.

The validator-class element represents the fully-qualified class name of the Validator class.

The attribute element identifies an attribute associated with the Validator. It has required attribute-name and attribute-class subelements. The attribute-name element refers to the name of the attribute as it appears in the validator tag. The attribute-class element identifies the Java type of the value associated with the attribute.

Create a Custom Tag or Use the validator Tag

There are two ways to register a Validator instance on a component from the page:

If you want to configure the attributes in the Validator implementation rather than from the page, the page author only needs to nest a f:validator tag inside the tag of the component whose data needs to be validated and set the validator tag's type attribute to the name of the Validator implementation:

<h:input_text id="zip" valueRef="CustomerBean.zip"
      size="10" ... >
  <f:validator type="cardemo.FormatValidator" />
  ...
</h:input_text> 

If you want to use a custom tag, you need to:

Writing the Tag Handler

The tag handler associated with a custom validator tag must extend the ValidatorTag class. This class is the base class for all custom tag handlers that create Validator instances and register them on a UI component. The FormatValidatorTag is the class that registers the FomatValidator instance.

The FormatValidator tag handler class:

Here is the createValidator method from FormatValidator:

protected Validator createValidator() throws JspException {
  FormatValidator result = null;
  result = (FormatValidator) super.createValidator();
  Assert.assert_it(null != result);
  result.setFormatPatterns(formatPatterns);
  return result;
} 

This method first calls super.createValidator to get a new Validator and casts it to FormatValidator.

Next, the tag handler sets the Validator instance's attribute values to those supplied as tag attributes in the page. The handler gets the attribute values from the page via the accessor methods that correspond to the attributes.

Writing the Tag Library Descriptor

To define a tag, you need to declare it in a tag library descriptor (TLD), which is an XML document that describes a tag library. A TLD contains information about a library and each tag contained in the library.

The custom validator tag for the Credit Card Number and Zip Code fields is defined in the cardemo.tld, located in <JWSDP_HOME/jsf/samples/cardemo/web/WEB-INF directory of your download bundle. It contains only one tag definition, for format_validator:

<tag>
  <name>format_validator</name>
  <tag-class>cardemo.FormatValidatorTag</tag-class>
  <attribute>
    <name>formatPatterns</name>
    <required>true</required>
    <rtexprvalue>false</rtexprvalue>
  </attribute>
</tag> 

The name element defines the name of the tag as it must be used in the page. The tag-class element defines the tag handler class. The attribute elements define each of the tag's attributes. For more information on defining tags in a TLD, please see Tag Library Descriptors (page 737).

Adding the Custom Tag to the Page

To use the custom validator in the JSP page, you need to declare the custom tag library that defines the custom tag corresponding to the custom component.

To declare the custom tag library, include a taglib directive at the top of each page that will contain the custom validator tags included in the tag library. Here is the taglib directive that declares the cardemo tag library:

<%@ taglib uri="/WEB-INF/cardemo.tld" prefix="cd" %> 

The uri attribute value uniquely identifies the tag library. The prefix attribute value is used to distinguish tags belonging to the tag library. Here is the format_validator tag from the zip tag on Customer.jsp:

<cd:format_validator 
    formatPatterns="99999|99999-9999|## ###" /> 

To register this validator on the zip component (corresponding to the Zip Codefield) you need to nest the format_validator tag within the zip component tag:

<h:input_text id="zip" valueRef="CustomerBean.zip" size="10" >
  ...
  <cd:format_validator 
    formatPatterns="99999|99999-9999|### ###" />
</h:input_text>
<h:output_errors for="zip" /> 

The output_errors tag following the zip input_text tag will cause the error messages to display next to the component on the page. The for attribute refers to the component whose value is being validated.

A page author can use the same custom validator for any similar component by simply nesting the custom validator tag within the component tag.

Divider
Download
FAQ
History
PrevHomeNext 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.