Well, there's Action chaining, and there's action chaining. It's a 
perfectly valid idea for an ActionMapping to select where control 
should go next, as Erik is doing. It's fundamental to the 
architechtural, and instrumental to how ActionForm validation 
works. 

So, if we're talking about one ActionMapping forwarding (or 
redirecting) to another ActionMapping, then sure. Everything is 
above board, and you can follow the bouncing ball through the 
Struts Config and see what's happening. 

But, then there's Action chaining. Here, people have an Action 
class create an ActionForward on the fly, jam in some parameters, 
and toss it back to the controller. This is where Action classes 
start binding to Action classes, and the mudslide begins. 

It's my feeling that if Action classes start creating query 
strings and need to be coded in terms of what they need to send to 
the "next" Action, then you're starting to use Action classes to 
implement a business facade. Action classes should be clients of 
the facade, not the facade itself.

In the current example, using an ActionMapping to call a 
DeleteAction and have it route back to some list afterwards seems 
fine to me. So, long as the DeleteAction doesn't know or care if 
its going back to a particular list or a given form. IMHO, an 
Action class should just return a simple semantic like "success", 
"failure", "cancel", and so forth, and let the ActionMapping 
decide how to handle the given gesture. 

And following Laird's example, an application could also include a 
workflow engine that would return a semantic to go get the 
whatchacallit. But the ActionMappings would hook up the semantic 
with the actual URI. The real "presentation logic" is that there's 
a JSP stored at /WEB-INF/pages/whatchacallit. On top of that, 
there's application/workflow logic that might say the semantic 
"whatchamcallit" should display the form that collects the 
whatchallit property.

Where things get messy is that sometimes people come up with a 
multi-step server-side workflow, where they want to, say, copy and 
delete (or move) a record, and then return to a list. So you got 
the copy action looking at some flag that says "do delete next", 
and so it sets something in the request or action form, and 
forwards on to delete, which then looks at something that tells it 
to forward on to a list.  

In this case, we're starting to do a Rube Goldberg shuffle around 
Robin Hood's barn. There should just be a move action that calls 
both copy and delete through the business facade -- being the 
exact same methods an independant copy or delete Action would 
call. If there is more than a line or two of code involved in an 
atomic process like delete, then the Action classes are working 
too hard. 

IMHO, Action classes should not be considered atomic. Most often, 
there should be a 1:1 correlation between an Action class and your 
business facade. The business facade is your application's 
internal API. It defines what the application can do, what it 
needs to do it, and what it returns when something is done. The 
Action classes interact with the business facade by allowing 
access to the facade from the web tier. Other tiers could also 
interact with the same facade from other platforms. 

So, given the trivial move example, the Action should not even 
have to call copy and delete. There should be move method on the 
facade, and the facade should be the one calling copy and delete.

Behind the facade are the atomic operations, like delete or copy. 
The facade then does any chaining or nesting between atomic 
operations. The atomic operations may be implemented using JDBC or 
EJB or CORBA or Lucene or a web service or whatever you like. But 
the actions don't need to know that, because they only talk to the 
facade. 

<preaching-to-the-choir>Of course, setting up a facade is some 
extra work, and so not everyone does it. Just like setting up an 
interface before defining a base class is some extra work. Using 
actions for your facade works, just like using base classes 
instead of interfaces works. In either case, you are trading a 
layer of indirection for reusability.</preaching-to-the-choir>

But, now we may be getting into the stuff of the user list =:0)

-Ted.




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

Reply via email to