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]

Reply via email to