Using a Workflow Form

 < Day Day Up > 



At times you will want to develop a wizard-style workflow. You can do this with the Validator Framework by using the page attribute of the field element. To make the page attribute work, the ValidatorForm includes a page property. You must include the current page in your HTML form (your JSP input page) with a hidden field that corresponds to the page property. The field described with the fields element will only be evaluated if the field element's "page" attribute is less than or equal to the page property of the ActionForm.

Let's consider the steps to convert our sample registration form into a two step process.

  1. Change the Action to subclass DispatchAction

  2. Create two ActionMappings entries into the struts-config file, one for each step

  3. In the Action, create two methods with the same signature as the execute method

  4. Add the method field to the ActionForm

  5. Create two input JSP pages, one page for each step

  6. Ensure each input JSP page passes the page property

  7. Ensure the first JSP page also passes which method to invoke on the second

  8. Modify the validation.xml file, add the page attribute for the fields in the form

The first step is to change the Action to subclass DispatchAction. The old action was built to handle just one form submission. This version of the action is a two-step process. Thus we want to create a method for each step. To accomplish this, we will use the DispatchAction as follows:

 import org.apache.struts.actions.DispatchAction; public class InputWorkflowAction extends DispatchAction {       ... 

Step 2: Create two ActionMappings entries into the struts-config file, one for each step. You need to define different forwards and inputs for each action. If there is a problem with form validation, you don't want the user to be forwarded to the first form in the wizard; instead, you want the user to be forwarded to the correct, current form. In order to accomplish this, you need to add two action mapping entries as follows:

         <action             path="/inputSubmitStep1"             type="ch12.InputWorkflowAction"             name="inputFormTwoStep"             scope="session"             validate="true"             parameter="method"             input="/step1.jsp">          <forward name="success" path="/step2.jsp"   />        </action>         <action             path="/inputSubmitStep2"             type="ch12.InputWorkflowAction"             name="inputFormTwoStep"             scope="session"             validate="true"             parameter="method"             input="/step2.jsp">          <forward name="success" path="/success.jsp"   />        </action> 

Notice that we specify the action element's parameter attribute. Since our action is now subclassing the DispatchAction, the parameter attribute refers to the request parameter name that will hold the method to invoke on our action. Thus, if the request parameter named method is set to step1 then the stepl method will be invoked on our action. Notice that both mappings map to the action class, namely, ch12.InputWorkflowAction.

start sidebar

Notice that we put the entire form into session by setting the scope attribute of the action mapping to session. This is desirable because we are dealing with a multi-step process. You could use request scope, but then you would have to pass all of the form fields that were not currently being entered as hidden fields in the input.jsp. You would not want to pass the password as a hidden field.

end sidebar

Step 3: In the Action, create two methods with the same signature as the execute method. You need to add a method per step as follows:

    public ActionForward step1(        ActionMapping mapping,        ActionForm form,        HttpServletRequest request,        HttpServletResponse response)        throws Exception {        InputWorkflowForm inputForm =                    (InputWorkflowForm) form;        inputForm.setPage(1);        System.out.println("Step1 "                      + inputForm.getUserName());        inputForm.setMethod("step2");        return mapping.findForward("success");    }    public ActionForward step2(        ActionMapping mapping,        ActionForm form,        HttpServletRequest request,        HttpServletResponse response)        throws Exception {        InputWorkflowForm inputForm =                       (InputWorkflowForm) form;        System.out.println("Step2: "                      + inputForm.getUserName());              //remove the form from Session scope           request.getSession()               .removeAttribute(mapping.getAttribute());        inputForm.setPage(2);        inputForm.reset(mapping, request);        return mapping.findForward("success");    } 

Notice that the step1 method sets the page property of the input form to 1. Then it sets the method property to step2. Setting the page property will limit which fields get validated by the Validator framework. Setting the method property to step2 will cause the step2 method to be invoked the next time the form is submitted.

Step 4: Add the method field to the ActionForm. The page property is part of the Validator framework. The method property is something we added to use with the DispatchAction class. Thus, we need to add this property to our ActionForm as follows:

 public class InputWorkflowForm extends ValidatorForm {     ...     private String method="step1";     /**      * @return      */     public String getMethod() {         return method;     }     /**      * @param string      */     public void setMethod(String string) {         method = string;     }     public void reset(ActionMapping mapping,                        HttpServletRequest request) {         super.reset(mapping, request);         System.out.println("RESET");         if(this.getPage()==2){             this.setMethod("step1");             this.setBirthDate ("");             this.setEmail("");             this.setFirstName("");             this.setLastName("");             this.setMiddleName("");             this.setUserName("");             this.setPassword("");             this.setPasswordCheck("");             this.setPhone("");             this.setWebsite("");         }     }      ... 

Notice that we do not want the fields reset until we are done with them. The reset method is called before every submission.

Step 5: Create two input JSP pages, one page for each step. Now that we have the action setup its time to create the two forms. A close examination of the action mappings reveal that we need to input forms: step1.jsp, and step2.jsp. Listing 12.6 shows step1.jsp; Listing 12.7 shows step2.jsp.

Listing 12.6: Step1.jsp.

start example
 <%@ taglib uri="struts-html"  prefix="html" %> <%@ taglib uri="struts-bean"  prefix="bean" %> <%@ taglib uri="struts-logic" prefix="logic" %> <html> <head> <title>Input Step 1</title> </head> <body> <h1>Step 1</h1> <logic:messagesPresent> There were errors <ul> <font color='red' > <html:messages >   <li><%= error %></li> </html:messages> </font> </ul> </logic:messagesPresent> <html:form action="inputSubmitStep1">  <bean:message key="inputForm.userName"/>  <html:text property='userName'/> <br />  <bean:message key="inputForm.password"/>  <html:password property='password'/> <br />  <bean:message key="inputForm.passwordCheck"/>  <html:password property='passwordCheck'/> <br />  <bean:message key="inputForm.firstName"/>  <html:text property='firstName'/> <br />  <bean:message key="inputForm.middleName"/>  <html:text property='middleName'/> <br />  <bean:message key="inputForm.lastName"/>  <html:text property='lastName'/> <br />  <html:hidden property='method'/>  <html:hidden property='page'/>  <html:submit value="ok"/> </html:form> </body> </html> 
end example

Listing 12.7: Step2.jsp.

start example
 <%@ taglib uri="struts-html"  prefix="html" %> <%@ taglib uri="struts-bean"  prefix="bean" %> <%@ taglib uri="struts-logic" prefix="logic" %> <html> <head> <title>Step 2</title> </head> <body> <h1>Step 2</h1> <logic:messagesPresent> There were errors <ul> <font color='red' > <html:messages >   <li><%= error %></li> </html:messages> </font> </ul> </logic:messagesPresent> <html:form action="inputSubmitStep2">  <bean:message key="inputForm.website"/>  <html:text property='website'/> <br />  <bean:message key="inputForm.birthDate"/>  <html:text property='birthDate'/> <br />  <bean:message key="inputForm.email"/>  <html:text property='email'/> <br />  <bean:message key="inputForm.phone"/>  <html:text property='phone'/> <br />  <html:hidden property='method'/>  <html:hidden property='page'/>  <html:submit value="ok"/> </html:form> </body> </html> 
end example

The first form (step1.jsp) now only has the userName, passwords, firstName, lastName, and middleName properties on it. The second form (step2.jsp) has website, birthdate, phone, and email properties on it. We only want the userName, passwords, firstName, lastName, and middleName validated when the first form submits; and we want both the sets of properties validated when the second form submits. Remember that we will only validate the properties we are interested in validating on each step (e.g., we never validate a middle name).

Step 6: Ensure each input JSP page passes the page property. The page property is what gets used by the Validator framework to determine if the other properties should be validated or not. Initially, the page property is set to 0 by the ValidatorForm. After the first form from stepl.jsp is submitted, the page property is set to 1 by the step1 method of the action. Then the step 1 method forwards to the step2.jsp (its success forward). The step2.jsp uses the html:hidden parameter to submit the new page number when the user submits the form.

Step 7: Ensure the first JSP page also passes which method to invoke on the second. In addition to the stepl method setting the page, it also sets the method property to step2. Then the step2.jsp uses the html:hidden parameter to submit the method as step2, causing the step2 method to be invoked when the form is submitted.

Step 8: Modify the validation.xml file, and add the page attribute for the fields in the form. Now that we have the page properties being submitted via the form, let's set up the validation.xml file to use them. You need to add page attributes to each of the fields that correlate to the inputFormTwoStep. For fields that you want to be validated on step1.jsp submission, add page='0'. For fields that you want to be validated on step2.jsp submission, add page='1'. The entry for this new workflow user registration (validation.xml) is shown in Listing 12.8.

Listing 12.8: Example validation.xml using workflow.

start example
    <form name="inputFormTwoStep">        <field property="userName"            depends="required,minlength,maxlength"            page='0'>            <arg0 key="inputForm.userName"/>            <arg1 key="${var:minlength}"                 name="minlength" resource="false"/>            <arg1 key="${var:maxlength}"                 name="maxlength" resource="false"/>            <var>                 <var-name>minlength</var-name>                 <var-value>5</var-value>            </var>            <var>                 <var-name>maxlength</var-name>                 <var-value>11</var-value>            </var>        </field>       <field property="firstName"            depends="required"            page='0'>            <arg0 key="inputForm.firstName" />       </field>       <field property="lastName"            depends="required"            page='0'>            arg0 key="inputForm.lastName" />        </field>       <field property="website"            depends="required"            page='1'>            <arg0 key="inputForm.website" />       </field>       <field property="birthDate"            depends="required,date"            page='1'>            <arg0 key="inputForm.birthDate" />            <var>                <var-name>datePattern</var-name>                <var-value>MM-dd-yyyy</var-value>            </var>        </field>        <field property="email"            depends="required,email"            page='1'>            <arg0 key="inputForm.email" />        </field>        <field property="phone"            depends="required,phoneext"            page='1'>            <arg0 key="inputForm.phone" />            <var>                <var-name>allowLocal</var-name>                <var-value>true</var-value>            </var>        </field>    </form> 
end example

Notice how the page attribute for the fields userName, firstName, and lastName are set to 0, and the page attribute for fields email, phone, webstie, and birthdate are set to 1. This means that userName, firstName and lastName will be validated when step1.jsp is submitted. When step2.jsp is submitted the validator framework will validate email, phone, website, and birthdate as well as userName, firstName, and lastName.



 < Day Day Up > 



Professional Jakarta Struts
Professional Jakarta Struts (Programmer to Programmer)
ISBN: 0764544373
EAN: 2147483647
Year: 2003
Pages: 183

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