> -----Original Message----- > From: Ted Husted [mailto:[EMAIL PROTECTED]] > 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.
Ah, that's what I use. I think. That is, if I'm going to cause two different Actions' perform() methods to be invoked during the same browser request, then I always do it via a mapping.findForward(XYZ) call instead of a new ActionForward(someComputedString) call. > 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. Agreed. Mudslides are kind of tasty, though. > 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. One variation on this that I don't think suffers from the same problems is to do something like: // Work has completed by this point, let's say. request.setAttribute(resultOfWork); return mapping.findForward(DONE); ...where the "next" Action selected by the ActionMapping may very well be expecting resultOfWork to be present as a request attribute for presentation/UI-layer purposes only. That is, the semantics of putting resultOfWork into the request must not require that there be a "next" Action--it's just something this Action has to do, regardless of whether someone else down the line consumes it or not. > 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. Right; Actions are web GUI EventListeners. The difference between this (and lots of other web-centric) event handling system and the Java beans event handling system is that the event type is basically the same: you get a request event that has a logical hashtable in it of parameters and values, and an identifier (the path) that tells you what kind of event it is. > 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. Minor quibble: in my mind, the *application* doesn't say to display anything. The presentation layer, which for these purposes I'm separating from the application, does. I only make this point because to me what you're calling the application workflow is really a property of the GUI/presentation layer, not the application. From my previous example, the application domain/business logic domain begins when the frobnicate() method is called, and ends once it returns. All the machinery to gather the requisite parameters and to render the response is presentation logic. Call it workflow if you must, but it's not workflow that's essential to the task (that of frobnication :-)) at hand. > 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. You must have been looking at some of the code that I'm currently forced to maintain. :-) > 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. Yes, exactly. One of the things I was trying to articulate (badly) in an earlier message was that if you do this right, you can swap out GUIs at configuration time. The way that I'm currently trying to do this is by approaching application design from an event perspective ("what events should any GUI for this application be expected to fire to the application itself?"). You set up a central event registry for these things, and have that central event registry also register listeners for those events. The benefits of this approach are that you absolutely and totally enforce separation between the gymnastics you go through on the presentation layer from those you go through on the business layer--if the presentation layer can only talk to the business layer via these centrally defined events, then the task becomes, how do I use my GUI toolkit to generate these events and listen for application events coming back from the business tier? So my Actions for this application are not necessarily super *simple*, but all that they do is to take the presentation layer data (ActionForms, paths, URLs, ActionMappings, ActionForwards, notions of "pages", sessions, etc.) and convert, munge, mash and translate it into Java beans event data ("get the request parameter; find the user data; etc.; fire a SaveUserDataEvent instance to all registered listeners). Then another method on the Action listens for the "return" event (UserDataSavedEvent) that's fired by the business tier. So all the application knows is that some UI somewhere fired a SaveUserDataEvent, and when that happens it knows to save the user data and fire a UserDataSavedEvent in return. You can see that to make this work with Swing all you have to do is hook up a bunch of ButtonListeners and the like and get them to fire SaveUserDataEvents in turn, and no application layer code needs to change. (I'm currently using this approach for a for-fun maunscript tracking software program that I'm writing--one set of customers wants it to be web based, and the other set wants it to be a desktop application. If I pull this off, I can web enable it by dropping different UI jars into place with the application's core jar and it should just work.) Cheers, Laird -- To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]> For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>