freefly
一门技术,如果不能讲出来,那么就是没有理解,如果不能很好的讲出来,那么就是理解不够透彻!
posts - 9,comments - 3,trackbacks - 0

Check Your Form with Validator

By James Holmes

Simplify Struts development with Validator's rich set of built-in validations.

One major benefit of the Struts framework is its built-in interface for performing data validations on incoming form data. If any validations fail, the application redisplays the HTML form so that the invalid data can be corrected. Otherwise, processing continues. The Struts framework's simple validation interface alleviates much of the headache associated with handling data validation, allowing you to focus on validation code and not on the mechanics of capturing data and redisplaying incomplete or invalid data.

Struts' built-in validation interface, however, has its shortcomings. Often, for example, validation code is heavily duplicated throughout an application, because many fields require the same validation logic. Any change in the validation logic for similar fields requires code changes in several places as well as recompilation of the affected code. To solve this problem and to enhance Struts' validation interface, the Validator framework was created as a third-party add-on to Struts. Validator was later integrated into the core Struts code base and has since been detached from Struts and is now a standalone Jakarta Commons project. Although Validator is an independent framework again, it still comes packaged and seamlessly integrated with Struts.

Validator Overview

Without Validator, you have to code all of your form data validations into the validate( ) methods of your Form Bean objects. Each Form Bean field on which you want to perform a validation requires you to code logic to do so. Additionally, you have to write code that stores error messages for validations that fail.

With Validator you don't have to write any code in your Form Beans for validations or storing error messages. Instead, your Form Beans extend one of Validator's ActionForm subclasses that provide this functionality for you.

The Validator framework is set up as a pluggable system of validation routines that can be applied to Form Beans. Each validation routine is simply a Java method responsible for performing a specific type of validation and can either pass or fail. By default, Validator comes packaged with several useful validation routines that will satisfy most validation scenarios. However, if you need a validation not provided by the Validator framework, you can create your own custom validation routine and plug it into the framework. Additionally, Validator supports both server-side and client-side (JavaScript) validations, whereas Form Beans provide only a server-side validation interface.

Validator uses two XML configuration files to determine which validation routines should be installed and how they should be applied for a given application, respectively. The first configuration file, validator-rules.xml, declares the validation routines that should be plugged into the framework and provides logical names for each of the validations. The validator-rules.xml file also defines client-side JavaScript code for each validation routine. Validator can be configured to send this JavaScript code to the browser so that validations are performed on the client side as well as on the server side.

The second configuration file, validation.xml, defines which validation routines should be applied to which Form Beans. The definitions in this file use the logical names of Form Beans from the struts-config.xml file along with the logical names of validation routines from the validator-rules.xml file to tie the two together.

Using the Validator framework involves enabling the Validator plug-in, configuring Validator's two configuration files, and creating Form Beans that extend the Validator's ActionForm subclasses. The following sections explain in detail how to configure and use Validator.

Enabling the Validator Plug-in

Although the Validator framework comes packaged with Struts, Validator is not enabled by default. To enable Validator, add the following plug-in definition to your application's struts-config.xml file.
<!-- Validator Configuration -->
<plug-in className="org.apache.struts
.validator.ValidatorPlugIn">
  <set-property property="pathnames"
               value="/technology/WEB-INF/
  validator-rules.xml, /WEB-INF/
  validation.xml"/>
</plug-in>


This definition tells Struts to load and initialize the Validator plug-in for your application. Upon initialization, the plug-in loads the comma-delimited list of Validator config files specified by the pathnames property. Each config file's path should be specified by use of a Web application-relative path, as shown in the previous example.

Note that your application's struts-config.xml file must conform to the Struts Configuration Document Type Definition (DTD), which specifies the order in which elements are to appear in the file. Therefore, you have to put the Validator plug-in definition into the proper place in the file. The easiest way to ensure that you are properly ordering elements in the file is to use a tool, such as Struts Console, that automatically formats your configuration file so that it conforms to the DTD.

Configuring validator-rules.xml

The Validator framework is set up as a pluggable system whose validation routines are simply Java methods that are plugged into the system to perform specific validations. The validator-rules.xml file declaratively plugs in the validation routines Validator uses for performing validations. Struts example applications come packaged with preconfigured copies of this file. Under most circumstances, you will not need to modify the preconfigured copies unless you are adding your own custom validations to the framework.

