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/StrutsManualActionClasses ------------------------------------------------------------------------------ One of the reasons of splitting this functionality into two actions is that Action class uses just one {{{execute()}}} method to handle all kinds of requests. (Servlet has separate {{{doGet()}}} and {{{doPost()}}} methods.) + inline:setup_submit_improved.gif + + inline:icon_alert.gif The above diagram shows the improved Setup/Submit Pattern. To see the original Setup/Submit Pattern click here (TODO). + A typical Setup Action will often implement the following logic in its {{{execute}}} method: * Make sure that a user is allowed to see the content of a web page that corresponds to the action. @@ -79, +83 @@ A typical Submit Action will often implement the following logic in its {{{execute}}} method: - * Validate the form bean properties as needed. If a problem is found, store the appropriate error message keys as a request (or session) attribute, and forward (or redirect) control to the input form so that the errors can be corrected. + * Validate the form bean properties as needed. If a problem is found, store the appropriate error message keys as a request (or session) attribute, and forward (or redirect) control to the setup action so that the errors can be corrected. * If input data is valid, perform the business task such as saving a row into a database. This can be done by logic code embedded within the Action class itself, but should generally be performed by calling an appropriate method of a business logic bean. * Update the server-side objects that will be used to create the next page of the user interface. These objects would typically be request scope or session scope beans, depending on how long you need to keep these items. - * Return an appropriate !ActionForward object that identifies the presentation page to be used to generate this response, based on the newly updated beans. Typically, you will acquire a reference to such an object by calling findForward on either the ActionMapping object you received (if you are using a logical name local to this mapping), or on the controller servlet itself (if you are using a logical name global to the application). + * Return an appropriate !ActionForward object that identifies the next web resource. The flip side of Struts flexibility is greater complexity of a most common request/response cycle comparing to similar ASP.NET request/response cycle: inline:asp_render_submit.gif - - Besides the sheer complexity, original Struts setup/submit pattern has other design and usability implications: - * Most developers program actions as simple services, not as part of a logical web resource. Thus one Action often deals with only one message, like {{{updateCustomer.do}}} handles "Update Customer" event, {{{deleteCustomer.do}}} handles "Delete Customer" event. - * Output data is often scattered in an uncontrolled manner throughout request and session scope. - * In case of error the data entry form is redisplayed by a submit action. This means that submit action duplicates setup functionality of setup action. - * This pattern often relies to automatic validation. The downside of this approach is that in case of error the submit action class is never get called and cannot affect the workflow. - * One page is represented with two different URLs in the browser. - * An attempt to refresh a page after it has been redisplayed causes double submit. - * Success page where submit action forwards to, often corresponds to a logically different resource. It is impossible to tell which logical resource is managed by which Action classes. The M:M relationship between actions and pages leads to a spaghetti code both in Java code as well as in {{{struts-config.xml}}} file. - - inline:icon_alert.gif This chapter discussed the improved Setup/Submit Pattern. To see the original Setup/Submit Pattern click here. - - == Improving Setup/Submit Pattern == - - Use !ActionForm object to store both input and output data. Use the same !ActionForm object in both setup and submit actions. Declaratively (via {{{struts-config.xml}}}) associate the action form with submit action only, do not associate the action form with setup action. - - On setup phase, prepare the action form with output data and forward to a view. When a user submits HTML form, Struts will populate the action form that is associated with submit action. This is the same form that was used to render a page. - - If input data is not valid, do not redisplay the page from submit action. Instead, update application state if needed, generate error messages, and forward control to setup action. It is the job of setup action to prepare and display views; the job of submit action is to handle the input and to update application state. - - If action form was associated with setup action, it would be repopulated by Struts. Remember, that action form has not been associated with setup action, so it will not be repopulated when control is forwarded to setup action from submit action. Setup action will render the page along with error messages that have been generated by submit action. - - Instead of forwarding to success '''page''', forward to '''setup action''' of success web resource. - - The above steps will allow to cleanly separate concerns between actions, as well as to keep input/output data in one place. - - inline:setup_submit_improved.gif == Action As Event Dispatcher == Event Dispatcher handles a group of related messages (events, commands). These messages often correspond to one business object, like classic Create, Retrieve, Update and Delete messages that identify basic operations on persistent objects in a database-driven application. Event Dispatcher usually changes application state based on incoming message. Application state can be stored in a database, a flat file or in a scoped object like !HttpSession or !HttpServletRequest. An event dispatcher has methods that correspond to incoming messages. Therefore an Action that manages a persistent object will likely have {{{create}}}, {{{retrieve}}}, {{{update}}} and {{{delete}}} methods. Each method is triggered with a specific parameter sent in a request. - - inline:event_dispatcher.gif Struts defines several dispatch classes like !DispatchAction, !LookupDispatchAction, !MappingDispatchAction, !EventDispatchAction. These subclasses decode an event from incoming request and dispatch it to a corresponding event handler. The exact way of defining events depends on specific Action subclass.