Date: 2004-10-25T05:59:12 Editor: JoeGermuska <[EMAIL PROTECTED]> Wiki: Apache Struts Wiki Page: ActionChaining URL: http://wiki.apache.org/struts/ActionChaining
remove nested 'code' format triple braces from email to improve formatting Change Log: ------------------------------------------------------------------------------ @@ -1,162 +1,160 @@ -Navigation Trail: HomePage / StrutsProjectPages / StrutsDeveloperPages / JamesMitchell / MailDocumentation - -Background: -One might argue that the normal flow of a Struts-based application would be similar to this: - -jsp -> /action -> jsp - -Some people (including myself) prefer this approach - -jsp -> /processaction -> /prepareviewaction -> jsp ----- -{{{ -On Tue, 23 Jul 2002, Pierre Delisle wrote: - -> Date: Tue, 23 Jul 2002 23:26:09 -0700 -> From: Pierre Delisle <[EMAIL PROTECTED]> -> Reply-To: Struts Developers List <[EMAIL PROTECTED]> -> To: [EMAIL PROTECTED] -> Subject: action calling another action -> -> I have a 1.0 struts-based web application where a "higher-level" -> action depends on the processing associated with another lower-level -> action. -> - -Welcome to the eternal debate over whether action chaining/nesting is a good design pattern or not :-). -I'm *not* a believer, but lets address your questions anyway. - -> For example, action "foo" needs to invoke the processing associated -> with action "bar". -> -> Using struts 1.0, I could do the following in the FooAction: -> -> ActionServletMine actionServlet = -> (ActionServletMine)mapping.getMappings().getServlet(); -> ActionMapping targetMapping = actionServlet.findMapping("/bar.do"); -> ((BarAction)actionServlet.getActionInstance( -> targetMapping)).perform(targetMapping, form, request, response); -> - -You should have been able to pass "/bar" as the argument to the -findMapping() method, even in Struts 1.0. - -> ActionServletMine is my own subclass of ActionServlet. It simply -> provides the extra method "getActionInstance()" to allow me to get -> access to the action instance associated with "targetMapping". (it -> calls processActionCreate()). -> -> Migrating to struts 1.1, I was hoping for backwards compatibility, but -> ActionMapping.getMappings() seems to have been removed without being -> first deprecated. Any reason, or am I missing something? (btw, I know -> I could simply call getServlet() within the Action subclass, but I'm -> still curious as to why getMappings() has been removed). -> - -There is no longer a single collection of ActionMappings -- there is one per application module. -So you'll need to do the following to get an -ActionMapping: - -{{{ ApplicationConfig appConfig = (ApplicationConfig) - request.getParameter(Action.APPLICATION_KEY); - ActionMapping mapping = (ActionMapping) - appConfig.findActionConfig("/bar"); }}} - -> -> If I am to bite the bullet right now and rearchitect the webapp with -> the new struts 1.1 api, I still run into a few issues. -> -> What I've described above is how I thought would be the proper way to -> handle "action calling other action" in the very early days of 1.0. -> There might be a better approach now. If so, I'd appreciate if someone -> could point me in the right direction. -> - -Best practice is to factor the common code out and call it from both actions, so you don't -have to do any form of "chaining" or "nesting". - -> If I am to simply migrate the above code to the new 1.1 apis, it -> appears that I'd have to do the following: -> -> ActionServlet actionServlet = getServlet(); -> ApplicationConfig appConfig = mapping.getApplicationConfig(); -> RequestProcessor rp = actionServlet.getRequestProcessor(appConfig); -> -> It appears that "findMapping()" has been deprecated. So the code -> ActionMapping targetMapping = -> actionServlet.findMapping("/bar.do"); -> should be replaced by -> ActionConfig targetAction = appConfig.findActionConfig() -> - -You have to look up the correct ActionConfig from the ApplicationConfig, and cast -it to ActionMapping (for backwards compatibility). - -> The problem though is that the execute() method of an Action expects -> an ActionMapping object... which means that I'm back to want to use -> the old 1.0 api to get an ActionMapping (or I'm once again missing -> something). How come the new execute() method of Action does not take -> an ActionConfig object as argument instead of the old ActionMapping? -> - -The ActionMapping class in 1.1 is a subclass of ActionConfig, and that is the class -actually used in the configuration file parsing. So the cast will always work. - -> Finally, it would be preferable to migrate to the new RequestProcessor -> interface. However, ActionServlet.getRequestProcessor() is protected, -> preventing me from accessing it from my Action code. Any reason why it -> is not public? - -Because you shouldn't be messing around with this stuff in the first place :-). - -Actually, the RequestProcessor instance that is processing the current request can be -acquired directly, from the same place that ActionServlet gets it: - -{{{ String key = Action.REQUEST_PROCESSOR_KEY + appConfig.getPrefix(); - RequestProcessor processor = (RequestProcessor) - servlet.getServletContext().getAttribute(key); }}} - -The only difference is that the ActionServlet.getRequestProcessor() method will lazilly -instantiate the request processor the first time. By the time you execute the above code -in an Action, you will not have to worry about that. - -> -> Many thanks for any answer/advice... -> -> -- Pierre -> - -Craig - - }}} - - - ----- - -Ted Husted wrote: - -IMHO, Action chaining is linking three or more Actions together. -(e.g., three points determine a chaine :0) Simply forwarding from -one Action to another, so the second can select the page and -complete the response, is an ordinary and expected use of the -framework. - -The "evil" part is when people start using the Action objects as -an API and want to pass (new) parameters from one Action to -another, either by changing the properties on the ActionForm or by -creating a new query string on the fly. The danger here is that -the Action *classes* become coupled and start looking like a mess -of "GOTO"s. - -While there could be exceptions, this usually indicates that there -is not sufficient separation between the Action classes and the -business tier. Why? Because if I have a decent business facade, I -shouldn't have to kludge-around with setting new properties on an -ActionForm or as a request parameter. I should be able to code -directly to the business facade. - --Ted. - - - +Navigation Trail: HomePage / StrutsProjectPages / StrutsDeveloperPages / JamesMitchell / MailDocumentation + +Background: +One might argue that the normal flow of a Struts-based application would be similar to this: + +jsp -> /action -> jsp + +Some people (including myself) prefer this approach + +jsp -> /processaction -> /prepareviewaction -> jsp +---- +{{{ +On Tue, 23 Jul 2002, Pierre Delisle wrote: + +> Date: Tue, 23 Jul 2002 23:26:09 -0700 +> From: Pierre Delisle <[EMAIL PROTECTED]> +> Reply-To: Struts Developers List <[EMAIL PROTECTED]> +> To: [EMAIL PROTECTED] +> Subject: action calling another action +> +> I have a 1.0 struts-based web application where a "higher-level" +> action depends on the processing associated with another lower-level +> action. +> + +Welcome to the eternal debate over whether action chaining/nesting is a good design pattern or not :-). +I'm *not* a believer, but lets address your questions anyway. + +> For example, action "foo" needs to invoke the processing associated +> with action "bar". +> +> Using struts 1.0, I could do the following in the FooAction: +> +> ActionServletMine actionServlet = +> (ActionServletMine)mapping.getMappings().getServlet(); +> ActionMapping targetMapping = actionServlet.findMapping("/bar.do"); +> ((BarAction)actionServlet.getActionInstance( +> targetMapping)).perform(targetMapping, form, request, response); +> + +You should have been able to pass "/bar" as the argument to the +findMapping() method, even in Struts 1.0. + +> ActionServletMine is my own subclass of ActionServlet. It simply +> provides the extra method "getActionInstance()" to allow me to get +> access to the action instance associated with "targetMapping". (it +> calls processActionCreate()). +> +> Migrating to struts 1.1, I was hoping for backwards compatibility, but +> ActionMapping.getMappings() seems to have been removed without being +> first deprecated. Any reason, or am I missing something? (btw, I know +> I could simply call getServlet() within the Action subclass, but I'm +> still curious as to why getMappings() has been removed). +> + +There is no longer a single collection of ActionMappings -- there is one per application module. +So you'll need to do the following to get an +ActionMapping: + + ApplicationConfig appConfig = (ApplicationConfig) + request.getParameter(Action.APPLICATION_KEY); + ActionMapping mapping = (ActionMapping) + appConfig.findActionConfig("/bar"); + +> +> If I am to bite the bullet right now and rearchitect the webapp with +> the new struts 1.1 api, I still run into a few issues. +> +> What I've described above is how I thought would be the proper way to +> handle "action calling other action" in the very early days of 1.0. +> There might be a better approach now. If so, I'd appreciate if someone +> could point me in the right direction. +> + +Best practice is to factor the common code out and call it from both actions, so you don't +have to do any form of "chaining" or "nesting". + +> If I am to simply migrate the above code to the new 1.1 apis, it +> appears that I'd have to do the following: +> +> ActionServlet actionServlet = getServlet(); +> ApplicationConfig appConfig = mapping.getApplicationConfig(); +> RequestProcessor rp = actionServlet.getRequestProcessor(appConfig); +> +> It appears that "findMapping()" has been deprecated. So the code +> ActionMapping targetMapping = +> actionServlet.findMapping("/bar.do"); +> should be replaced by +> ActionConfig targetAction = appConfig.findActionConfig() +> + +You have to look up the correct ActionConfig from the ApplicationConfig, and cast +it to ActionMapping (for backwards compatibility). + +> The problem though is that the execute() method of an Action expects +> an ActionMapping object... which means that I'm back to want to use +> the old 1.0 api to get an ActionMapping (or I'm once again missing +> something). How come the new execute() method of Action does not take +> an ActionConfig object as argument instead of the old ActionMapping? +> + +The ActionMapping class in 1.1 is a subclass of ActionConfig, and that is the class +actually used in the configuration file parsing. So the cast will always work. + +> Finally, it would be preferable to migrate to the new RequestProcessor +> interface. However, ActionServlet.getRequestProcessor() is protected, +> preventing me from accessing it from my Action code. Any reason why it +> is not public? + +Because you shouldn't be messing around with this stuff in the first place :-). + +Actually, the RequestProcessor instance that is processing the current request can be +acquired directly, from the same place that ActionServlet gets it: + + String key = Action.REQUEST_PROCESSOR_KEY + appConfig.getPrefix(); + RequestProcessor processor = (RequestProcessor) + servlet.getServletContext().getAttribute(key); + +The only difference is that the ActionServlet.getRequestProcessor() method will lazilly +instantiate the request processor the first time. By the time you execute the above code +in an Action, you will not have to worry about that. + +> +> Many thanks for any answer/advice... +> +> -- Pierre +> + +Craig + + }}} + + + +---- + +Ted Husted wrote: + +IMHO, Action chaining is linking three or more Actions together. +(e.g., three points determine a chaine :0) Simply forwarding from +one Action to another, so the second can select the page and +complete the response, is an ordinary and expected use of the +framework. + +The "evil" part is when people start using the Action objects as +an API and want to pass (new) parameters from one Action to +another, either by changing the properties on the ActionForm or by +creating a new query string on the fly. The danger here is that +the Action *classes* become coupled and start looking like a mess +of "GOTO"s. + +While there could be exceptions, this usually indicates that there +is not sufficient separation between the Action classes and the +business tier. Why? Because if I have a decent business facade, I +shouldn't have to kludge-around with setting new properties on an +ActionForm or as a request parameter. I should be able to code +directly to the business facade. + +-Ted. + --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]