Listing 1 is a sample validator-rules.xml file that illustrates how validation routines are plugged into Validator. Each validation routine in the validator-rules.xml file has its own definition that is declared with a validator tag, which is used to assign a logical name to the routine, using the name attribute, and to specify the class and method for the routine. The routine's logical name is used by other routines in this file as well as by validation definitions in the validation.xml file to refer to the routine.

Note that the validator tag encapsulates a javascript tag, which is used to define client-side JavaScript code for performing the same validation on the client side as on the server side.

Included Validations

By default, Validator comes packaged with several basic validation routines you can use to handle most validation scenarios. These routines have logical names, such as required (for required values), CreditCard (for credit card number values), email (for e-mail address values), and so on.

Creating Form Beans

To use Validator, your application's Form Beans have to subclass one of Validator's ActionForm subclasses instead of ActionForm itself. Validator's ActionForm subclasses provide an implementation for ActionForm's validate( ) method that hooks into the Validator framework. Instead of hard-coding validations into the validate( ) method, you simply omit the method altogether, because Validator provides the validation code for you.

Parallel to the core functionality provided by Struts, Validator gives you two paths to choose from when creating Form Beans. The first path you can choose is to create a concrete Form Bean object like the following:


package com.jamesholmes.minihr;

import org.apache.struts.validator
.ValidatorForm;

public class LogonForm extends ValidatorForm {
  private String username;
  private String password;
 
  public String getUsername() {
    return username;
  }
 
  public void setUsername(String
username) {
    this.username = username;
  }

  public String getPassword() {
    return password;
  }
public void setPassword(String
password) {
    this.password = password;
  }
}


This class is similar to one you would create if you were not using Validator, but this class extends ValidatorForm instead of ActionForm. This class also does not provide an implementation for ActionForm's empty reset( ) and validate( ) methods, because ValidatorForm does.

You configure this concrete Form Bean in the struts-config.xml file the same way you would a regular Form Bean:


<form-beans>
  <form-bean name="logonForm"
            type="com.jamesholmes
  .minihr.LogonForm"/>
</form-beans>


The logical name given to the concrete Form Bean with the form tag's name attribute is the name you use when defining validations in the validation.xml file, as shown here.


<!DOCTYPE form-validation
PUBLIC "-//Apache Software Foundation//
       DTD Commons Validator Rules
       Configuration 1.0//EN"
       "
http://jakarta.apache.org/
      commons/dtds/validator_1_0.dtd">

<form-validation>
  <formset>
    <form name="logonForm">
      <field property="username"
            depends="required">
        <arg0 key="prompt.username"/>
      </field>
    </form>
  </formset>
</form-validation>


Validator uses the value of the form tag's name attribute to match validation definitions to the name of the Form Bean to which they should be applied.

The second path you can choose when creating your Form Bean is to define a dynamic Form Bean in the struts-config.xml file, as follows:


<form-beans>
  <form-bean name="logonForm"
            type="org.apache
.struts.validator.DynaValidatorForm">
    <form-property name="username"
            type="java.lang.String"/>
    <form-property name="password"
            type="java.lang.String"/>
  </form-bean>
</form-beans>


Dynamic Form Beans do not require you to create concrete Form Bean objects; instead, you define the properties your Form Bean should have and their types, and Struts dynamically creates the Form Bean for you. Validator allows you to use this concept just as you would with core Struts. The only difference with Validator is that you specify that your Form Bean is of type org.apache.struts.validator.DynaValidatorForm instead of org.apache.struts.action.DynaActionForm.

The logical name given to dynamic Form Beans is the name you use when defining validations in the validation.xml file. Validator uses the matching names to tie the validations to the Form Bean.

