As is, the DispatchAction in Struts 1.02  cool, but does not provide direct
support for eliminating or consolidating duplicate code from related tasks.
It's just a different style.  With DispatchAction, one can have one big
action class to handle related tasks, as opposed to  several little Action
classes.  However, related tasks often have some common logic that needs to
be performed for all the tasks, and other logic that is specific to each
task.  It would be cool if there was a DispatchAction that provided hooks
for the common logic.  One approach would be to use the Template Method
pattern, perhaps something like this:

public class TemplateMethodDispatchAction extends DispatchAction {

  public ActionForward perform(ActionMapping mapping,
                               ActionForm form,
                               HttpServletRequest request,
                               HttpServletResponse response) {
    beforeHook();
    ActionForward forward = super.process(mapping, form, request, response);
    return afterHook(forward);  
  }

  protected void beforeHook(ActionMapping mapping,
                            ActionForm form,
                            HttpServletRequest request,
                            HttpServletResponse response) {
    // does nothing by default
  } 

  protected ActionForward afterHook(ActionForward forward, 
                                    ActionMapping mapping,
                                    ActionForm form,
                                    HttpServletRequest request,
                                    HttpServletResponse response) {
    return forward; // just returns the forward that was passed in by
default
  } 
 
}

Defing the beforeHook and afterHook methods in derived clases would be
optional.  If you don't define them, TemplateMethodDispatchAction behaves
just like DispatchAction.  If you choose to define them, you have slots to
put common pre/post processing logic.

The afterHook method returns an ActionForward to allow for cases where the
logic to determine the next page is common for all tasks, and can thus be
coded in one place in the afterHook.  However, the default implementation of
afterHook just returns the forward returned by the task specific methods
(i.e. create, update, delete), to allow for cases where the logic to
determine the next page varies with the task.
  
Of course, you can use procedural decomposition to factor out the common
logic instead, and rely on the task specific methods (i.e. create, update,
delete) to remember to call the appropriate pre/post processing methods at
the right time.  However, the calls to the common methods would still get
duplicated in each task specific method.  The Template Method approach is
more automated.

Does Struts 1.1 have anything like this?

Steve Molitor
[EMAIL PROTECTED]



-----Original Message-----
From: Ted Husted [mailto:[EMAIL PROTECTED]]
Sent: Friday, May 31, 2002 6:12 AM
To: [EMAIL PROTECTED]
Subject: [Struts Tips] #2 - Use DispatchAction to organize related
operations


Any software application is defined by the things it can do for you. In
a Struts Web application, the things an application does is usually
defined by its action-mapping elements. An action-mapping is designed to
be the target of an HTML form, and is often used with hyperlinks as
well. 

Each action-mapping can specify a Struts Action class as its handler. In
larger applications, developers can find themselves managing dozens or
even hundreds of Action classes. 

In practice, many of these Action classes handle related operations,
often evidenced by their name. A package might include separate
RegCreate, RegSave, and RegDelete Actions, which just perform different
operations on the same RegBean object. Since all of these operations are
usually handled by the same JSP page, it would be handy to also have
them handled by the same Struts Action. 

A very simple way to do this is to have the submit button modify a field
in the form which indicates which operation to perform. 

<SCRIPT>
function set(target) {
 document.forms[0].dispatch.value=target;
}
</SCRIPT>

<html:hidden property="dispatch" value="error"/>
<html:submit onclick="set('save');">SAVE</html:submit>
<html:submit onclick="set('create');">SAVE AS NEW</html:submitl> 
<html:submit onclick="set('delete);">DELETE</html:submit>

Then, in the Action you can setup different methods to handle the
different operations, and branch to one or the other depending on which
value is passed in the dispatch field. 

String dispatch = myForm.getDispatch();

if ("create".equals(dispatch)) { ...

if ("save".equals(dispatch)) { ...

The Struts Dispatch Action is designed to do exactly the same thing, but
without messy branching logic. The base perform method will check a
dispatch field for you, and invoke the indicated method. The only catch
is that the dispatch methods must use the same signature as perform.
This is a very modest requirement, since in practice you usually end up
doing that anyway. 

To convert an Action that was switching on a dispatch field to a
DispatchAction, you simply need to create methods like this 

    public ActionForward create(ActionMapping mapping,
                 ActionForm form,
                 HttpServletRequest request,
                 HttpServletResponse response)
    throws IOException, ServletException { ...

    public ActionForward save(ActionMapping mapping,
                 ActionForm form,
                 HttpServletRequest request,
                 HttpServletResponse response)
    throws IOException, ServletException { ...

Cool. But do you have to use a property named dispatch? No, you don't.
The other step is to specify the name of of the "dispatch" property as
the "parameter" property of the action-mapping. So a mapping for our
example might look like this:

            <action 
                path="/reg/dispatch"
                type="app.reg.RegDispatch"
                name="regForm"
                scope="request"
                validate="true"
                parameter="dispatch"/> // Which parameter to use

If you wanted to use the property "o" instead, as in o=create, you would
change the mapping to 

            <action 
                path="/reg/dispatch"
                type="app.reg.RegDispatch"
                name="regForm"
                scope="request"
                validate="true"
                parameter="o"/> // Look for o=dispatchMethod

Again, very cool. But why use a JavaScript button in the first place?
Why not use several buttons named "dispatch" and use the values to
specify the operation.

You can, but the value of the button is also its label. This means if
the page designers want to label the button something different, they
have to coordinate with the Action programmer. Worse, localization
becomes virtualy impossible.

If you prefer not to use JavaScript buttons, you can use the
DispatchLookup Action instead. This works much like the DispatchAction,
but requires more setup. We'll explore the DispatchLookup Action in Tip
#3. 

HTH, Ted.

---

Struts Tips premiere twice weekly on the MVC-Programmers List. To
subscribe, visit BaseBean Engineering < http://www.basebeans.com >. 

An archive of past tips, like this one, is available at <
http://jguru.com/faq/subtopic.jsp?topicID=893704 >.

About Ted. Ted Husted is an active Struts Committer. He also moderates
the Struts mailing list and the JGuru Struts
FAQ.

Copyright Ted Husted 2002. All rights reserved. 

_______________________________________________
MVC-Programmers mailing list
[EMAIL PROTECTED]
http://www.basebeans.com:8081/mailman/listinfo/mvc-programmers

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

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

Reply via email to