|
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.
All of these validator classes implement the
Validatorinterface. 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
Validatorimplementations, how to write your own custom validator by implementing theValidatorinterface, 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_errorstag. Here is an example of anoutput_errorstag:The
output_errorstag causes validation error messages to be displayed wherever the tag is located on the page. Theforattribute 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'sidattribute. If theforattribute 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 theoutput_errorstag with the validation tags.Using the Standard Validators
When using the standard
Validatorimplementations, 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 ofUIInput) and provide the necessary constraints, if the tag requires it. Validation can only be performed on components whose classes extendUIInputsince these components accept values that can be validated.The
Customer.jsppage of thecardemoapplication uses two of the standard validators:StringRangeValidatorandRequiredValidator. This section explains how to use these validators. The other standard validators are used in a similar way.Using the Required Validator
The
zipinput_texttag onCustomer.jspuses aRequiredValidator, which checks if the value of the component is null or is an empty String. If your component must have a non-nullvalue or aStringvalue at least one character in length, you should register this validator on the component. If you don't register aRequiredValidator, any other validators you have registered on the component will not be executed. This is because the other validators can only validate a non-nullvalue or aStringvalue of at least one character. Here is thezipinput_texttag fromCustomer.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
zipcomponent tag contains a custom validator tag besides thevalidate_requiredtag. This custom validator is discussed in section Creating a Custom Validator. In order for other validators to be processed, thevalidate_requiredtag 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_errorstag, an error will display on the page if the value is null or an emptyString. 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
middleInitialcomponent on theCustomer.jsppage uses aStringRangeValidator, which checks if the user only enters an alphabetic character in themiddleInitialcomponent. Here is themiddleInitialinput_texttag fromCustomer.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
middleInitialtag uses thesizeattribute and themaxlengthattribute. These attributes restrict the input to one character.The
validate_stringrangetag uses aStringRangeValidatorwhose 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:
The
cardemoapplication 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: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
Validatorinterface. This implementation must contain a constructor, a set of accessor methods for any attributes on the tag, and avalidatemethod, which overrides thevalidatemethod of theValidatorinterface.The
FormatValidatorclass implementsValidatorand validates the data on the Credit Card Number field and the Zip code field. This class defines accessor methods for setting the attributeformatPatterns, which specifies the acceptable format patterns for input into the fields.In addition to the constructor and the accessor methods, the class overrides
Validator.validateand provides a method calledgetMessageResources, which gets the custom error messages to be displayed when theStringis invalid.All custom
Validatorimplementations must override thevalidatemethod, which takes theFacesContextand the component whose data needs to be validated. This method performs the actual validation of the data. Here is thevalidatemethod fromFormatValidator: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 theformatPatternsListlist, which is the list of acceptable patterns as specified in theformatPatternsattribute of theformat_validatortag. 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'ssetValidmethod with the valuetrue. 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 callingcomponent.setValid(false), generates an error message, and queues the error message to theFacesContextso that the message is displayed on the page during the Render Response phase.The
FormatValidatorclass also provides thegetMessageResourcesmethod, 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 returnsApplicationinstances. The Application instance supports thegetMessageResources(String)method, which returns theMessageResourcesinstance identified bycarResources. ThisMessageResourcesinstance 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-resourceselement represents a set of localizable messages, which are all related to a uniquemessage-resources-id. Thismessage-resources-idis the identifier under which theMessageResourcesclass must be registered. It corresponds to a static message ID in theFormatValidatorclass:The
messageelement can contain any number of summary elements, each of which defines the localized messages. Thelangattribute 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
MessageResourcesclass, create separate XML files for each locale, and add code to aServletContextListenerimplementation. 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
validatorXML 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-idandvalidator-classare required subelements. Thevalidator-idrepresents the identifier under which theValidatorclass should be registered. This ID is used by the tag class corresponding to the customvalidatortag.The
validator-classelement represents the fully-qualified class name of theValidatorclass.The
attributeelement identifies an attribute associated with theValidator. It has requiredattribute-nameandattribute-classsubelements. Theattribute-nameelement refers to the name of the attribute as it appears in thevalidatortag. Theattribute-classelement 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
Validatorinstance on a component from the page:If you want to configure the attributes in the
Validatorimplementation rather than from the page, the page author only needs to nest af:validatortag inside the tag of the component whose data needs to be validated and set thevalidatortag'stypeattribute to the name of theValidatorimplementation:<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
ValidatorTagclass. This class is the base class for all custom tag handlers that createValidatorinstances and register them on a UI component. TheFormatValidatorTagis the class that registers theFomatValidatorinstance.The
FormatValidatortag handler class:
- Sets the ID of the
Validatorby callingsuper.setId("FormatValidator").- Provides a set of accessor methods for each attribute defined on the tag.
- Implements the
createValidatormethod of theValidatorTagclass. This method creates an instance of theValidatorand sets the range of values accepted by the validator.Here is the
createValidatormethod fromFormatValidator: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.createValidatorto get a newValidatorand casts it toFormatValidator.Next, the tag handler sets the
Validatorinstance'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-INFdirectory of your download bundle. It contains only one tag definition, forformat_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
nameelement defines the name of the tag as it must be used in the page. Thetag-classelement 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
taglibdirective at the top of each page that will contain the custom validator tags included in the tag library. Here is thetaglibdirective that declares the cardemo tag library:The
uriattribute value uniquely identifies the tag library. Theprefixattribute value is used to distinguish tags belonging to the tag library. Here is theformat_validatortag from theziptag onCustomer.jsp:To register this validator on the
zipcomponent (corresponding to the Zip Codefield) you need to nest theformat_validatortag within thezipcomponent 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_errorstag following thezipinput_texttag will cause the error messages to display next to the component on the page. Theforattribute 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.