In addition to the two standard options for creating Form Beans, Validator provides an advanced feature for tying multiple validation definitions to one Form Bean definition. When you use validatorForm- or DynaValidatorForm-based Form Beans, Validator uses the logical name for the Form Bean from the struts-config.xml file to map the Form Bean to validation definitions in the validation.xml file. This mechanism is great in most cases, but in some scenarios, Form Beans are shared among multiple actions. One action may use all of the Form Bean's fields, and another action may use only a subset of the fields. Because validation definitions are tied to the Form Bean, the action that uses only a subset of the fields has no way of bypassing validations for the unused fields. When the Form Bean is validated, it generates error messages for the unused fields, because Validator has no way of knowing not to validate the unused fields; it simply sees them as missing or invalid.

To solve this problem, Validator provides two additional ActionForm subclasses that allow you to tie validations to actions instead of to Form Beans. That way you can specify which validations to apply to the Form Bean based on which action is using the Form Bean. For concrete Form Beans, you subclass org.apache.struts.validator.ValidatorActionForm, as follows:

 

public class AddressForm extends ValidatorActionForm {
  ...
}


For dynamic Form Beans, you specify a type of org.apache.struts.validator.DynaValidatorActionForm for your Form Bean definition in the struts-config.xml file, as follows:


<form-bean name="addressForm"
          type="org.apache.struts
.validator.DynaValidatorActionForm">
  ...
</form-bean>


Inside your validation.xml file, you map a set of validations to an action path instead of to a Form Bean name, because if you have two actions defined, Create Address and Edit Address, which use the same Form Bean, each will have a unique action path, as follows:


<action-mappings>
  <action path="/technology/createAddress"
         type="com.jamesholmes
  .minihr.CreateAddressAction"
         name="addressForm"/>
  <action path="/technology/editAddress"
         type="com.jamesholmes
  .minihr.EditAddressAction"
         name="addressForm"/>
</action-mappings>


The following validation.xml file snippet shows two sets of validations that are intended for the same Form Bean but are distinguished by different action paths:


<formset>
  <form name="/technology/createAddress">
    <field property="city"
          depends="required">
      <arg0 key="prompt.city"/>
    </field>
  </form>
  <form name="/technology/editAddress">
    <field property="state"
          depends="required">
      <arg0 key="prompt.state"/>
    </field>
  </form>
</formset>


Because your Form Bean subclasses either ValidatorActionForm or DynaValidatorActionForm, Validator knows to use an action path instead of the Form Bean's logical name to find validations for the Form Bean.

Configuring validation.xml

The validation.xml file is used to declare sets of validations that should be applied to Form Beans. Each Form Bean you want to validate has its own definition in this file. Inside that definition, you specify the validations you want to apply to the Form Bean's fields. The following is a sample validation.xml file that illustrates how validations are defined:


<!DOCTYPE form-validation
PUBLIC "-//Apache Software Foundation//
       DTD Commons Validator Rules
       Configuration 1.0//EN"
       "
http://jakarta.apache.org/
      commons/dtds/validator_1_0.dtd">

<form-validation>
  <formset>
    <form name="logonForm">
      <field property="username"
            depends="required">
        <arg0 key="prompt.username"/>
      </field>
      <field property="password"
            depends="required">
        <arg0 key="prompt.password"/>
      </field>
    </form>
  </formset>
</form-validation>


The first element in the validation.xml file is the form-validation element. This element is the master element for the file and is defined only once. Inside the form-validation element, you define form-set elements that encapsulate multiple form elements. Generally, you define only one form-set element in your file, but you would use a separate one for each locale if you were internationalizing validations.

Each form element uses the name attribute to associate a name with the set of field validations it encompasses. Validator uses this logical name to map the validations to a Form Bean defined in the struts-config.xml file. Based on the type of Form Bean being validated, Validator attempts to match the name to either a Form Bean's logical name or an action path. Inside the form element, field elements define the validations to apply to specified Form Bean fields. The field element's property attribute corresponds to the name of a field in the specified Form Bean. The depends attribute specifies the logical names of validation routines from the validator-rules.xml file that should be applied to the field.

Configuring ApplicationResources.properties

Validator uses Struts' Resource Bundle mechanism for externalizing error messages. Instead of having hard-coded error messages in the framework, Validator allows you to specify a key to a message in the ApplicationResources.properties file that should be returned if a validation fails. Each validation routine in the validator-rules.xml file specifies an error message key with the validator tag's msg attribute, as follows:


<validator name="required"
          classname="org.apache
