| Author |
Multi-page form without hidden fields
|
David Pizon
Greenhorn
Joined: Oct 03, 2004
Posts: 10
|
|
Howdy, Ranchers! I'm working on the mulit-page user registration portion of a small web application. What I have so far (hope to improve): I do not override the Form class reset() method. As the controller moves from page to page, all of the old form information still exists within the form object. At the final page, I remove the form object from the session. Also, I do not override the Form class validate() method. The controller flows to the Action class. Within the execute() method of the Action class I call a custom validation method in the form object, check to see if errors were returned (actionMessages.isEmpty()), and return the appropriate ActionForward. Right now each page contains a page value as a hidden field to determine which fields to validate for the given stage. <html:hidden property="page" value="1"/> <html:hidden property="page" value="2"/> <html:hidden property="page" value="3"/> ... and so on ... The controller takes this hidden field and performs the setPage() method (inherited from the ValidatorForm class). I would like to avoid passing hidden fields because I worry about users faking requests to the web application (savvy users forming a request with a different page value) and tricking the web application into skipping right to the confirmation stage. I've tried coding the JSP pages to pull the form object from the session, perform the setPage() method, and re-stuffing the object into the session. For some reason the Form's "page" integer remains 0 when I do this. Does anyone else have any suggestions? [ July 28, 2005: Message edited by: David Pizon ] [ July 28, 2005: Message edited by: David Pizon ] [ July 28, 2005: Message edited by: David Pizon ]
|
 |
Merrill Higginson
Ranch Hand
Joined: Feb 15, 2005
Posts: 4864
|
|
|
Since it's the action classes that control navigation from page to page, to my way of thinking, it should be the action classes that set the page value, not the jsp. So, for example, when an action class is about to forward to page 2, it should also execute setPage("2") on the ActionForm. This will work as long as the ActionForm is scoped to session as you say it is.
|
Merrill
Consultant, Sima Solutions
|
 |
David Pizon
Greenhorn
Joined: Oct 03, 2004
Posts: 10
|
|
That would seem perfectly logical and I would love to do it that way. However, for some unknown reason page-to-page flow does not work properly. Clicking on the "next" button on the first page will validate and send the user to the second page. Clicking on the "next" button on the second page validates the first page (known to be valid) and re-sends the user to the second page. The Form "page" int is apparently not getting changed. Am I not setting it correctly?
|
 |
David Pizon
Greenhorn
Joined: Oct 03, 2004
Posts: 10
|
|
/* * Created on Jul 11, 2005 * * TODO Figure out why setPage() does not change the page number past this instance of the execute() method * registrationForm.getPage() always returns 0 */ package com.campushousingguide.action; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.Action; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionMessages; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import com.campushousingguide.form.RegistrationForm; /** * @author David Pizon */ public class RegistrationAction extends Action { // Local Forwards public static final String FORWARD_page1 = "page1"; public static final String FORWARD_page2 = "page2"; public static final String FORWARD_page3 = "finish"; public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception { String forward = FORWARD_page1; int page = 0; // Retrieve the registration form RegistrationForm registrationForm = (RegistrationForm)form; page = registrationForm.getPage(); System.out.println("Why is this value always 0?"); System.out.println(new Integer(registrationForm.getPage()).toString()); // Check to see if the user clicked on the "back" button if (request.getParameter("back") != null) { switch(page) { case 0: break; case 1: page = 0; forward = FORWARD_page1; break; case 2: page = 1; forward = FORWARD_page2; break; default: break; } registrationForm.setPage(page); return mapping.findForward(forward); } // Perform our custom validation method on our form ActionMessages actionMessages = registrationForm.validateRegisterForm(mapping, request); this.saveErrors(request, actionMessages); // If there were no errors -- move to the next page if (actionMessages.isEmpty()) page++; registrationForm.setPage(page); System.out.println(new Integer(registrationForm.getPage()).toString()); System.out.println("The page value has been set but will default to back to zero when we next run this method"); // Send the user to whichever page they should go to switch(page) { // Move to the next page case 0: forward = FORWARD_page1; break; case 1: forward = FORWARD_page2; break; case 2: // The form is completed // Perform whatever database stuff we need to here forward = FORWARD_page3; break; default: break; } return mapping.findForward(forward); } } [ July 29, 2005: Message edited by: David Pizon ]
|
 |
Merrill Higginson
Ranch Hand
Joined: Feb 15, 2005
Posts: 4864
|
|
I may be missing something here, but when you're currently on page 1, don't you want to move to page 2? The code you gave us doesn't do that. It redisplays page one. Here's how I think the switch statement should read: // Send the user to whichever page they should go to switch(page) { // Move to the next page case 0: registrationForm.setPage(1); forward = FORWARD_page2; break; case 1: registrationForm.setPage(2); forward = FORWARD_page3; break; case 2: // The form is completed // Perform whatever database stuff we need to here registrationForm.setPage(3); forward = ???confirmation page???; break; default: break; }
|
 |
David Pizon
Greenhorn
Joined: Oct 03, 2004
Posts: 10
|
|
Moving to the next page *should* be handled by the following code: <snip> // Perform our custom validation method on our form ActionMessages actionMessages = registrationForm.validateRegisterForm(mapping, request); this.saveErrors(request, actionMessages); // If there were no errors -- move to the next page if (actionMessages.isEmpty()) page++; registrationForm.setPage(page); </snip> Validation is done from within the Action class (by calling the custom validateRegisterForm() method in the Form object). If the returned actionMessages object is empty, the page number gets increased and set before feeding into the switch statement which sends the user on thier way. The problem appears to be that the registrationForm.setPage() calls do not actually store the page value to the Form object in the session. Upon entering the Action class execute() method, registrationForm.getPage() always returns 0.
|
 |
Merrill Higginson
Ranch Hand
Joined: Feb 15, 2005
Posts: 4864
|
|
Check the reset() method of your form bean. Does it set page to zero? If so, take out the code. This would have worked when the page was being reset by the JSP, but it would cause problems once you removed the page property from the JSP, [ July 29, 2005: Message edited by: Merrill Higginson ]
|
 |
David Pizon
Greenhorn
Joined: Oct 03, 2004
Posts: 10
|
|
Hooookay... First of all I would like to give a great deal of thanks to Merrill Higginson for your support. Since I did not override the Form class reset() method I do not know how the page integer was getting reset. I added the following code to my Form class to make sure the parent reset() method wasn't doing anything sneaky: <snip> public void reset() { } </snip> No joy. Lastly I created a private integer "stage" with appropriate gets and sets. If I use getStage() instead of getPage() everything works the way it should. It's a pity that I'm not understanding the proper use of the "page" integer since upon first glance it seems to be exactly what I am after. If anyone has any pointers on how exactly the "page" integer should properly be used, I'd be happy to hear from you. Until then... don't squat with your spurs on.
|
 |
 |
|
|
subject: Multi-page form without hidden fields
|
|
|