Recipe8.11.Validating a Wizard Form


Recipe 8.11. Validating a Wizard Form

Problem

You need to perform validations on a form shared across pages as part of a wizard-style interface.

Solution

Use the Validator's built-in support for wizards via the page attribute. Example 8-16 configures the Validator use of this attribute. Validations will be performed on fields where the page attribute value is less than or equal to the page property of the ActionForm.

Example 8-16. Use of the Validator page attribute
<form name="WizardForm">     <field property="username" page="1"             depends="required">         <arg key="prompt.username"/>     </field>     <field property="password" page="2"             depends="required">         <arg key="prompt.password"/>     </field>     <field property="ssn" page="3"             depends="required,mask">         <arg key="prompt.ssn"/>         <var>             <var-name>mask</var-name>             <var-value>^\d{3}-\d{2}-\d{4}$</var-value>         </var>     </field> </form>

If the form used for the wizard uses the DynaValidatorForm (or one of its subclasses), add a form-property with the name of page. The property must be of type java.lang.Integer:

<form-bean name="WizardForm"            type="org.apache.struts.validator.DynaValidatorForm">     <form-property name="username" type="java.lang.String"/>     <form-property name="password" type="java.lang.String"/>     <form-property name="ssn" type="java.lang.String"/>     <form-property name="page" type="java.lang.Integer"/> </form-bean>

For conventional ActionForms that subclass ValidatorForm (or one of its subclasses), no changes are necessary. The ValidatorForm already provides a page property. Because the page instance variable is protected, it can be accessed by subclasses. (See Example 8-17.)

Example 8-17. Action Form for wizard interface
package com.oreilly.strutsckbk.ch08; import javax.servlet.http.HttpServletRequest; import org.apache.struts.action.ActionErrors; import org.apache.struts.action.ActionMapping; import org.apache.struts.action.ActionMessage; import org.apache.struts.validator.ValidatorForm; public class WizardForm extends ValidatorForm {     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;     }     public String getSsn( ) {         return ssn;     }     public void setSsn(String ssn) {         this.ssn = ssn;     }     private String username;     private String password;     private String ssn; }

Discussion

The Validator supports validation of session-scoped ActionForms used in wizard-style interfaces. You can specify a page attribute for each field element in your validation.xml file. When you submit the form from a step in the wizard, you set the page property to a number representing the current step. This property can be set in the Action preceding the page, or it can be hardcoded on the JSP itself; either way, it's usually rendered as a hidden field.

When the Validator validates the form, it checks those fields whose page attribute value is less than or equal to the current page. The Solution, for example, is based on a wizard interface with three pages; the first page handles the username, the second page handles the password, and the last page handles the SSN.

The Validator validates prior pages and the current page primarily for thoroughness. Because of programming errors, a step in the flow could be accidentally skipped. On a more ominous note, a hacker could circumvent the wizard's flow by submitting directly to an out-of-sequence URL. By validating prior pages in addition to the current page, no assumptions are made about how the current page was accessed; all prior fields are validated.

If you override the ValidatorForm.validate( ) method in your own subclass, you can account for the page property as the Validator does. This code snippet shows how you could override the validate( ) of the ActionForm in Example 8-17:

public ActionErrors validate(ActionMapping mapping,                               HttpServletRequest request) {     ActionErrors errors = super.validate(mapping, request);             if (page >= 2) {         if (username.equals(password)) {             errors.add( "password",                  new ActionMessage("password",                    "errors.password.sameAsUsername"));         }     }     return errors; }

This method calls super.validate() to perform the Validator validations. It then performs a business logic validation, verifying that the username and password are different. If the validation fails, an ActionMessage (or ActionError in Struts 1.1) is added to the set of errors. Just like the Validator, this validation accounts for the current page. In this case, the validation is only performed for page 2 and beyond.

See Also

Recipe 8.10 shows Solutions for adding custom validations by extending Validator forms. Recipe 7.6 considers additional details about setting up a wizard-style interface.



    Jakarta Struts Cookbook
    Jakarta Struts Cookbook
    ISBN: 059600771X
    EAN: 2147483647
    Year: 2005
    Pages: 200

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