Validating multi-page forms


When large amount of data is collected from the user , it is customary to split the form into multiple pages. The pages follow a wizard like fashion. However the ActionForm would still exists as a single Java class. Moreover at any point, the data validation should be limited to only those pages that have been submitted. Fortunately, this feature is already built into the Validator. However it requires some setup from your side. There are two alternatives ‚ the first uses a single action mapping and the second uses multiple action mappings. The struts-validator.war provided with the Struts distribution adopts the first approach, while we recommend the latter.

Both approaches require the use of an optional hidden variable called page . Consider an html form split into two JSPs ‚ PageA.jsp and PageB.jsp . Since both JSPs will have the hidden variable mentioned earlier, it is sent as a request parameter from both form submissions. The hidden variable is assigned the value of 1 in PageA and 2 in PageB. The ValidatorForm already has a JavaBeans property named page of type int . All validation for any field on a page less than or equal to the current page is performed on the server side. This will of course require that each rule defined for the field in the validation.xml should have a page attribute as follows :

 <form name="CustomerForm">       <field property="firstName"  page="1"  depends="required">         <arg0 key="customerform.firstname"/>       </field>           <field property="fieldX"  page="2"  depends="required">         <arg0 key="customerform.fieldX"/>       </field>     </form> 

With this background, we will first explain the single action mapping approach. The html forms in both pages have the same action - < html:form action= ‚½/submitForm ‚½ >.

In the struts config file, set validate=false for the /submitForm action mapping and add forwards for each of the pages as follows:

 <action  path="/submitForm"          type="mybank.example.CustomerAction"          name="CustomerForm"          scope="request"  validate="false"  >   <forward name="success"  path="/Success.jsp"/>   <forward name="cancel"  path="/Cancelled.jsp"/>   <  forward name="input1"   path="/PageA.jsp"/  >   <  forward name="input2"   path="/PageB.jsp"/  > </action> 

Since validate is set to false, the execute() method in Action gets control immediately after the RequestProcessor populates the form. You have to now explicitly call the form.validate() in the execute() method (Since the CustomerForm extends from ValidatorForm , the validate() is already implemented). After that you have to forward to the appropriate page depending on the current page and whether there are ActionErrors in the current page. For instance, if PageA is submitted and there are no ActionErrors, then PageB is displayed to the user. However if there were ActionErrors in PageA, then it is displayed back to the user. The code is shown below.

 public ActionForward execute(.. ..) throws Exception {   CustomerForm info = (CustomerForm)form;   // Was this transaction cancelled?   if (isCancelled(request)) {     // Add code here to remove Form Bean from appropriate scope     return (mapping.findForward("cancel"));   }   ActionErrors errors = info.validate(mapping, request);   if (errors != null && errors.isEmpty()) {     if (info.getPage() == 1)               return mapping.findForward("input2");     if (info.getPage() == 2){       //Data collection completed. Invoke Business Logic here       return mapping.findForward("success");     }   } else {     saveErrors(request, errors);     return mapping.findForward("input" + info.getPage());   } } 

This approach is counter-intuitive. After all, validate() method was supposed to be invoked automatically by the framework, not manually in the execute() method. The second approach eliminates the need to manually invoke the validate() . In this method, the two forms in two pages have different actions as follows:

Page A Form submission - < html:form action= ‚½/submitPageA ‚½ >

Page B Form submission - < html:form action= ‚½/submitPageB ‚½ >

Two action mappings are added to the Struts Config file for the above form submissions. Note that both of the action mappings use the same Action class. Moreover there is no need to set validate=false . The action mapping for PageA form submission is as follows:

 <action  path="/submitPageA"  type="mybank.example.CustomerAction"          name="CustomerForm"          scope="request"  validate="true"   input="/PageA.jsp"  >   <  forward name="success"  path="/PageB.jsp"/  >   <forward name="cancel"  path="/Cancelled.jsp"/> </action> 

Similarly, the action mapping for PageB form submission is as follows:

 <action  path="/submitPageB"  type="mybank.example.CustomerAction"          name="CustomerForm"          scope="request"  validate="true"   input="/PageB.jsp"  >   <  forward name="success"  path="/Success.jsp"/  >   <forward name="cancel"  path="/Cancelled.jsp"/> </action> 

Both action mappings define an input value. When the form is validated by the RequestProcessor and there are errors, the mapping.getInput() page is shown to the user. Similarly the mapping.findForward( ‚“success ‚½) page is shown when there are no ActionErrors. Any business logic invocation happens only after the PageB data is collected. The code below shows the execute() method.

 public ActionForward execute(.. ..) throws Exception {   CustomerForm info = (CustomerForm)form;   // Was this transaction cancelled?   if (isCancelled(request)) {     // Add code here to remove Form Bean from appropriate scope     return (mapping.findForward("cancel"));   }   if (info.getPage() == 2) {     //Data collection completed. Invoke Business Logic here   }   return mapping.findForward("success"); } 

With the second approach, the execute() method in Action is simplified. While you may not see much difference between the two execute() methods shown earlier, it will be much pronounced as the number of pages increase and the last thing you want is page navigation logic intermingled with business logic invocation.




Struts Survival Guide. Basics to Best Practices
Struts Survival Guide: Basics to Best Practices (J2ee Survival Series)
ISBN: 0974848808
EAN: 2147483647
Year: 2004
Pages: 96

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