Dear Wiki user,

You have subscribed to a wiki page or wiki category on "Struts Wiki" for change 
notification.

The following page has been changed by MichaelJouravlev:
http://wiki.apache.org/struts/StrutsCatalogActionForms

The comment on the change is:
This is junk; bless wiki for being able to remove my articles.

------------------------------------------------------------------------------
- What are the possible choices for storing and accessing input and output data 
from an action class?
+ deleted
  
- === Not using action forms ===
- 
- This is the radical choice. Proponents of this choice do not see added value 
of action forms. They can obtain input data directly from the request object, 
and they can display information directly from the business object or another 
bean. They prefer to validate input data by explicitly calling the validator, 
or they have their own validation techniques.
- 
- Another reason for not using action forms is using presentation engine 
different from JSP. Quoting Don Brown: "My primary app uses stxx 
(http://stxx.sf.net) so without taglibs, there isn't much left to !ActionForms. 
 My forms are XML based, so I use commons-validator with custom XML validators, 
and JXPath to populate (treats the form element names as xpath expressions). My 
wizards that use Struts Flow use the same population and validation methods."
- 
- attachment:noform.gif
- 
- This approach is used by 22% of developers, who participated in the quick 
poll.
- 
- === Using action form for input only ===
- 
- Struts populates form bean with input data from the request. After input is 
processed and domain model is updated, output data is generated manually and 
pushed into request or session scope, either field by field or packaged into a 
bean. This approach makes sense if a page is rendered with non-JSP engine, too.
- 
- attachment:forminput.gif
- 
- Used by 11% of respondents.
- 
- === Using action form for output only ===
- 
- This is quite an exotic choice. To make this work, action form should not 
have any setters, since Struts uses setters to populate action form bean. 
- 
- attachment:formoutput.gif
- 
- No one who responded to the poll, uses this approach.
- 
- === Using same action form for both input and output data ===
- 
- This choice turned out to be quite popular, 50% usage out of all respondents. 
Here is an outline:
- 
-    * HTML FORM is submitted from the input page, usually using POST request 
method.
-    * Struts populates form bean with request data.
-    * Form bean validates input and if something wrong, it generates error 
messages.
-    * If validate() returns errors, Struts does not bother to call action 
class. Instead, it forwards to location, which is defined in "input" property 
of <action> element.
-    * If, on the other hand, input data is correct, Struts calls execute() 
method of the action class.
-    * execute() usually performs model update, then fills out form bean with 
output values, and forwards to JSP page, which displays output data.
- 
- attachment:forminputoutput.gif
- 
- === Using input form and output form ===
- 
- Action mapping does not allow to assign more than one action form to an 
action class declaratively. If you want to use action form for both input and 
output, but do not want to keep the data in the single form, then you can use 
two action classes, each with its own action form.
- 
- attachment:twoforms.gif
- 
- In this scheme each action class and form bean performs its own specific task.
- 
-    * Input form bean is populated with input data.
-    * Input Form bean validates input and if something wrong, it generates 
error messages.
-    * If validate() returns errors, Struts forwards to location, which is 
defined in "input" property of <action> element.
-    * If input data is correct, Struts calls execute() method of the input 
action class.
-    * Input action class forwards to output action mapping. This is basically 
a simple action chaining.
- 
- Struts will try to populate output form bean, but here is the trick: you do 
not need to define setters for properties in the output form. Also, the field 
on the output form usually differ from fields on the input form.
- 
- Now we have clean separation of input and output data, and each class is 
doing a small but specific task. About 17% of respondents use separate input 
and output form beans.
- 
- === Separating input phase from output phase ===
- 
- Separating data may be important for a web developer, but it is invisible for 
a browser. The only thing that browser knows, is that to obtain a certain page 
it has to issue a certain request. Putting it differently: each page has a 
unique location. What does it really mean?
- 
- When a browser submits data, it sends a request to the server. By default, 
when browser submits an HTML form, the request has POST type. Server 
application processes input data, updates domain objects, and responds with 
result page. From browser's point of view, the result page has an address, 
which is a combination of URL and browser input data. To reload the result page 
the browser needs to send to the server exactly the same address. Thus, when a 
user clicks Reload button, browser resends to the server information that has 
been already submitted.
- 
- HTTP specification distinguishes between POST and GET request types. GET 
should be used for requests, which do not produce side effects when repeated. 
POST should be used primarily for changing server state. Because of that, when 
the same POST is resent to the server, browser is obliged to ask a user for 
confirmation. Obviously, if application does not check for duplicate input 
data, the same server activity can be performed twice, say, a user credit card 
can be charged once again.
- 
- This situation is known as "postdata situation" or "double submit problem". 
Struts provides a special object, token, to detect that a particular request is 
resubmitted. While this helps to fight with the double submit, what if we can 
avoid double submits altogether?
- 
- To accomplish that, we need to ensure that when a user clicks Reload, browser 
does not send another POST request to the browser. That means that result page 
must have a different address. That, in turn, means that result page cannot be 
generated in response to POST request. Instead, it should be generated in 
response to GET request. This means, that we need to make two requests out of 
one, and the second response must have GET type.
- 
- Combining this information together, we can come up with a logical solution:
-    * Browser submits input data using POST request.
-    * Server application processes input data and updates domain model.
-    * Server redirects to the address of result page. Redirection codes 302 
and 303 produce GET request. 302 code is automatically generated with Java 
!HttpServletResponse.sendRedirect method.
-    * Browser uses new address to load the result page.
- 
- Now, when a user clicks Reload button, browser uses address from GET request 
to reload a page. Thus, no input data is resubmitted to the server. Also, 
because this request has GET type, browser does not show warning dialog window.
- 
- === Remove "input" property and use redirect ===
- 
- Usually, when form bean is used for input, errors are forwarded to location, 
defined in "input" property. By default, "input" property does not allow 
redirection. Redirection can be enabled, but for the whole application. Because 
most applications forward to input page instead of redirecting, page is sent 
back to browser immediately in response to POST request. This results in 
POSTDATA situation when a user tries to reload input page afterwards.
- 
- So, as a first step of splitting one request into two I suggest either to get 
rid of "input" property and automatic validation, or to set controller 
property, that allows redirection for "input" location.
- 
- Then we need to use redirection instead of forwarding between the action 
mappings, and this is it! 
- 
- attachment:twoformsredirect.gif
- 
- Well, we are almost there, but not quite. Because now we need to find a 
place, where to store intermediate data and error messages between requests. 
This data can either be passed in the redirected request, or saved in the 
session. The choice is yours. I prefer to store most of the data in the 
session, and to pass only object ID as the request parameter. I will discuss 
the details of redirecting from POST to GET on a separate page.
- 
- === Dialog Action ===
- 
- What if we need to use one form? Say, we have a wizard or a dialog, which 
shares data between pages. No problem, just use one form bean with session 
scope instead of two, and it will retain all input data between requests. You 
can use one action class as well. To avoid endless loop, you need to check the 
request method. It it is POST, then you redirect to the same action mapping 
again. If it is GET, you display the result page.
- 
- attachment:twoformsdialog.gif
- 
- Separation between input and output phases using redirection provides freedom 
of browsing. Now we can reload result page without risking to resubmit input 
data. And we can go back and forward again without invoking POST requests.
- 
- == Comments ==
- 
-    * [http://www.mail-archive.com/user%40struts.apache.org/msg26454.html 
Thread on Struts user list] 
-    * This page was heavily updated since after the comments on Struts user 
list
- 
- == How do you use action forms (aka form beans)? ==
- 
- Please, cast your vote here: 
http://jmikus.freepolls.com/cgi-bin/polls/001/poll_center.htm
- 
- Please note, that employing "input" property and redisplaying input page with 
error message does not count as using form bean for output.
- 

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to