John, We use a simple forward suffixing technique that I came up when we started out with Struts 0.5. Forward suffixing has been very effective for reducing action mapping explosion for our reusable components. I'm not sure if this will help in your situation but definitely think it's useful to the community.
Background: We have a framework for displaying interactive maps. The framework contains a number of reusable components (pages) that can be assembled in different ways depending on the features needed. For example, the user may start out on a page containing just a map viewer. Then user might then click on a driving directions link that takes them to another page containing the same map viewer component along with an address input component and a driving directions component. We also reuse the action mappings for our HTML map viewer and our JavaScript map viewer. The map viewer has about 10 - 30 actions depending on configuration: mapInit, mapImage, redraw, click, pan, zoom, selectAtPoint, zoomToPoint, panToPoint, etc... Every time we added a new view that used the map viewer component, we had to replicate 10 - 30 actions just to change the forward for the success action. We needed a way to have multiple success and failure forwards so that we could reuse the existing action mappings. Since we were developing a framework, we needed something that was easy to configure and use. To put this in context, take a look at our demo site: http://206.144.170.252/cit-framework Sorry about the IP address URL. If it bothers you, go to our main website www.objectfx.com and navigate to Products: Product Demos: Web Application Framework Demos. Solution: We decided to add a suffix to the forward name for each view. For example: successView1, failureView1, successView2, failureView2, etc... This is accomplished by setting a forwardSuffix request parameter. This is usually done on an init action for the view. Then we added a getActionForward method to our Action subclass (I'll call it MyActionBase) that added the suffix to the forward name. All of our action classes then use this method to append the suffix to the forward name. Here are the basics needed to implement this: Sample struts-config.xml (notice that this retains all the flexibility of global forwards and chaining and for this example reduces the mappings from 12 to 3): ... <!-- ========== Global Forward Definitions ============================== --> <global-forwards> <forward name="failure" path="/error.jsp"/> <forward name="failureView2" path="/errorView2.jsp"/> </global-forwards> <!-- ========== Action Mapping Definitions ============================== --> <action-mappings> <!-- Redraw Map Request --> <action path="/redrawMap" type="com.ofx.action.redrawMapAction"> <forward name="success" path="defaultView.jsp"/> <forward name="successView1" path="/view1.jsp"/> <forward name="successView2" path="/view2.jsp"/> <forward name="successView3" path="/view3.jsp"/> </action> <!-- Select At Point and chain to the Redraw Map action --> <action path="/selectAtPoint" type="com.ofx.action.SelectAtPointAction" name="selectAtPointActionForm"> <forward name="success" path="/redrawMap.do"/> <forward name="successView1" path="/redrawMap.do"/> <forward name="successView2" path="/redrawMap.do"/> <forward name="successView3" path="/goElsewhere.jsp "/> </action> <!-- Zoom Out Request --> <action path="/zoomOut" type="com.ofx.action.zoomOutAction" name="zoomActionForm"> <forward name="success" path="/defaultView.jsp"/> <forward name="successView1" path="/view1.jsp"/> <forward name="successView2" path="/view2.jsp"/> <forward name="successView3" path="/view3.jsp"/> <forward name="failureView3" path="/errorZoomOutView3.jsp"/> </action> ... xxxAction extends MyActionBase ... public ActionForward execute( ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { try { // process the action... return getActionForward(request, mapping, "success"); // append the forwardSuffix to the forward name. } catch (MyAppException e) { return getActionForward(request, mapping, "failure"); // append the forwardSuffix to the forward name. } } ... MyActionBase extends org.apache.struts.action.Action ... /** * Gets the Struts ActionForward for this request. Takes into account * any forward suffix values that affect where this request will go. * All Web App Framework Actions should use this method to determine the * appropriate action forward. Actions that do not use this method * will not take "forward suffixes" into account, and subsequently * may forward to the wrong action. <p> * * For example, suppose you append "forwardSuffix=View1" to a given * action url, and call a Web App Framework Action. If the action completes * successfully, it will normally call this method with a forward * name of "success". This method will search the Http request for a * forward suffix, and if found, append it to the forward name. This * would result in a forward name of "successView1". The * ActionMapping is then asked for an ActionForward matching this * name, and it is returned. <p> * * This allows multiple Struts Actions to be reused by simply adding * a new forward success to the action definition in the * "struts-config.xml" file. * * @param request The Http Request that initiated the Action * @param mapping The Action Mapping of the requested Action * @param name The Action Forward name as known to the Action, * such as "success" or "failure". * @return The ActionForward based on a Action Forward name * that may have had a forward suffix appended to it, such as * "successView1" instead of "success" */ public ActionForward getActionForward(HttpServletRequest request, ActionMapping mapping, String name) { // first look for a forward suffix parameter on the request String suffix = request.getParameter("forwardSuffix"); if (suffix == null) { try { // look for a previous forward suffix stored in the session suffix = (String)request.getSession().getAttribute("forwardSuffix"); } catch (Exception e) { log.error("MyActionBase.getActionForward an exception has occured: ", e); } } String forwardName = name; if (suffix != null) { forwardName = forwardName + suffix; } if (log.isDebugEnabled()) { log.debug("MyActionBase.getActionForward for action: " + mapping.getPath() + " forwardName: " + forwardName); } // Although not publicly known or advertised, the logic below allows action // forwards to be dynamically overridden. For example, if you specified a url // like "myAction.do?success=nextAction.do", you could override // the default behavior for succes as defined in the struts action mapping. String forward = request.getParameter(forwardName); if (forward == null) { return mapping.findForward(forwardName); } else { return new ActionForward(forward); } } ... I hope this is useful. Thanks, Nathan. Nathan A. Niesen Application Developer ObjectFX Corporation 10 Second St NE, Suite 400 Minneapolis, MN 55413 612-312-2002 x2633 mailto:[EMAIL PROTECTED] www.objectfx.com -----Original Message----- From: Hohlen, John C [mailto:[EMAIL PROTECTED] Sent: Wednesday, March 26, 2003 8:04 PM To: Struts Users Mailing List; Struts-User (E-mail); Hohlen, John C; Niesen, Nathan Subject: RE: Configuring Tiles + Validation + Modules Nathan, For now, I think we're going to just use the multiple config file options (new in B3). I was able to bust up our ONE struts-config.xml file and get this working in just 1/2 day (it would have been less if I wouldn't have introduced some XML syntax errors in my new config files). In addition, we'll probably bust up our application resource file and merge them back together during our ANT build process. We have a team of about 12 developers, so these files have become a real bottleneck. This approach seems to achieve many of the same benefits as modules, without all the additional technical headaches (although you need to guard against duplicate action mappings, form bean definitions, keys/values across all the collection of files). JOHN -----Original Message----- From: Niesen, Nathan [mailto:[EMAIL PROTECTED] Sent: Wed 3/26/2003 4:43 PM [EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]> To: Struts-User (E-mail) Cc: Subject: RE: Configuring Tiles + Validation + Modules I basically have the same questions. I've been searching the user docs and mailing lists trying to get a handle on what modules were intended to do, what modules can and can't do, and how I can use modules to improve my application framework. It appears to me that the modules feature opened up a whole can-o-design-worms and they're still wiggling. I can't find anything that clearly defines intended usage of modules or the limitations of modules; especially in regards to using "resources" outside of a modules sub-directory. In addition to John's questions, I have the following question: 1) How can I use tiles/templates to assemble a page in one module from reusable "components/pages" in one or more other modules? For example: I have pages in modules B, C, and D, that all want to pull in a menu page from my default module as well as a reusable page from module A. Other issues with modules: 1) Not all tags (html:img in particular) use the pagePattern or forwardPattern attributes from the controller. If I want to use an image in my header.jsp, the image file has to be physically located in each module or I get a broken link. 2) The pagePattern and forwardPattern are defined on the controller which means all tag or forward URLs for the module will be mapped to the same context relative URL. I think it would be more flexible if you simply specified the pattern as part of the URL attribute for the tag or forward. For example: <html:img alt="get an image from the default module" page="$P/header.gif"/> and <html:img alt="get an image from the current module" page="$M$P/module.gif"/> 3) The examples don't effectively demonstrate the effects that the contextRelative, inputForward, pagePattern, and forwardPattern attributes have on the page, forward, action, and href attributes. 4) The examples only show how to switch from one self-contained module to another. They don't demonstrate how to combine resources/pages from multiple modules into a single page via either includes or tiles/templates. Thanks, Nathan. -----Original Message----- From: Hohlen, John C [mailto:[EMAIL PROTECTED] <mailto:[EMAIL PROTECTED]> ] Sent: Wednesday, March 26, 2003 8:20 AM To: Struts-User (E-mail) Subject: Configuring Tiles + Validation + Modules I'm looking for some help on how to configure the Tiles and Validation Plug-Ins. A lot of the good books (Struts In Action, Programming Jakarta Struts, etc.) and replies to the mailing list address these topics independently, but not collectively. In addition, I took a look at James Holmes "Switching Modules" example, but that focuses on the different ways to switch b/t modules, not on how to configure Modules with Tiles and the Validation frameworks. For discussion purposes, let's assume I have following 3 modules (default, modA, modB). Here are my questions: 1) If I have a form bean definition used by all 3 modules, does it need to be defined in each of the 3 struts-config files, or can I just declare it in the default struts-config? 2) Does each modules' struts-config file need the following declaration to use the Validation framework, or can I simply declare this once in the config file for the default module? <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> <set-property property="pathnames" value="/WEB-INF/validator-rules.xml, /WEB-INF/validation.xml"/> </plug-in> 3) For Tile Definition config files, can all of these just be declared in the default struts-config, or should they be declared in the module struts-config they correspond to (assuming you've divided your Tile definitions by module)? For example: <plug-in className="org.apache.struts.tiles.TilesPlugin" > <set-property property="definitions-config" value="/WEB-INF/tiles-defs-default.xml, /WEB-INF/tiles-defs-modA.xml, /WEB-INF/tiles-defs-modB.xml"/> </plug-in> 4) Can I use the default module's application resource file for text common across modules? Therefore, preventing me from having to duplicate entries across modules. If so, this means Struts always looks in the particular module's application resource first, then the default module. But this doesn't apply for form bean definitions or action mappings, correct? 5) Is the following an acceptable way to configure the application resource files: --- struts-config.xml (default) ------- <message-resources parameter="Messages" null="false"/> --- struts-config-modA.xml (default) ------- <message-resources parameter="Messages-modA" null="false"/> --- struts-config-modB.xml (default) ------- <message-resources parameter="Messages-modB" null="false"/> Thanks in advance for your help, JOHN --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED] --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]

