Martin, I am really interested in those gnarly bits of including a Struts action, because I use this approach a lot. Maybe what I do helps me to somehow avoid the reefs, but for the sake of broader education I would really be interested in possible issues.
I will try to reconstruct what happens with including a Struts action. Please correct me if/when I get wrong. (1) First, the JSP dynamic include mechanism is a legitimate way of building composite pages. It should work properly with no regards to what is included, whether a Struts action or a JSP file. Tomcat's Jasper compiler uses RequestDispatcher.include for <jsp:include> action: if(flush && !(out instanceof BodyContent)) out.flush(); String resourcePath = getContextRelativePath(request, relativePath); RequestDispatcher rd = request.getRequestDispatcher(resourcePath); rd.include(request, new ServletResponseWrapperInclude(response, out)); Such straightforward usage of RequestDispatcher.include does not work well with Struts actions because a Struts action usually performs a forward to JSP. Forwarding from an included resource does not work because servlet spec states explicitly that container should flush the output stream after forwarding. Therefore the content of a composite page that follows the included Struts action is not rendered. This is not that bad actually. Resin renders such a composite page successfully, apparently they went a little bit farther than SRV spec. Tomcat, on the other hand, renders a partial page, cutting out the content that follows an included action, exactly by the book. So using standard <jsp:include> tag does not work well for Struts actions. Oh well, but <c:import> works! In Tomcat a resource imported with JSTL <c:import> results in: ImportResponseWrapper irw = new ImportResponseWrapper((HttpServletResponse)pageContext.getResponse()); rd.include(pageContext.getRequest(), irw); pageContext.getOut().print(irw.getString()); Instead of writing directly to original response and flushing it, ImportSupport tag uses a separate response wrapper and adds the output of included resource to original stream. This allows using forwarding in an included resource and makes including of a Struts action possible. The verdict on dynamic inclusion: Apache implementation of JSTL spec allows to include a resource that forwards to another resource, like a Struts action forwarding to JSP page. Will this work with non-Apache JSTL implementation? I don't know, frankly I haven't read JSTL spec. This may be a potential issue. But it seems that Apache implementation is the industry standard, Sun's website links to Apache when one wants to download JSTL implementation. So I am pretty confident about including a Struts action with a <c:import> tag. (2) Repeating the request processing sequence, by container. This should work on all containers for all types of resources, so I don't see how including a Struts action is worse than including a JSP file. If a container behaves differently, by executing or not executing filters for included resources, it should behave the same way for JSP file or for a Struts action. (3) Repeating the request processing sequence, by Struts. Struts will repeat the whole command chain for an included request. Aside from extra processing time, how bad is it? Right off the bat I can see the only major problem with instantiating and populating ActionForms. First problem is having the same ActionForm referred to in a composite page as well as in included action. If the ActionForm is defined in different scopes, it will be recreated. Long ago I experimented with chained actions having ActionForms in different scopes and I agree that the result did not exactly turn as I predicted. So one should use the same scope for the same-named actionform to avoid "gnarly issues". If an ActionForm is in the same scope for both actions, it will be repopulated. So what? This seems normal to me, at least for the way how Struts works, and this is documented. On the other hand, composing a page out of actions is not exactly the same thing as chaining. I doubt that one would use the same actionform for composite page itself and for an included action. I see included actions as standalone components, they should not share their parts. Another issue is messages. Currently messages are bound to scope, not to an action. This is just wrong. Messages should be bound to an ActionForm, messages should be *stored* in an ActionForm. This makes things simple. ActionForm is an UI object that represents business data. ActionForm also contains messages related to this data. I think this is logical. I am not going to change how messages are handled now, but I would like to add new messages object, that is a property of an ActionForm. Wrote a lot... What did I miss or get wrong? On 9/7/06, Martin Cooper <[EMAIL PROTECTED]> wrote:
On 9/6/06, Michael Jouravlev <[EMAIL PROTECTED]> wrote: > > On 9/6/06, Martin Cooper <[EMAIL PROTECTED]> wrote: > > The action is (intended to be) the class that handles the entire > > request, whether that involves parcelling out the work to other classes > or > > not. An action was designed to be the end point of the request, not one > of a > > set that handles the request in collaboration with each other. > > The SS-18 ballistic missile was created to deliver a dozen of nuclear > warheads to another continent. Now it is used to launch satellites > into orbit. I don't see a problem in using something in a way it was > not intended to be used. > > > It is the nested invocation of > > the request dispatcher that causes all of the issues with (traditional) > > action chaining. It's the request dispatcher that may or may not execute > > filters, depending on the container and J2EE version you are running. It > is > > the request dispatcher that will combine request parameters from the > > original request with those of the include or forward, possibly > occluding > > what you want to see. Those are where the gnarly bits lie. > > These are all good arguments against composing a page out of > action-based components. Still I don't see a *really* serious problem > here. Yes, parameters will be combined. Yes, request dispatcher will > do the same work several times for one request, so what? Filters, > well, I haven't thought about them... Still, I don't want to dismiss > the composition idea just because of "gnarly bits" of implementation > ;) For six years or so, I've watched people repeatedly shoot themselves in the foot becuse they think they want to chain actions and they _don't know_ the consequences or their - uh - actions. The serious problem is that many - perhaps most - developers have no idea what is going on under the covers, and they _will_ get into problems with chaining actions, and will have no idea _why_ they are getting into problems. There's no way I want to see us encouraging the use of an anti-pattern that is an anti-pattern for very good reasons. Just because it _can_ be done doesn't mean it _should_ be done. We are here to help users to build their applications as simply as possible. Using techniques that have traps and pitfalls that are easily stumbled upon is not a good way to do that. -- Martin Cooper
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]