Action Chaining

First, we usually define "action chaining" as creating a "move" action
by having a "copy" action forward to a "delete" action. Simply going
from one action to another isn't a classic example of harmful
chaining. The key point is whether only one action resolves the
business use case.

Classic action chaining is considered harmful because it implies that
the Actions have become a business facade. Any Action should be able
to call facade.copy and facade.delete from a move Action. Better yet,
the facade should provide a move method, and implement it any way it
likes. We should not feel like we need to reuse multiple Action
classes to solve one business use case. Struts 1 Actions were intended
to be what Martin Fowler calls a "transaction script", where "move" is
one transaction, not two.

The design of Struts 1 made action chaining difficult because s1
repopulates the request on every forward. When people start to use the
S1 actions as an API, they want to do things like change properites on
an ActionForm, and are surprised when the framework resets their
changes!

The Struts 2 group does discourgage classic Action chaining, because
it implies the business API is underdevelpoed. Albeit, we do provide a
action chaining result that copies the properties from one Action to
the next. The interceptor stack and result are processed for the
chained action, but the request doesn't pass back through the
container.

* http://struts.apache.org/2.x/docs/action-chaining.html

So you can set a flag on the copy action and have it picked up by the
delete action. This is *not* considered an ideal practice, since
coupling individual Action classes complicates the API, but it's there
when people choose to use it.

So, yes, Struts 2 has an elegant solution for action chaining, if you
choose to use it.

Control preparation

As mentioned, Struts 2 solves the control population issue via the
preparable interface. Another solution is to use the action tag to
execute an Action in place.

* http://cwiki.apache.org/confluence/display/WW/action

One way to use this tag is to put a control on a "snippet" JSP that is
rendered as a result of an Action that does nothing but create the
object that populates the control. The action tag sets
"executeresult=true", then control markup will be "included" into the
page (like a tile), after the action executes.

In effect, exectuteResult actions can be used like a tag that can run
its own action before emitting the markup.

Input.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<s:form>
   <s:action name="languages" namespace="/ActionTag" executeResult="true"/>
   <s:action name="colors" namespace="/ActionTag" executeResult="true"/>
   <ssubmit/>
</s::form>

Languages.jsp

<%@ taglib prefix="s" uri="/struts-tags" %>
<s:select
       tooltip="Choose Your Favorite Language"
       label="Favorite Language"
       list="favoriteLanguages"
       name="favoriteLanguage"
       listKey="key"
       listValue="description"
       emptyOption="true"
       headerKey="None"
       headerValue="None"/>

Languages.java (execute)

   public String execute() {
       favoriteLanguages.add(new Select.Language("EnglishKey",
"English Language"));
       favoriteLanguages.add(new Select.Language("FrenchKey", "French
Language"));
       favoriteLanguages.add(new Select.Language("SpanishKey",
"Spanish Language"));
       return SUCCESS;
   }


struts.xml (Input, Languages)

       <action name="Input">
           <result type="plaintext">Input.jsp</result>
       </action>

       <action name="Languages" class="app.Languages">
           <result>Languages.jsp</result>
       </action>


The advantage being that the "Languages" action could be dropped in
whereever the "Languages" control is needed, and that the Action for
the form doesn't need to know how to populate the Languages control.

Now, the Action is going to be hit every time the page is rendered,
but so long as you are using a caching data access layer, like IBATIS
or Hibernate, it will end up being a memory-to-memory transfer, rather
than a database access.

-Ted.

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

Reply via email to