Re: The BIG Check-In for Multi-App Support
Some others have gone fine, but I just moved a production application over to recent releases of Validator and Tiles and got it working under the 1.1 pre-BIG-check-in build. When I drop in the latest 1.1 Struts JAR, under Resin it comes up with 500 Servlet Exception java.lang.NoClassDefFoundError: org/apache/commons/digester/RuleSet at java.lang.Class.newInstance0(Native Method) at java.lang.Class.newInstance(Class.java:237) at java.beans.Beans.instantiate(Beans.java:207) at java.beans.Beans.instantiate(Beans.java:51) I also had the same problem with the Velocity tools. OK under the precheck in build, but now Resin reports the above, and Tomcat reports: 2002-01-30 18:38:19 StandardContext[/velstruts]: Servlet /velstruts threw load() exception javax.servlet.ServletException: Error instantiating servlet class org.apache.struts.action.ActionServlet at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:829) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3267) at org.apache.catalina.core.StandardContext.start(StandardContext.java:3384) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:785) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:454) at org.apache.catalina.core.StandardHost.install(StandardHost.java:712) at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:599) at org.apache.catalina.startup.HostConfig.start(HostConfig.java:777) at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:463) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:155) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1131) at org.apache.catalina.core.StandardHost.start(StandardHost.java:612) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1123) at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:307) at org.apache.catalina.core.StandardService.start(StandardService.java:388) at org.apache.catalina.core.StandardServer.start(StandardServer.java:505) at org.apache.catalina.startup.Catalina.start(Catalina.java:776) at org.apache.catalina.startup.Catalina.execute(Catalina.java:681) at org.apache.catalina.startup.Catalina.process(Catalina.java:179) at java.lang.reflect.Method.invoke(Native Method) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:243) - Root Cause - java.lang.NoClassDefFoundError: org/apache/commons/digester/RuleSet at java.lang.Class.newInstance0(Native Method) at java.lang.Class.newInstance(Unknown Source) at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:820) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:3267) at org.apache.catalina.core.StandardContext.start(StandardContext.java:3384) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:785) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:454) at org.apache.catalina.core.StandardHost.install(StandardHost.java:712) at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:599) at org.apache.catalina.startup.HostConfig.start(HostConfig.java:777) at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:463) at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:155) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1131) at org.apache.catalina.core.StandardHost.start(StandardHost.java:612) at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1123) at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:307) at org.apache.catalina.core.StandardService.start(StandardService.java:388) at org.apache.catalina.core.StandardServer.start(StandardServer.java:505) at org.apache.catalina.startup.Catalina.start(Catalina.java:776) at org.apache.catalina.startup.Catalina.execute(Catalina.java:681) at org.apache.catalina.startup.Catalina.process(Catalina.java:179) at java.lang.reflect.Method.invoke(Native Method) at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:243) I'll try to look into this futher, but wanted to pass along the report. Meanwhile, I've started to move the Artimus example into the modular/DynaBean format, so we will have a good working example of that. I'm *very* excited about the module and DynaBean support in the new controller package. -Ted. -- To unsubscribe, e-mail: mailto:[EMAIL PROTECTED] For additional commands, e-mail: mailto:[EMAIL PROTECTED]
Re: The BIG Check-In for Multi-App Support
I've finally had a chance to spend a little time looking at this, and it's *very* cool. Regarding backward compatibility, I tried running a large, complicated Struts 1.0 app, complete with customisations of ActionServlet and friends, on top of the latest nightly build, and saw no problems at all. It worked flawlessly. Awesome, Craig! One area that we might give more thought to is that of message resources. In both Struts 1.0.x and the latest code, the apparent assumption is that each application has a single source of message resources. (Alternatively, it is assumed that any other message resources are handled independently of Struts.) In practise, that is not always the case. Each application may have multiple sets of message resources, one of which would typically be the default. Since the DTD now includes support for (default) message resources, how about expanding that capability to allow for the definition of multiple message resources per application, where each non-default resource would have an identifier (key) associated with it? -- Martin Cooper - Original Message - From: Craig R. McClanahan [EMAIL PROTECTED] To: [EMAIL PROTECTED] Sent: Saturday, January 12, 2002 4:52 PM Subject: The BIG Check-In for Multi-App Support OK, I think I've got it working now -- the support for multiple Struts sub-applications in a single web-app, that is. While I'm writing up some documentation for it, here's the key points that will help you experiment with it: * All of the configuration information about a sub-app is stored in the ApplicationConfig object, including a bunch of stuff that used to be set with init parameters on the controller servlet. * A multi-app environment still runs from a single instance of the controller servlet, but you can have multiple struts-config.xml files -- one per sub-application. * The sub-application that applies to a particular request is based on matching an application prefix at the beginning of the context-relative URI (similar to the way that a servlet container chooses the web app to run based on the context path prefix of the request URI. * Like a servlet container, there is the notion of a default sub-application that is used to process requests not assigned to any sub-applicaiton. The prefix for this application is (i.e. the empty string). * All of the context relative values in struts-config.xml are now application-relative instead -- in other words, the request URI equals context path + application prefix + local value. This works even for the default sub-application, because its prefix is a zero-length string. * A primary design goal is that the struts-config.xml for an existing Struts applicaiton can be used as a sub-application with no changes. Failure of this to work should be considered a bug in the current implementation, and needs to be fixed. * In addition to its other duties, the controller servlet creates two request attributes for all requests that flow through the controller: Action.APPLICATION_KEYWill contain the ApplicationConfig instance for the sub-applcation that is selected by the current request URI. Action.MESSAGES_KEY Will contain the MessageResources instance for the sub-applcation that is selected by the current request URI. * WARNING: If you want to use your existing Struts application as a sub-application, then *ALL* of the requests must flow through the controller servlet -- no direct linking to pages -- in order for the above request attributes to always be set. In a servlet 2.3 environment, we'd be able to avoid worrying about this by using a filter, but that doesn't help under servlet 2.2. * A known issue is that sub-apps won't work for path-mapped actions -- only extension mapped at the moment. I believe this can be fixed, but wanted to focus on getting the basics right first. As a quick example of the new approach, assume you have three sub-apps: main - Main menu and such (this is the default subapp) catalog - The shopping portion of a shopping site - prefix /catalog checkout - The checkout portion of a shopping site - prefix /checkout You would configure the sub-applicaitons in their own struts-config files, and tell the controller servlet about them like this: servlet servlet-nameaction/servlet-name servlet-classorg.apache.struts.action.ActionServlet/servlet-class !-- The default sub-application -- init-param param-nameconfig/param-name param-value/WEB-INF/struts-config-main.xml/param-value /init-param !-- The catalog sub-application -- init-param param-nameconfig/catalog/param-name -- Includes prefix! -- param-value/WEB-INF/struts-config-catalog.xml/param-value /init-param
RE: The BIG Check-In for Multi-App Support
On Mon, 14 Jan 2002, Donnie Hale wrote: Date: Mon, 14 Jan 2002 23:54:33 -0500 From: Donnie Hale [EMAIL PROTECTED] Reply-To: Struts Developers List [EMAIL PROTECTED] To: Struts Developers List [EMAIL PROTECTED] Subject: RE: The BIG Check-In for Multi-App Support I've finally had a chance to download this check-in. Please note that while I've built it, I haven't yet had a chance to test it with anything. Are there any examples yet which include all these new features (exceptions, roles, multi-apps, etc.)? There's a lot get one's arms around. Most importantly, this is great stuff and really appreciated. If one of the committers would propose giving Craig a raise, I'd +1 it. ;) So... Some general comments and comments from looking at pieces of the code: 1. I don't know if this is carved in stone yet, but IMHO this is much more than a 1.1 release. Perhaps not a 2.0 release, but at least a 1.5 release. The implications of a single point release to me are minor functional enhancements and bug fixes. These are substantive, major functional enhancements which still provide backward compatibility. Again, just my opinion... I don't consider any of it cast in stone. There are way to many smart people contributing to the future of Struts for me to have the only good ideas. The reason I still want to call the next release 1.1 is this: despite the huge number of internal changes, the fundamental APIs for applications *are* pretty much backwards compatible. That's a promise that was made early on in Struts development, and I want to honor that. Calling it 1.5 or 2.0 would raise concerns in people's minds about compatibility -- even if those fears turned out to be unfounded. 2. I'm thrilled to see all the config-related stuff broken out from the servlet. I did this myself in some recent attempts at refactoring ActionServlet, and the effort was desperately needed to make ActionServlet more approachable. Naturally, Craig did a better job than I, as he gave each piece of config info its own class. Much more manageable and flexible that way. Besides making things easier to understand, it's already had an additional benefit -- new configuration parameters can be added with no code changes to the controller servlet. In fact, if you're adding a property to an existing config object, it is just a matter of a getter and setter, and the automatic introspection logic in Digester takes care of things. 3. In the DTD, the BeanName entity is being overloaded somewhat in that it's used for naming keys to various context attributes as well as for the form beans. BeanName is documented as having to be a legal Java identifier since it's used in JSPs; not sure off the top of my head if that is a constraint on attribute names in the various servlet contexts or not. In any case, might I suggest a ContextKey entity be added to the DTD and that used where appropriate (data-source.key, action.attribute, etc.). That definitely sounds like a good idea. At some point we might add an XML Schema (or other) validation of the struts-config.xml file that adds more semantic checks, so it would be good to get the names right now. 4. Breaking out the request processing into RequestProcessor is also huge. ActionServlet plus the config stuff seem like they can now stand alone with pluggable request processing easily able to reuse those elements. Yep. A subsequent check-in enabled having different RequestProcessor instances (and even implementation classes) per sub-application. 5. In the new ActionServlet, doGet and doPost are identical. Would it be better to delegate their implementations, simple though they are, to a protected overridable method? When it was a single hard-coded request processor instance, the implementation was one line each - I guess three lines is enough to make a subordinate method again. 6. It's a little confusing seeing member variables of type and name FastHashmap actions in both ApplicationConfig and RequestProcessor. Perhaps the variable names could be clarified. In ApplicationConfig, maybe the variable name should be actionConfigs? That corresponds to what the Map actually contains. 7. Is the special handling for the default app's ControllerConfig and MessageResourcesConfig so that existing web.xml files will still work for setting those parameters? Yes. It actually took just as long to figure out how to deal with this as the rest of the design. 8. ActionForward and ActionMappings both still retain references to ActionServlet, and in both cases it seems primarily to allow the user of an ActionForward or ActionMappings to get a reference to the servlet. With the drastic changes to ActionServlet, what method on ActionServlet would the user of an ActionForward or ActionMappings need to call? I guess what I'm saying is that it would be nice to deprecate and/or remove those getServlet/setServlet methods from those classes if they're not really
RE: The BIG Check-In for Multi-App Support
Craig, Thanks for the detailed reply. See below. [snip[ 1. I don't know if this is carved in stone yet, but IMHO this is much more than a 1.1 release. Perhaps not a 2.0 release, but at least a 1.5 release. The implications of a single point release to me are minor functional enhancements and bug fixes. These are substantive, major functional enhancements which still provide backward compatibility. Again, just my opinion... I don't consider any of it cast in stone. There are way to many smart people contributing to the future of Struts for me to have the only good ideas. The reason I still want to call the next release 1.1 is this: despite the huge number of internal changes, the fundamental APIs for applications *are* pretty much backwards compatible. That's a promise that was made early on in Struts development, and I want to honor that. Calling it 1.5 or 2.0 would raise concerns in people's minds about compatibility -- even if those fears turned out to be unfounded. I guess my point was that anything 1.x implies backward compatibility, but a bigger point change implies somewhat substantive functional changes. To Ted - going straight from 1.0.1 to 1.5 wouldn't make me wonder about intervening versions any more than going from 1.2 (or whatever the highest 1.x version of Struts ends up being) to 2.0 will. :) [snip] 4. Breaking out the request processing into RequestProcessor is also huge. ActionServlet plus the config stuff seem like they can now stand alone with pluggable request processing easily able to reuse those elements. Yep. A subsequent check-in enabled having different RequestProcessor instances (and even implementation classes) per sub-application. I noticed that, and I'm hoping to get a chance to revisit the way I'd like to see a RequestProcess be designed. I didn't get that far since I was going about refactoring ActionServlet. But now you've done the dirty work, and it's checked in!!! 5. In the new ActionServlet, doGet and doPost are identical. Would it be better to delegate their implementations, simple though they are, to a protected overridable method? When it was a single hard-coded request processor instance, the implementation was one line each - I guess three lines is enough to make a subordinate method again. I think that's a good idea. Someone may want to override both, and it would be easier to get the super() call right if they just have to override the subordinate method. 6. It's a little confusing seeing member variables of type and name FastHashmap actions in both ApplicationConfig and RequestProcessor. Perhaps the variable names could be clarified. In ApplicationConfig, maybe the variable name should be actionConfigs? That corresponds to what the Map actually contains. I think that's a good idea. 7. Is the special handling for the default app's ControllerConfig and MessageResourcesConfig so that existing web.xml files will still work for setting those parameters? Yes. It actually took just as long to figure out how to deal with this as the rest of the design. Do you think it's possible to target the eventual deprecation of that capability - i.e. requiring thos parms to be in struts-config.xml, even for the default app? I understand the reasoning now, but I think it will be confusing to newcomers in the future and could cause support issues if someone drops in a struts-config.xml file with those values set and intends it to configure the default app. One other question I forgot to ask - you've marked findDataSource and destroyDataSources as deprecated. Should that not also make the dataSources FastHashmap member variable deprecated. It would seem that since the datasources are stuck straight into the context, Struts can let the container manage them and eliminate having to manage them itself. 8. ActionForward and ActionMappings both still retain references to ActionServlet, and in both cases it seems primarily to allow the user of an ActionForward or ActionMappings to get a reference to the servlet. With the drastic changes to ActionServlet, what method on ActionServlet would the user of an ActionForward or ActionMappings need to call? I guess what I'm saying is that it would be nice to deprecate and/or remove those getServlet/setServlet methods from those classes if they're not really required, esp. if the best practice way to get to a resource is through one of the contexts. FWIW... Deprecation is probably a reasonable idea, but I want to walk through the code paths to see if the servlet references are used internally anywhere first. I did searches throughout the base code and didn't come up w/ anything. My biggest concern, and why deprecation would be preferred, is if there are derived ActionForward / ActionMapping classes that think they need access to it. But they're likely broken anyway since, I believe, a lot of the API they'd expect from
RE: The BIG Check-In for Multi-App Support
I've finally had a chance to download this check-in. Please note that while I've built it, I haven't yet had a chance to test it with anything. Are there any examples yet which include all these new features (exceptions, roles, multi-apps, etc.)? There's a lot get one's arms around. Most importantly, this is great stuff and really appreciated. If one of the committers would propose giving Craig a raise, I'd +1 it. ;) So... Some general comments and comments from looking at pieces of the code: 1. I don't know if this is carved in stone yet, but IMHO this is much more than a 1.1 release. Perhaps not a 2.0 release, but at least a 1.5 release. The implications of a single point release to me are minor functional enhancements and bug fixes. These are substantive, major functional enhancements which still provide backward compatibility. Again, just my opinion... 2. I'm thrilled to see all the config-related stuff broken out from the servlet. I did this myself in some recent attempts at refactoring ActionServlet, and the effort was desperately needed to make ActionServlet more approachable. Naturally, Craig did a better job than I, as he gave each piece of config info its own class. Much more manageable and flexible that way. 3. In the DTD, the BeanName entity is being overloaded somewhat in that it's used for naming keys to various context attributes as well as for the form beans. BeanName is documented as having to be a legal Java identifier since it's used in JSPs; not sure off the top of my head if that is a constraint on attribute names in the various servlet contexts or not. In any case, might I suggest a ContextKey entity be added to the DTD and that used where appropriate (data-source.key, action.attribute, etc.). 4. Breaking out the request processing into RequestProcessor is also huge. ActionServlet plus the config stuff seem like they can now stand alone with pluggable request processing easily able to reuse those elements. 5. In the new ActionServlet, doGet and doPost are identical. Would it be better to delegate their implementations, simple though they are, to a protected overridable method? 6. It's a little confusing seeing member variables of type and name FastHashmap actions in both ApplicationConfig and RequestProcessor. Perhaps the variable names could be clarified. 7. Is the special handling for the default app's ControllerConfig and MessageResourcesConfig so that existing web.xml files will still work for setting those parameters? 8. ActionForward and ActionMappings both still retain references to ActionServlet, and in both cases it seems primarily to allow the user of an ActionForward or ActionMappings to get a reference to the servlet. With the drastic changes to ActionServlet, what method on ActionServlet would the user of an ActionForward or ActionMappings need to call? I guess what I'm saying is that it would be nice to deprecate and/or remove those getServlet/setServlet methods from those classes if they're not really required, esp. if the best practice way to get to a resource is through one of the contexts. FWIW... Thanks for bearing with me. Please note that I'm not trying to avoid contributing by bringing up these issues. I want to make sure I don't jump to any false conclusions before I try to help out. Thanks again, Donnie -Original Message- From: Craig R. McClanahan [mailto:[EMAIL PROTECTED]] Sent: Saturday, January 12, 2002 7:53 PM To: [EMAIL PROTECTED] Subject: The BIG Check-In for Multi-App Support OK, I think I've got it working now -- the support for multiple Struts sub-applications in a single web-app, that is. While I'm writing up some documentation for it, here's the key points that will help you experiment with it: * All of the configuration information about a sub-app is stored in the ApplicationConfig object, including a bunch of stuff that used to be set with init parameters on the controller servlet. * A multi-app environment still runs from a single instance of the controller servlet, but you can have multiple struts-config.xml files -- one per sub-application. * The sub-application that applies to a particular request is based on matching an application prefix at the beginning of the context-relative URI (similar to the way that a servlet container chooses the web app to run based on the context path prefix of the request URI. * Like a servlet container, there is the notion of a default sub-application that is used to process requests not assigned to any sub-applicaiton. The prefix for this application is (i.e. the empty string). * All of the context relative values in struts-config.xml are now application-relative instead -- in other words, the request URI equals context path + application prefix + local value. This works even for the default sub-application, because its prefix is a zero-length string. * A primary design goal is that the struts-config.xml
Re: The BIG Check-In for Multi-App Support
Craig R. McClanahan wrote: Let's get this new code wrinkled out in the short term so that we can move towards a 1.1 release as well as the 1.0.1 that was just created. Cool. I can put this to work right away in the Artimus package, http://husted.com/scaffolding/dist/artimus.zip since it is already designed around the idea of sub apps (even though we didn't have them yet). -- Ted Husted, Husted dot Com, Fairport NY USA. -- Building Java web applications with Struts. -- Tel +1 585 737-3463. -- Web http://www.husted.com/struts/ -- To unsubscribe, e-mail: mailto:[EMAIL PROTECTED] For additional commands, e-mail: mailto:[EMAIL PROTECTED]
RE: The BIG Check-In for Multi-App Support
Craig: OK, I think I've got it working now -- the support for multiple Struts sub-applications in a single web-app, that is. I'm happy to hear about this, as it's one of the things we extended in Struts 1.0 when we connected it with Expresso, as the sub-app concept was important for Expresso applications, like eForum, ePoll, etc. I'd like to merge what we did with where you're going, and of course any bits of what we've done already that are useful you're welcome to as well. Just some observations on the parallels, for people using both Expresso and Struts - they're pretty close in most cases, so a merge wouldn't be a serious impedance mismatch from what I can see: * All of the configuration information about a sub-app is stored in the ApplicationConfig object, including a bunch of stuff that used to be set with init parameters on the controller servlet. This sounds a lot like what we currently call a Schema object (which is a misleading name, I know). The relative path to the MessageBundle for the sub-app lives in the Schema. In Expresso the Schema object also defines the list of DBObjects, Jobs, and Controllers (Action) objects, so we can do things like default security, DB creation, etc. Sounds like maybe Schema extends ApplicationConfig is in the cards... * A multi-app environment still runs from a single instance of the controller servlet, but you can have multiple struts-config.xml files -- one per sub-application. One of our contributors extended ControllerServlet to simply read all xml's with the appropriate DTD in a specific directory, one per sub-app. Might this be easier than having to least each app in the web.xml? One less thing to configure? Just thinking out loud... Or does the param to the ControllerServlet also define the prefix? We do the same kind of thing with Lo4j config files - put each of them in a specific directory, then read everything that matches that doctype. Makes configuring a new app pretty quick and painless. * The sub-application that applies to a particular request is based on matching an application prefix at the beginning of the context-relative URI (similar to the way that a servlet container chooses the web app to run based on the context path prefix of the request URI. In Expresso we have a table in the DB that lists all the Schema objects, and each one has a prefix like this associated with it. It also forms a prefix for finding related JSP/HTML/doc for the sub-app, so it serves double-duty in that sense. * Like a servlet container, there is the notion of a default sub-application that is used to process requests not assigned to any sub-applicaiton. The prefix for this application is (i.e. the empty string). Great news - we're already on this path, so that's no change at all. * All of the context relative values in struts-config.xml are now application-relative instead -- in other words, the request URI equals context path + application prefix + local value. This works even for the default sub-application, because its prefix is a zero-length string. Ditto, no change here. * A known issue is that sub-apps won't work for path-mapped actions -- only extension mapped at the moment. I believe this can be fixed, but wanted to focus on getting the basics right first. Has there been any thought to extended path info as parameters? We were doing this before Expresso 4.0, but dropped it when we integrated Struts 1.0 - does make for cleaner URLs sometimes... I look forward to seeing this evolve, and helping Expresso evolve with it. Thanks for the update! Regards, Mike -- To unsubscribe, e-mail: mailto:[EMAIL PROTECTED] For additional commands, e-mail: mailto:[EMAIL PROTECTED]
RE: The BIG Check-In for Multi-App Support
On Sun, 13 Jan 2002, Michael Nash wrote: Date: Sun, 13 Jan 2002 10:44:04 -0500 From: Michael Nash [EMAIL PROTECTED] Reply-To: Struts Developers List [EMAIL PROTECTED], [EMAIL PROTECTED] To: Struts Developers List [EMAIL PROTECTED] Subject: RE: The BIG Check-In for Multi-App Support Craig: OK, I think I've got it working now -- the support for multiple Struts sub-applications in a single web-app, that is. I'm happy to hear about this, as it's one of the things we extended in Struts 1.0 when we connected it with Expresso, as the sub-app concept was important for Expresso applications, like eForum, ePoll, etc. I'd like to merge what we did with where you're going, and of course any bits of what we've done already that are useful you're welcome to as well. Just some observations on the parallels, for people using both Expresso and Struts - they're pretty close in most cases, so a merge wouldn't be a serious impedance mismatch from what I can see: * All of the configuration information about a sub-app is stored in the ApplicationConfig object, including a bunch of stuff that used to be set with init parameters on the controller servlet. This sounds a lot like what we currently call a Schema object (which is a misleading name, I know). The relative path to the MessageBundle for the sub-app lives in the Schema. In Expresso the Schema object also defines the list of DBObjects, Jobs, and Controllers (Action) objects, so we can do things like default security, DB creation, etc. Sounds like maybe Schema extends ApplicationConfig is in the cards... If I was building from scratch, knowing what we know now (how many times have we said *that* before :-), I probably would have ended up with something more like this. I left MessageResources bundles separate, though, because quite a few apps seem to look them up individually and I wanted to minimize the backwards-incompatible changes. However, having the config stuff in a separate object tree has already helped in one major respect -- adding new configuration parameters doesn't require any tweaks to the controller servlet any more. All you do is add the getter and setter to the appropriate Config bean, and voila ... * A multi-app environment still runs from a single instance of the controller servlet, but you can have multiple struts-config.xml files -- one per sub-application. One of our contributors extended ControllerServlet to simply read all xml's with the appropriate DTD in a specific directory, one per sub-app. Might this be easier than having to least each app in the web.xml? One less thing to configure? Just thinking out loud... Or does the param to the ControllerServlet also define the prefix? We do the same kind of thing with Lo4j config files - put each of them in a specific directory, then read everything that matches that doctype. Makes configuring a new app pretty quick and painless. It's certainly possible to do all the XML files in directory foo in a Servlet 2.3 environment, because you can use ServletContext.getResourcePaths() to identify them in a portable manner. In a Servlet 2.2 world, though, you have to rely on file i/o for that -- something I'd prefer to avoid since it is not guaranteed to be available everywhere. Instead, I used a trick that I've done in other environments -- the prefix for a subapp is part of the parameter name. For my example scenario, you have config (which is backwards compatible :-), config/catalog, and config/checkout. * The sub-application that applies to a particular request is based on matching an application prefix at the beginning of the context-relative URI (similar to the way that a servlet container chooses the web app to run based on the context path prefix of the request URI. In Expresso we have a table in the DB that lists all the Schema objects, and each one has a prefix like this associated with it. It also forms a prefix for finding related JSP/HTML/doc for the sub-app, so it serves double-duty in that sense. I did a subsequent checkin that lets you configure different RequestProcessor instances (and even implementation classes) for each sub-app, in case they need different customizations to the standard request processing functionality. * Like a servlet container, there is the notion of a default sub-application that is used to process requests not assigned to any sub-applicaiton. The prefix for this application is (i.e. the empty string). Great news - we're already on this path, so that's no change at all. Great minds and all ... :-) * All of the context relative values in struts-config.xml are now application-relative instead -- in other words, the request URI equals context path + application prefix + local value. This works even for the default sub-application, because its prefix is a zero-length string. Ditto, no change here. * A known issue is that sub
The BIG Check-In for Multi-App Support
OK, I think I've got it working now -- the support for multiple Struts sub-applications in a single web-app, that is. While I'm writing up some documentation for it, here's the key points that will help you experiment with it: * All of the configuration information about a sub-app is stored in the ApplicationConfig object, including a bunch of stuff that used to be set with init parameters on the controller servlet. * A multi-app environment still runs from a single instance of the controller servlet, but you can have multiple struts-config.xml files -- one per sub-application. * The sub-application that applies to a particular request is based on matching an application prefix at the beginning of the context-relative URI (similar to the way that a servlet container chooses the web app to run based on the context path prefix of the request URI. * Like a servlet container, there is the notion of a default sub-application that is used to process requests not assigned to any sub-applicaiton. The prefix for this application is (i.e. the empty string). * All of the context relative values in struts-config.xml are now application-relative instead -- in other words, the request URI equals context path + application prefix + local value. This works even for the default sub-application, because its prefix is a zero-length string. * A primary design goal is that the struts-config.xml for an existing Struts applicaiton can be used as a sub-application with no changes. Failure of this to work should be considered a bug in the current implementation, and needs to be fixed. * In addition to its other duties, the controller servlet creates two request attributes for all requests that flow through the controller: Action.APPLICATION_KEYWill contain the ApplicationConfig instance for the sub-applcation that is selected by the current request URI. Action.MESSAGES_KEY Will contain the MessageResources instance for the sub-applcation that is selected by the current request URI. * WARNING: If you want to use your existing Struts application as a sub-application, then *ALL* of the requests must flow through the controller servlet -- no direct linking to pages -- in order for the above request attributes to always be set. In a servlet 2.3 environment, we'd be able to avoid worrying about this by using a filter, but that doesn't help under servlet 2.2. * A known issue is that sub-apps won't work for path-mapped actions -- only extension mapped at the moment. I believe this can be fixed, but wanted to focus on getting the basics right first. As a quick example of the new approach, assume you have three sub-apps: main - Main menu and such (this is the default subapp) catalog - The shopping portion of a shopping site - prefix /catalog checkout - The checkout portion of a shopping site - prefix /checkout You would configure the sub-applicaitons in their own struts-config files, and tell the controller servlet about them like this: servlet servlet-nameaction/servlet-name servlet-classorg.apache.struts.action.ActionServlet/servlet-class !-- The default sub-application -- init-param param-nameconfig/param-name param-value/WEB-INF/struts-config-main.xml/param-value /init-param !-- The catalog sub-application -- init-param param-nameconfig/catalog/param-name -- Includes prefix! -- param-value/WEB-INF/struts-config-catalog.xml/param-value /init-param !-- The checkout sub-application -- init-param param-nameconfig/checkout/param-name -- Includes prefix! -- param-value/WEB-INF/struts-config-checkout.xml/param-value /init-param ... other global parameters ... /servlet In such an environment, you might have context-relative request URIs like: /index.jsp Main menu of the entire site /logon.do Log on action (default subapp) /catalog/index.jsp Main menu of the product catalog /catalog/addItem.do Add an item to the shopping cart /checkout/index.jsp Beginning of the check out area /checkout/checkVisa.do Check the entered VISA credit card number Application Development Issues: * As stated above, I tried to maximize backwards compatibility. The following points are things I know about that might impact porting of existing Struts apps into being usable in a multi-sub-app environment as a sub-application (no change should be required to continue use as the default sub-app). * Applications that are calling Action.getResources() should be modified to call Action.getResources(HttpServletRequest) instead. This allows you to pick up the message resources that are unique to this sub-application. Otherwise, the message resources for the default sub-app will be used. *