Hello,
 
You may have noticed the posts concerning the request for comments on Action Wrappers 
which appeared in Aug and a couple of days ago. Action wrappers work with the existing 
RequestProcessor (1.1) but a much cleaner solution involves a (currently) minor 
refactoring of the RequestProcessor. I would like to ask that this refactoring 
proposal be taken into consideration during discussion of and changes to the 
RequestProcessor.
 
An introduction to Action Wrappers can be found here: 
http://www.sistemas-jasper.com/indexStrutsActionWrappers.htm. The description of the 
refactoring can be found in the API documentation of the ActionProcessor class. The 
refactoring is simple but for brevity I have not cut and paste it here.
 
I believe the action wrappers would be extremely useful to the Struts community, the 
code exists today and they do not conflict with the idea of action chains. So, once 
again, I'd like to request consideration for the refacting mentioned.
 
John A. Sessler
 
 

"Craig R. McClanahan" <[EMAIL PROTECTED]> wrote:
Ted Husted wrote:

> Craig R. McClanahan wrote:
>
>> In terms of the chain implementation of the request processing 
>> lifecycle, this is just an unconditional command in the chain (it's 
>> implemented in o.a.s.c.servlet.PerformForward). No skipping or 
>> stepping is requried. See
>>
>> contrib/struts-chain/src/conf/chain-config.xml
>>
>> for the entire definition. You'll note that it requires no skipping 
>> -- just the conditional behavior on validation failures, which is 
>> modelled as a branch to a separately named command.
>
>
> I wonder if even these conditionals could be made part of the chain. As
> an alternative to branching, the Command could update the state of the
> Context and return false. What is now a conditional Command could be the
> next link the Chain. The "conditional" would check to see if the state
> calls for it to execute, and if so, do its business and return true.

They could indeed be made part of the chain, and "checking the current 
state to see if it's appropriate for me to do anything" is certainly 
more in the spirit of the original CoR pattern. However, I worry a 
little that creating the need for that state information increases 
coupling between commands, and therefore increases the complexity of 
reusing commands in alternative chains.

In the real-life use case we actually have in the CVS repository (the 
one in struts-chain, which actually does work :-), the case in question 
was to deal with the fact that the Struts request processing lifecycle 
has a branch in it, based on whether or not validation succeeds. The 
basic flow goes like this (using the class name of the command 
implementation class, and presuming we're all pretty familiar with the 
corresponding RequestProcessor behavior):

(1) LookupCommand (analogous to the processPreprocess() hook)
(2) ExceptionCatcher (no direct analog - used to implement exception 
mapping behavior)
(3) SelectLocale
(4) SelectAction
(5) CreateActionForm
(6) PopulateActionForm
(7) ValidateActionForm
(8) CreateAction
(9) ExecuteAction
(10) PerformForward

The conditional behavior happens in Step (7) -- if validation fails, an 
alternative path is desired:
(7a) SelectInput (uses the "input" attribute on the )
(7b) PerformForward

At the moment, this is implemented as a branch, to a separate chain that 
the author of ValidateActionForm need not even know the name of at 
design time (it's a configuration property). If ValidateActionForm 
detects a failure, it looks up an alternate chain in the Catalog, 
executes this chain, and then returns true (so that steps 8-10 of the 
original chain are never executed). Note that step (10) in the original 
chain and step (7b) in the alternate chain share a single Command 
implementation instance, because Struts ends up doing the same thing 
either way (RequestDispatcher.forward() or redirect based on what 
ActionForward it is passed). Nothing had to be coded twice.

What would this look like if we merged it into a single chain? Probably 
something like this, with additional state-dependent checking indicated 
in [square brackets]

(1) LookupCommand
(2) ExceptionCatcher
(3) SelectLocale
(4) SelectAction
(5) CreateActionForm
(6) PopulateActionForm
(7) ValidateActionForm (must save state in the Context)
(NEW) SelectInput [skip if validation succeeded]
(8) CreateAction [skip if validation failed]
(9) ExecuteAction [skip if validation failed]
(10) PerformForward

So, implementing this as a single chain would require ValidateActionForm 
to the success/failure state of the validation into the Context -- easy 
to do -- and three commands must now (inside their implementation -- the 
Chain does not know anything about this) surround their current behavior 
in an "if" statement, which means that they have to know the location of 
the state information that was saved (slight increase in coupling), and 
they get processed by the Chain even if they are not relevant (very 
minor performance impact; almost never enough of a concern to worry 
about). But it would definitely work.

As Jing points out, the JavaServer Faces request processing lifecycle is 
slightly more complex, because there are more "go to the end" 
branchpoints (one after each processing phase) -- but again, either 
design pattern will work. In that case, conditional execution is 
actually easier because the relevant state (has 
FacesContext.renderResponse() been called yet?) is visible directly as 
part of the FacesContext that would be passed along anyway).

I think we're going to find that both approaches have applicability. 
You'll tend to choose the "branch" approach when the alternative 
behavior is completely different based on the branch conditions (think 
of a request processor for a SOAP request, which chooses the correct 
chain to execute based on the contents of the SOAP-Action header or 
other data in the request), while conditionals based on state will 
probably be better when the branches "merge" later on (i.e. the 
conditional stuff is in the middle of the chain, not at the end). But 
neither one of them require any change to commons-chain itself, and I'm 
going to continue to resist adding anything there until we find 
application requirements that are both (a) suitable for implementation 
as a chain in the first place; and (b) cannot be implemented cleanly 
without additional control flow type APIs.

>
> -Ted.

Craig



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


---------------------------------
Do you Yahoo!?
The New Yahoo! Shopping - with improved product search

Reply via email to