OK, I've assigned myself the following bugzilla ticket:

  http://nagoya.apache.org/bugzilla/show_bug.cgi?id=16603

and am trying to decide how to deal with it.  I think I understand what
the reporter (cc'd above) is proposing.  What's not clear is whether we
should make any change now, or perhaps ever.  I'd like to discuss
that here before deciding.


Background:
----------

For a while now, we have supported the "forwardPattern" and "pagePattern"
properties on the ControllerConfig object.  These patterns support
certain substitutions so that you can, for example, declare that you
want your JSP pages under /WEB-INF so that they can be accessible only
via RequestDispatcher.forward() calls.

Example scenario (assume a module prefix of "/mymodule"):

  <global-forwards>
    ...
    <forward name="Main Menu" path="/mainmenu.jsp"
                   contextRelative="false"/>
    ...
  </global-forwards>

  <controller ... forwardPattern="/WEB-INF/pages$M$P" .../>

If an Action returns the "Main Menu" ActionForward (nee ForwardConfig)
object, the request procesor will ultimately call
RequestUtils.forwardURL()  to calculate the context-relative path
of "/WEB-INF/pages/mymodule/mainmenu.jsp".  If no forward pattern had been
specified, the default mechanism would have returned
"/mymodule/mainmenu.jsp" instead.

So far, so good.  Now we've got a way to "globally redirect" the URLs
within a module, without having to modify all of the individual paths in
our forward directives.

The problem pointed out by the Bugzilla ticket, though, is that we do not
respect forwardPattern universally; it is *only* used in the scenario
described above, plus in a couple of other special cases.


Other Potential Remapping Scenarios:
-----------------------------------

Scanning the code for the core Struts controller (I didn't check the Tiles
request processor, but suspect it might have similar issues), there are
several other scenarios where one might argue that the remapping through
the specified forwardPattern would make sense.  The ones I found are as
follows, numbered for reference in later discussion:

(1) <action ... forward="/foo" .../>

    Tells request processor to handle this request by performing
    a RequestDispatcher.forward() to the specified "module-relative
    path of the servlet or other resource that will process this
    request", instead of invoking an Action.  This path is not currently
    processed by any specified "forwardPattern", instead a pattern
    of "$M$P" is assumed.

(2) <action ... include="/foo" .../>

    Tells request processor to handle this request by performing
    a RequestDispatcher.include() to the specified "module-relative
    path of the servlet or other resource that will process this
    request", instead of invoking an Action.  This path is not currently
    processed by any specified "forwardPattern", instead a pattern
    of "$M$P" is assumed.

(3) <action ... input="/foo" .../>

    There are actually two subcases here, depending on the state of
    the "inputForward" property of our module's ControllerConfig:

    (3a) <controller ... inputForward="true" .../>

         The value of the "input" property is treated as the name
         of a local or global ForwardConfig, which is then processed
         through the forwardPattern remapping just like an ActionForward
         returned from an Action would be.

    (3b) <controller ... inputForward="false" .../>

         The value of the "input" property is treated as the
         "module-relative path of the action or other resource
         to which control should be returned if the form bean
         returns validation errors.  This path is not currently
         processed by any specified "forwardPattern", instead a
         pattern of "$M$P" is assumed.

    Note that 3b is the default for backwards compatibility:

(4) <action ... path="/foo" .../>

    This is the module-relative path that is used to match a
    request to a particular action.  It is not currently mapped through
    any specified "forwardPattern", instead a pattern of "$M$P" is assumed.

(5) <exception ... path="/foo" .../>

    This is the module-relative path of the resource that should
    complete this request/response if an Action throws an exception
    of the specified type.  Whether remapping occurs or not is up to
    the ExceptionHandler that is invoked; the default implementation
    constructs an ActionForward based on this path (but sets the
    contextRelative property, which looks like a bug but isn't related
    to the issue at hand here), which will get processed through the
    "forwardPattern" remapping if we fixed the contextRelative bug.

So, we currently do the remapping in case (3b), and ought to be doing it
in case (5).  But what about the other scenarios?


Analysis:
--------

The underlying issue is that we have fallen into the (bad, but that's
hindsight for you) habit of using ActionForward instances to point at
(at least) three very different kinds of things:

(a) The view tier component that should actually render
    the response (typically a JSP page)

(b) The next action to execute, if you are doing action
    chaining

(c) The "application resource" that should handle a thrown
    exception from an action (which could be a view tier
    component, an arbitrary servlet, or an action)

The original intent of "forwardPattern" was to cover case (a) only,
because it was (in theory) only the view tier components that you'd want
to redirect for (i.e. to put JSP pages under /WEB-INF, or otherwise remap
the set of view components for a particular module).  Case (b) seems like
it should NOT be mapped, for consistency with how case (4) is handled
(mapping the original request to the original action in the first place).
Case (c) should probably be remapped if it's a view component, but not if
it's an action.

But there is nothing about an ActionForward that lets you unambiguously
determine whether it points at a view component or not.  :-(


Recommendation:
--------------

If we were not imminently trying to release a 1.1 final, I would be
tempted to design and work out a strategy for dealing with this ambiguity
problem, and hash out what the right behavior should be in each case.
However, at this point in time, I'm going to suggest that we resolve this
one as LATER and put it into the "1.2 Family" camp.  We're going to need
to deal with it in a 1.2 time frame anyway, especially if we try to
implement any sort of "module configuration inheritance" mechanisms, which
are only going to make the problem worse.

In a 2.0 time frame, the lesson I draw from this is that we will want to
be very specific in defining how mapping of logical paths to physical
paths is performed, including a way to distinguish what kind of logical
path you're talking about (so that you can apply different rules for view
components and for action components, for example).

Does this sound like a plan that we (committers) can agree to?

Craig


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to