Struts Tip #11 - Use smart forwarding to dispatch actions

Ted Husted



A key component to the Struts framework is the ActionForward. A deceptively simple object, all the ActionForward does is associate a system path with a logical name. But this object gives the framework much of its power and flexibility.

The workhorse of the framework are the Action objects. When an Action completes, it returns an ActionForward to the controller. The controller then passes control to whatever path is indicated by the ActionForward. Most times, the Action doesn't know anything about the path. It just knows to forward to "success" or "failure". Of course some Actions are more flexible and might return any number of different forwards depending on the circumstances. An Action could start by retrieving a record and then forward to "copy" or "delete", depending on what the user requested.

There's a similar situation when an application processes a form. Most forms contain a number of fields that you can enter or edit, with an OK or CANCEL button. But other times, we might want to do several other things, like "DELETE" or "SAVE AS NEW". We could use a DispatchAction (Tip #2), but that requires making changes to how an Action is coded.

The Struts framework already provides ActionForwards to describe how control flows through the application. An action mapping can have any number of local forwards. So it follows that we should be able to use local forwards to dispatch control. Each of the local forwards can represent one of the form operations. So, for example, the "copy" forward can send control to the copy action, and the "delete"forward can send control to the delete action. Something like this

<action name="articleForm" path="/do/article/Submit" ... > 
    <forward name="create" path="/do/article/Create"/> 
    <forward name="save" path="/do/article/Store"/> 
    <forward name="delete" path="/do/article/Recycle"/> 
    <forward name="cancel" path="/do/Menu"/> 

A HTML form can only submit to one location, so we have to start with a single "clearinghouse" action that can be the target of the form. This action needs to be able to determine the operation, and then send control to the appropriate local forward. This is very similar to what the DispatchAction does. It looks up a parameter in the request and uses the value of that parameter to select a method.

Doing the same thing in an action takes a single line in the perform() [or execute()] method:

public final class RelayAction extends Action { 
    public ActionForward perform(
        ActionMapping mapping, 
        ActionForm form, 
        HttpServletRequest request, 
        HttpServletResponse response) throws IOException, ServletException { 

        return mapping.findForward(request.getParameter(Tokens.DISPATCH)); 

} // end RelayAction

So, if we have a parameter like


Our RelayAction will look up the "delete" forward and return it to the controller. Working from the example, this would cause the controller to forward to /do/article/Recycle. The Recycle action would then fire as if it had been the target of the action in the first place.

In the form, we can use the same JavaScript function as we used for the DispatchAction in Tip #2:

<html:hidden property="dispatch" value="error"/> 
 function set(target){document.forms[0].dispatch.value=target;} 
<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>

This sets the dispatch property to whatever button the user presses, which in turn selects the corresponding ActionForward for the mapping.

Since the RelayAction is configured through its action-mapping, it can be used as many times as needed by your application without subclassing.

In the next tip, we will look at ways to use RelayAction and some like-minded friends to build config-based menu systems.

HTH, Ted.


Struts Tips  are excerpts from the book Java Web Development with Struts. The tips released twice weekly on the MVC-Programmers List. To subscribe, visit BaseBean Engineering.

About Ted. Ted Husted is an active Struts Committer and co-author of Java Web Development with Struts and Professional JSP Site Design. Ted also moderates the Struts mailing list and the JGuru Struts FAQ.

Copyright Ted Husted 2002. All rights reserved.