Fixing the RequestDispatcher implementation to be more web container generic 
and pluggable through a Service
------------------------------------------------------------------------------------------------------------

                 Key: PLUTO-557
                 URL: https://issues.apache.org/jira/browse/PLUTO-557
             Project: Pluto
          Issue Type: Bug
          Components: portlet container
    Affects Versions: 2.0.0
         Environment: Tomcat 5/6, Websphere 6.1
            Reporter: Ate Douma
            Assignee: Ate Douma
            Priority: Critical
             Fix For: 2.0.0


The requirements of the new portlet 2.0 specification with respect to portlet 
request dispatching is one area where complexity has grown massively. 
Especially the new support for forwarding, *even* from a RenderRequest, which 
requires the portlet container to "fake" the dispatch state as a forward while 
internally it must use an include, is very difficult to implement generically.

The current implementation as I wrote some months ago uses a solution by 
interpreting the expected dispatch state *upfront*, before doing the actual 
dispatch, and then use that state internally to present to the invoked Servlet 
(RequestDispatcherPathInfo).
This solution however now turned out to be "not good enough"...

While the Portlet 2.0 TCK is a great help of validating our container 
implementation, in certain areas it only goes about "1 inch deep".
So, while the current implementation passes the TCK, its not difficult to come 
up with practical use-cases which break the implementation flat out :(
One specific conveniently "ignored" servlet api usage in the TCK is using a 
ServletContext.getRequestDispatcher(path) from within a dispatched Servlet. 
While there are a few (minor) descriptions in JSR-286 how the dispatcher state 
should be managed and what is allowed and not, the TCK *only* tests using a 
ServletRequest.getRequestDispatcher(path)...
The real problem of using the ServletContext.getRequestDispatcher is that the 
portlet container handling will not, *and can not*, be aware of that as the 
servlet api provides no means to intercept or wrap such usage! 

Another very important limitation of the current implementation is that it 
turned out to be very Tomcat specific!
For instance, the "detection" if a dispatched request is further dispatched 
(nested) currently depends on how Tomcat deals with that.
Tomcat always "injects" another Tomcat specific RequestHandler *above* the 
current request wrapper to handle nested dispatch specific state (like merged 
query string parameters on the parameter map and include/forward specific 
request path attributes).
The current implementation checks if the getRequest() of the current request is 
changed, and if so rebuilds its internal parameterMap cache.  

However, while testing Pluto (or actually Jetspeed using Pluto) on Websphere 
6.1, this turned out to be not working at all. 
Websphere (and like Jetty I thereafter discovered) dynamically update its 
initial RequestHandler instead.

To cut a long story short: the current implementation is both broken and too 
much (Tomcat) web container specific.

However, I've been working on an alternative solution during the last week 
which is much more generic and capable of handling much more use-cases (but not 
all: that will *never* be possible because of spec limitations).

This new solution no longer tries to interpret expected dispatch state 
*upfront*, but instead *derives* this during/after a dispatch, including nested 
dispatch and ServletContext.getRequestDispatcher invocations.
This solution no longer needs the servlet url mapping from web.xml as used by 
the current implementation (only), which means that part of the OM loading can 
be dropped again and removed from the pluto container api as well!

I have tested this against both Tomcat 5/6 and Websphere 6.1 successfully, 
which includes the TCK tests and several other real usage test-cases. 

One downside of the new implementation is that it requires somewhat more 
runtime overhead, as it for instance requires comparing all (10) dispatch path 
attributes on the current request with a previously cached copy on each request 
attribute read access (for these attributes).  
However, I'm already working on a "adaptive" algorithm to automatically detect 
at runtime if a much more optimal nested dispatch detection as we used for 
Tomcat may be used too. If true, the implementation then can "switch" to using 
that detection mechanism instead.

All the above however makes clear that we're dealing with a very tricky part of 
the portlet spec which might or might not work on other web containers than has 
been tested against Tomcat/Websphere so far.
For that reason, I'm also reworking the current implementation towards a new 
container RequestDispatcherService to make it pluggable and extendable.
The RequestDispatcherService rewrite already is mostly done, the "adaptive" 
nested dispatch detection is still in the works but should be completed pretty 
soon. When both are finished, I'll replace the current broken implementation 
with this new solution ASAP.


-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to