On Sun, 20 Feb 2005 10:26:14 -0800, Don Brown wrote: > Ah, we finally stumble onto the very slipperly slope that is > conditional support for commons-chain. As we put more and more > code into chain, we will inevitably have commands that only need to > execute under certain conditions. There are three possibilities: > > 1. Bury conditional logic inside the command itself. This is the > approach many of the current chains take, but has the disadvantage > of the flow being very unclear to the reader of the config file, > requiring digging into the source code. > 2. Create an "if" command, which then would logically lead to a > "switch" command and perhaps a "for" command. These commands would > check certain conditions then execute configured commands based on > the outcome. > 3. Modify the XML so that the branching code is described as XML > elements. While this option produces the clearest code, it also > brings all the problems of something like Jelly with it. > > So far, chain has resisted conditional support for the very reason > it opens up a huge can of worms. However, as soon as you start > putting complex logic in commons-chain, you are going to run up > against the problem again and again, and I think solution 1 will > really start to be inadequate. Solution 2 feels like a hack, and > solution 3 (executable XML) has been shown a bad idea through Jelly. > > I wonder what a merging of commons-chain and a scripting language > like beanshell would look like... > > Don
(4) Make Chains extensible so that the caller can select the appropriate branch I wouldn't suggest getting into this for 1.3.0, but one way to move some of the conditional logic out of a chain might be to make the Chains more extensible, so that one size does not have to fit all. For example, not every Struts application uses modules. But, there is a lot of special case logic in the Commands to support modules. It would be handy if we could start with a basic Chain that did not support modules, and then specify new Commands to add module support. The key idea would be to give Commands in a Chain identifiers. So, instead of <!-- Identify the ActionConfig for this request --> <command className="org.apache.struts.chain.commands.servlet.SelectAction"/> We'd have <!-- Identify the ActionConfig for this request --> <command NAME="SelectAction" className="org.apache.struts.chain.commands.servlet.SelectAction"/> We could then do something like <chain name="process-action-with-modules" EXTENDS="process-action"> <command name="SelectAction" className="org.apache.struts.chain.commands.servlet.MODULES.SelectAction"/> </chain> to create a new Chain that replaces one Command with another and just copying the rest. Of course, there would be other commands to replace, but the idea would be that only the modular applications would need to load the modular code. Likewise, there could be distinct process-action chains for actions with validation and without validation. <chain name="process-action-with-validation" extends="process-action"> <command name="ValidateActionForm" AFTER="PopulateActionForm" classname ="..." /> </chain> In this case, the "ValidateActionForm" Command would be inserted into the Chain after the "ProcessActionForm" Command. Of course, the conditional logic still occurs (TNSTAFL), but it moves out of the commands and into the controller/caller. The controller (aka request processor) decides whether to call "process-action" or "process-action-with-validate". The difference being that the validation commands no longer need to check the state for themselves. Having been made part of the Chain, they can just go about their business. Using a factory, the "decision" can be made in a OOP way, if we like, if the request-processing chain is made an attribute of the mapping. When the mapping is created, the constructor could assign the appropriate request processing chain. At runtime, the controller would just call whatever chain is linked to a given mapping. This could lead to mappings specifying custom request-processing chains. If some mappings needed an extra processing step, the mapping could specify an alternate request processing chain to be called instead of the default set. Changes to the default processing chain could be specified as part of the mapping, rather than in the catalog. The request-processor catalog could be made part of the struts-config at some point, so that we'd have a one-stop shop again. Of course, such ideas would only be practical if the Chain element supports extends, and I would suggest we ship what we have using Chain 1.0.0 first. -Ted. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]