.struts.validator.FieldChecks"
          method="validateRequired"
          methodParams="java.lang
.Object, org.apache.commons.validator
.ValidatorAction, org.apache.commons
.validator.Field, org.apache.struts
.action.ActionErrors, javax.servlet
.http.HttpServletRequest"
          msg="errors.required">


If the validation fails when it is run, the message corresponding to the key specified by the msg attribute will be returned.

The following snippet shows the default set of validation error messages from the ApplicationResources.properties file that comes prepackaged with Struts example applications. Each message key corresponds to those specified by the validation routines in the validator-rules.xml file, which also comes prepackaged with Struts example applications.


# Error messages for Validator framework validations
errors.required={0} is required.
errors.minlength={0} cannot be less than {1} characters.
errors.maxlength={0} cannot be greater than {2} characters.
errors.invalid={0} is invalid.
errors.byte={0} must be a byte.
errors.short={0} must be a short.
errors.integer={0} must be an integer.
errors.long={0} must be a long.0.   errors.float={0} must be a float.
errors.double={0} must be a double.
errors.date={0} is not a date.
errors.range={0} is not in the range {1} through {2}.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.


Note that each message has placeholders, in the form {0}, {1}, or {2}. At runtime the placeholders are replaced by another value such as the name of the field being validated. This feature is especially useful in allowing you to create generic validation error messages that can be reused for several different fields.

Take, for example, the required validation's error message, errors.required, shown here:


errors.required={0} is required.


When you use the required validation in the validation.xml file, you have to define the value that should be used to replace {0} in the error message, as shown here.


<form name="auctionForm">
  <field property="bid" depends="required">
    <arg0 key="prompt.bid"/>
  </field>
</form>


Error messages can have up to four placeholders: {0} through {3}. These placeholders are known as arg0 through arg3, respectively, and you can specify them by using the arg0 - arg3 tags. In the example above, the arg0 tag specifies the value that should be used to replace the {0} placeholder. This tag's key attribute specifies a message key from the ApplicationResources.properties file, such as the following, whose value is used as the replacement for the placeholder: Next Steps

READ
more about Validator
jakarta.apache.org/commons/validator

more about Struts Console
www.jamesholmes.com/struts
 


prompt.bid=Auction Bid


Using a message key for the placeholder value frees you from having to hard-code the replacement value over and over in the validation.xml file. However, if you don't want to use the Resource Bundle key/value mechanism for specifying placeholder values, you can explicitly specify the placeholder value by using the following syntax for the arg0 tag.


<arg0 key="Auction Bid" resource="false"/>


In this example, the resource attribute is set to false to instruct Validator that the value specified with the key attribute should be taken as the literal placeholder value and not as a key for a message in the ApplicationResources.properties file.

Enabling Client-Side Validations

Besides providing a framework for simplifying server-side form data validations, Validator provides an easy-to-use mechanism for performing client-side validations. Each validation routine defined in the validator-rules.xml file optionally specifies JavaScript code that can be run in the browser (on the client side) to perform the same validations that take place on the server side. When run on the client side, the validations do not allow the form to be submitted until they have all passed.

To enable client-side validation, you have to place the Struts HTML Tag Library's javascript tag in each JSP that needs validation, as follows:


<html:javascript formName="logonForm"/>


The javascript tag requires you to use the formName attribute to specify the name of a form definition from the validation.xml file for which you want validations performed, as follows:


<form name="logonForm">
  <field property="username"
        depends="required">
    <arg0 key="prompt.username"/>
  </field>
  <field property="password"
        depends="required">
    <arg0 key="prompt.password"/>
  </field>
</form>


All the validations you have specified for the form definition to run on the server side are also run on the client side. Because client-side validation is performed with JavaScript, there are ways of circumventing it. To ensure that validations are always run, Validator performs the validations on the server side, whether or not you have chosen to enable client-side validation.

Conclusion

The Validator framework adds significant value to the core Struts framework, by providing a configurable system for applying form data validations. You can save time and simplify your Struts application development by using the Validator framework with your application

posted on 2006-04-29 16:45 freefly 阅读(627) 评论(0)  编辑  收藏 所属分类: struts

只有注册用户登录后才能发表评论。


网站导航: