On Wed, 13 Aug 2003, PILGRIM, Peter, FM wrote:

> In the excitment I got caught up the discussion about customised
> action forward, whereas the original design intention got chucked
> to the side, namely a ``composable request processor''. So let
> me spend some time discussing this:
>
> Now I am at work. I said `RequestProcessor' currently could be
> rewritten as a `Chain', because it aggregates a many `Command's.
> But I am wondering about that statement. It would be seem
> to me `RequestProcessor' is a very complex `Command'
>
> Going back to the original "Decomposable request Processor" thread
> there were at least two concerns:
>
> 1) How delegate or nest processors so that they do the right thing.
>

In contrib/struts-chain you'll see one approach for doing that.  I
separated the chain to pick which module to run from the chain to run the
standard processing pipeline.  In commons-chain there's a generic lookup
command so that you can easily call nested chains by literal names or
indirectly (by computing the name of the chain you want and then looking
it up in the Catalog).

There's also an option on the lookup command to ignore lookup failures.
The example config uses this to let you optionally plug a preprocess
command into either of the above two chains, simply by registering your
own command under a particular name.

> 2) Deciding which methods of the current processor should be decomposed.
>

If we're trying to emulate the 1.1 RequestProcessor, wouldn't it need to
be all of them?  That's what I started down the path of doing.

> 3) Configuring the chain of processor from XML.
>

commons-chain has some utilities to easily construct a Digester instance
that can parse them, and contrib/struts-chain uses that.  See the
following file in the Struts sources:

  contrib/struts-chain/src/conf/chain-config.xml

There are, of course, no restrictions on how you actually register things
in the Catalog, so you can load chain definitions from a database (or
whatever) as well.

>
> Delegation: I believe would be like Servlet Filters as they are implemented
> now. If we have servlet filters A and B , then we know that if filter A
> chained to filter B. The final effect is not necessarily equal to B
> followed A.
>

Order is definitely important in the standard chain, just like it is
today.

> Methods: In the current request processor there is one method
> `process()' which has a default implementation:
>
>    public void process(HttpServletRequest request,
>                         HttpServletResponse response)
>         throws IOException, ServletException
>
> This method calls other ``process*'' methods.
>
>         processLocale(request, response);
>
>       ...
>
>         processPreprocess(request, response);
>
>         ActionMapping mapping = processMapping(request, response, path);
>
>       ...
>
>         ActionForm form = processActionForm(request, response, mapping);
>         processPopulate(request, response, form, mapping);
>
>       ...
>
>         Action action = processActionCreate(request, response, mapping);
>
>       ...
>         ActionForward forward =
>             processActionPerform(request, response,
>                                  action, form, mapping);
>
> My question is if we make `RequestProcessor' a common-chain `Command'
> then do then in turn make it call other `Command' in order to emulate
> all the `process*()' calls. For example
>
>       // RequestProcessor implemented as complex `Command'
>       // Assuming we get a web context from somewhere,
>       StrutWebContext sc = ... ;
>
>       processPreprocessCommand.execute( sc );
>
>       ...
>
>       ActionForm form = (Action)
>               processActionCreate.getAttributes().get("ActionForm");
>
>       ...
>
>       processActionCreate.execute( sc );
>       Action action = (Action)
>               processActionCreate.getAttributes().get("Action");
>
>       ...
>
>       processActionCreate.execute( sc );
>       ActionForward forward = (Action)
>               processActionCreate.getAttributes().get("ActionForward");
>
>
> Is this anything like what you had in mind, Craig? Because it
> looks to me a bit untidy, but the request processor has effectively
> been decomposed into commands.
>

Not only "had in mind" but "already partly done".  There would no longer
be any direct calls to each "process" method -- instead, they would all be
commands in a chain that is preconfigured by Struts (and then optionally
specialized by the app developer).

See the sources in contrib/struts-chain.

> The problem for me is building the new request processor, complex
> command. what would the API look like?
>
>       DefaultComplexProcessor dcp = ... ; // Our new request processor
>
> Suppose I want to intercept the process of creating a new ``Action''
> instance. If we write accessor method to expose the ``Chain'' that
> is responsibe for creating an action, such as this:
>
>       Chain oneChain =dcp.getProcessActionCreateChain();
>
> then I could add my custom interceptor
>
>       oneChain.addCommand( new ExpressoProcessActionCreateCommand() );
>
> Is this speculation or truth? Am I on the right track or do you
> have something else in mind.
>

At the API level, Chain.addCommand() is absolutely the way that chains are
actually constructed.  It's easier to build them from XML or some other
data source, though.

If we were to build everything on such a structure, configuring a Struts
app would be mostly done by letting Struts load its standard definitions
of all the chains (from some internal-to-Struts XML resource), then
letting the application load its own config files -- possibly overriding
the standard chain definitions -- then specifying the name of the chain
that initially gets control (and is therefore responsible for processing
the entire request).  There wouldn't really be a RequestProcessor any more
(although for 1.1 we'd probably implement all this inside a new one that
simply replaces the process() method with the appropriate chain lookup and
execution.)

> Thoughts
>
> --
> Peter Pilgrim,
> Struts/J2EE Consultant, RBoS FM, Risk IT
> Tel: +44 (0)207-375-4923
>

Craig

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

Reply via email to