Download FAQ History |  | API Search Feedback

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

> - A 5-digit number
> - A 9-digit number, with a hyphen between the 5th and 6th digits
> - A 6-character string, consisting of numbers or letters, with a space between the 3rd and 4th character

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

> - Specify which validator class to use with the `validator` tag. The `Validator` implementation defines its own properties
> - Create a custom tag that provides attributes for configuring the properties of the validator 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:

> - Write a tag handler to create and register the `Validator` instance on the component
> - Write a TLD to define the tag and its attributes
> - Add the custom tag to the page.

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

> - Sets the ID of the `Validator` by calling `super.setId("FormatValidator")`.
> - Provides a set of accessor methods for each attribute defined on the tag.
> - Implements the `createValidator` method of the `ValidatorTag` class. This method creates an instance of the `Validator` and sets the range of values accepted by the validator.

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

> ##### 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.

Download FAQ History |  | API Search Feedback

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.