You are viewing a plain text version of this content. The canonical link for it is here.
Posted to pluto-scm@portals.apache.org by ms...@apache.org on 2016/04/08 15:40:35 UTC

[23/34] portals-pluto git commit: Refactoring to make sure that the portal listener is the last listener to execute. Added code to re-initialize the portlet request context properly during the async dispatch.

Refactoring to make sure that the portal listener is the last listener to
execute. Added  code to re-initialize the portlet request context properly
during the async dispatch.


Project: http://git-wip-us.apache.org/repos/asf/portals-pluto/repo
Commit: http://git-wip-us.apache.org/repos/asf/portals-pluto/commit/78dee92d
Tree: http://git-wip-us.apache.org/repos/asf/portals-pluto/tree/78dee92d
Diff: http://git-wip-us.apache.org/repos/asf/portals-pluto/diff/78dee92d

Branch: refs/heads/V3Prototype
Commit: 78dee92d5b47c84c854db7c1aba19d0e12fd1f7f
Parents: 75119d2
Author: Scott Nicklous <ms...@apache.org>
Authored: Fri Apr 1 22:11:07 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Fri Apr 1 22:11:07 2016 +0200

----------------------------------------------------------------------
 .../portals/samples/AsyncPortletResource.java   |  15 +-
 .../pluto/container/PortletAsyncContext.java    |  14 +
 .../PortletResourceRequestContext.java          |   7 +
 .../pluto/container/driver/PortletServlet3.java |  64 ++-
 .../bean/processor/PortletInvoker.java          |  19 +
 .../impl/PortletAsyncRequestWrapper.java        |  20 +-
 .../container/impl/ResourceRequestImpl.java     |   7 -
 .../container/PortletAsyncContextImpl.java      | 181 ++++++++
 .../PortletResourceRequestContextImpl.java      | 412 ++++++++++---------
 9 files changed, 528 insertions(+), 211 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
index 0868f58..59cc599 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -46,7 +46,6 @@ import org.apache.portals.samples.AsyncDialogBean.OutputType;
  */
 public class AsyncPortletResource {
    private static final Logger LOGGER = Logger.getLogger(AsyncPortletResource.class.getName());
-   private static final boolean isDebug = LOGGER.isLoggable(Level.FINE);
    private static final boolean isTrace = LOGGER.isLoggable(Level.FINEST);
    
    private final static String JSP         = "/WEB-INF/jsp/asyncOutput.jsp";
@@ -106,12 +105,12 @@ public class AsyncPortletResource {
                str.append(", Servlet patch: ").append(hreq.getServletPath());
                LOGGER.fine(str.toString());
                hreq.setAttribute(ATTRIB_AUTO, new Boolean(true));
-               ctx.dispatch(hreq.getServletContext(), hreq.getServletPath());
+               ctx.dispatch();
                break;
             case DISPATCH:
                LOGGER.fine("Dispatching to JSP.");
                hreq.setAttribute(ATTRIB_TITLE, "Thread dispatching to JSP");
-               ctx.dispatch(hreq.getServletContext(), JSP);
+               ctx.dispatch(JSP);
                break;
             case FWD:
                LOGGER.fine("Doing request dispatcher forward to JSP: " + JSP);
@@ -178,8 +177,7 @@ public class AsyncPortletResource {
          
          PortletRequestDispatcher rd;
 
-         HttpServletRequest hreq = (HttpServletRequest) req.getAttribute("javax.portlet.debug.ServletRequest");
-         trace(hreq, "Resource method: ");
+         trace(req, "Resource method: ");
          
          // HttpServletRequest hreq = (HttpServletRequest) ctx.getRequest();
          PortletConfig config = (PortletConfig) req.getAttribute("javax.portlet.config");
@@ -192,7 +190,7 @@ public class AsyncPortletResource {
          case DISPATCH:
             LOGGER.fine("Dispatching to JSP.");
             req.setAttribute(ATTRIB_TITLE, "Resource Method dispatching to JSP");
-            ctx.dispatch(hreq.getServletContext(), JSP);
+            ctx.dispatch(JSP);
             break;
          case FWD:
             LOGGER.fine("Doing request dispatcher forward to JSP.");
@@ -243,6 +241,11 @@ public class AsyncPortletResource {
       }
    }
    
+   public static void trace(ResourceRequest req, String src) {
+      HttpServletRequest hreq = (HttpServletRequest) req.getAttribute("javax.portlet.debug.ServletRequest");
+      trace(hreq, src);
+   }
+   
    public static void trace(HttpServletRequest hreq, String src) {
       if (isTrace) {
          List<String> attrNames = Collections.list(hreq.getAttributeNames());

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
new file mode 100644
index 0000000..1567767
--- /dev/null
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletAsyncContext.java
@@ -0,0 +1,14 @@
+package org.apache.pluto.container;
+
+import javax.servlet.AsyncContext;
+
+public interface PortletAsyncContext extends AsyncContext {
+
+   void requestComplete(PortletResourceRequestContext prctx);
+
+   /**
+    * @param actx the async context to set
+    */
+   void setWrapped(AsyncContext actx);
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResourceRequestContext.java
----------------------------------------------------------------------
diff --git a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResourceRequestContext.java b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResourceRequestContext.java
index f8d50f9..20adad4 100644
--- a/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResourceRequestContext.java
+++ b/pluto-container-api/src/main/java/org/apache/pluto/container/PortletResourceRequestContext.java
@@ -23,6 +23,9 @@ import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
 import javax.servlet.AsyncContext;
 import javax.servlet.DispatcherType;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpSession;
 
 /**
  * @version $Id$
@@ -68,4 +71,8 @@ public interface PortletResourceRequestContext extends PortletRequestContext
     boolean isAsyncSupported();
     AsyncContext getAsyncContext() throws IllegalStateException;
     DispatcherType getDispatcherType();
+    HttpSession getSession();
+    AsyncContext startAsync();
+    AsyncContext startAsync(ServletRequest request, ServletResponse response);
+    PortletAsyncContext getPortletAsyncContext();
 }

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
----------------------------------------------------------------------
diff --git a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
index 7aed69d..b936626 100644
--- a/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
+++ b/pluto-container-driver-api/src/main/java/org/apache/pluto/container/driver/PortletServlet3.java
@@ -39,6 +39,10 @@ import javax.servlet.DispatcherType;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletRequestWrapper;
+import javax.servlet.ServletResponse;
+import javax.servlet.ServletResponseWrapper;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -52,6 +56,7 @@ import org.apache.pluto.container.PortletResponseContext;
 import org.apache.pluto.container.PortletWindow;
 import org.apache.pluto.container.bean.processor.AnnotatedConfigBean;
 import org.apache.pluto.container.bean.processor.PortletInvoker;
+import org.apache.pluto.container.impl.PortletAsyncRequestWrapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -272,10 +277,67 @@ public class PortletServlet3 extends HttpServlet {
       final FilterManager filterManager = 
             (FilterManager) request.getAttribute(PortletInvokerService.FILTER_MANAGER);
 
-      if (request.getDispatcherType() != DispatcherType.ASYNC) {
+      if (LOG.isTraceEnabled()) {
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("\nRequest wrapper stack: ");
+         ServletRequest wreq = request;
+         ServletRequest tstreq = requestContext.getServletRequest();
+         int n = 1;
+         while (wreq instanceof ServletRequestWrapper) {
+            txt.append("\nLevel ").append(n++).append(": ").append(wreq.getClass().getCanonicalName());
+            txt.append(", dispatch type: ").append(wreq.getDispatcherType());
+            txt.append(", equal to req context req: ").append(wreq == tstreq);
+            wreq = ((ServletRequestWrapper) wreq).getRequest();
+         }
+         txt.append("\nLevel ").append(n++).append(": ").append(wreq.getClass().getCanonicalName());
+         txt.append(", dispatch type: ").append(wreq.getDispatcherType());
+         txt.append(", equal to req context req: ").append(wreq == tstreq);
+
+         txt.append("\n\nResponse wrapper stack: ");
+         ServletResponse wresp = response;
+         ServletResponse tstresp = requestContext.getServletResponse();
+         n = 1;
+         while (wresp instanceof ServletResponseWrapper) {
+            txt.append("\nLevel ").append(n++).append(": ").append(wresp.getClass().getCanonicalName());
+            txt.append(", equal to req context resp: ").append(wresp == tstresp);
+            wresp = ((ServletResponseWrapper) wresp).getResponse();
+         }
+         txt.append("\nLevel ").append(n++).append(": ").append(wresp.getClass().getCanonicalName());
+         txt.append(", equal to req context resp: ").append(wresp == tstresp);
+         LOG.debug(txt.toString());
+      }
+      
+      if (request.getDispatcherType() == DispatcherType.ASYNC) {
+         
+         // have to reinitialize the request context with the request under our wrapper.
+         
+         ServletRequest wreq = request;
+         while ((wreq instanceof ServletRequestWrapper) &&
+               !(wreq instanceof PortletAsyncRequestWrapper) ) {
+            wreq = ((ServletRequestWrapper) wreq).getRequest();
+         }
+         
+         
+         if (wreq instanceof PortletAsyncRequestWrapper) {
+            
+            HttpServletRequest hreq = (HttpServletRequest) ((PortletAsyncRequestWrapper) wreq).getRequest();
+            HttpServletResponse hresp = requestContext.getServletResponse();
+            
+            LOG.debug("Extracted wrapped request. Dispatch type: " + hreq.getDispatcherType());
+
+            requestContext.init(portletConfig, getServletContext(), hreq, hresp);
+            responseContext.init(hreq, hresp);
+            
+         } else {
+            LOG.debug("Couldn't find the portlet async wrapper.");
+         }
+         
+      } else {
+         
          // the contexts are already initialized if this is part of a resource request async sequence
          requestContext.init(portletConfig, getServletContext(), request, response);
          responseContext.init(request, response);
+      
       }
 
       PortletWindow window = requestContext.getPortletWindow();

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletInvoker.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletInvoker.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletInvoker.java
index fd090da..982cee5 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletInvoker.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletInvoker.java
@@ -51,7 +51,10 @@ import javax.portlet.annotations.ServeResourceMethod;
 import javax.servlet.DispatcherType;
 import javax.xml.namespace.QName;
 
+import org.apache.pluto.container.PortletAsyncContext;
 import org.apache.pluto.container.PortletInvokerService;
+import org.apache.pluto.container.PortletResourceRequestContext;
+import org.apache.pluto.container.impl.PortletAsyncRequestWrapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -275,6 +278,7 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
             LOG.warn(txt.toString());
             return;
          }
+         LOG.debug("Processing async dispatch. method: " + meth.toString());
          meths.add(meth);
       } else {
          meths = getMethods(mi);
@@ -331,6 +335,21 @@ public class PortletInvoker implements Portlet, ResourceServingPortlet, EventPor
                
                LOG.debug("Async processing was started during method: " + meth.toString());
                req.setAttribute(PortletInvokerService.ASYNC_METHOD, meth);
+               
+               PortletResourceRequestContext reqctx = (PortletResourceRequestContext) req.getAttribute(PortletInvokerService.REQUEST_CONTEXT);
+               if (reqctx != null) {
+                  PortletAsyncContext pac = reqctx.getPortletAsyncContext();
+                  if (pac != null) {
+                     pac.requestComplete(reqctx);
+                  } else {
+                     LOG.warn("Couldn't get portlet async context.");
+                  }
+               } else {
+                  LOG.warn("Couldn't get request context.");
+               }
+            
+               
+               
                break;
                
             } else {

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletAsyncRequestWrapper.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletAsyncRequestWrapper.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletAsyncRequestWrapper.java
index aec96ef..353b49f 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletAsyncRequestWrapper.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/PortletAsyncRequestWrapper.java
@@ -24,16 +24,12 @@ import java.util.Collections;
 import java.util.Enumeration;
 
 import javax.portlet.ResourceRequest;
-import javax.portlet.ResourceResponse;
 import javax.servlet.AsyncContext;
-import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
 
 import org.apache.pluto.container.NamespaceMapper;
-import org.apache.pluto.container.PortletRequestContext;
 import org.apache.pluto.container.PortletResourceRequestContext;
 import org.apache.pluto.container.PortletWindowID;
 import org.slf4j.Logger;
@@ -52,13 +48,14 @@ public class PortletAsyncRequestWrapper extends HttpServletPortletRequestWrapper
    private static final boolean isTrace = LOG.isTraceEnabled();
    
    
+   @SuppressWarnings("unused")
    private final ResourceRequest preq;
    private final PortletResourceRequestContext reqctx;
    private final NamespaceMapper mapper;
    private final PortletWindowID winId;
 
    public PortletAsyncRequestWrapper(HttpServletRequest hreq, ResourceRequest preq, PortletResourceRequestContext reqctx) {
-      super(hreq, reqctx.getServletContext(), null, preq, true, false);
+      super(hreq, reqctx.getServletContext(), reqctx.getSession(), preq, true, false);
       this.preq = preq;
       this.reqctx = reqctx;
       this.mapper = reqctx.getContainer().getContainerServices().getNamespaceMapper();
@@ -213,22 +210,27 @@ public class PortletAsyncRequestWrapper extends HttpServletPortletRequestWrapper
 // 
    @Override
    public AsyncContext startAsync() throws IllegalStateException {
-      return getRequest().startAsync();
+      return reqctx.startAsync();
    }
 
    @Override
    public AsyncContext startAsync(ServletRequest request, ServletResponse response) throws IllegalStateException {
-      return getRequest().startAsync(request, response);
+      return reqctx.startAsync(request, response);
    }
 
    @Override
    public boolean isAsyncStarted() {
-      return getRequest().isAsyncStarted();
+      return reqctx.isAsyncStarted();
    }
 
    @Override
    public boolean isAsyncSupported() {
-      return getRequest().isAsyncSupported();
+      return reqctx.isAsyncSupported();
+   }
+   
+   @Override
+   public AsyncContext getAsyncContext() {
+      return reqctx.getAsyncContext();
    }
 
 

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/pluto-container/src/main/java/org/apache/pluto/container/impl/ResourceRequestImpl.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/impl/ResourceRequestImpl.java b/pluto-container/src/main/java/org/apache/pluto/container/impl/ResourceRequestImpl.java
index 721c5e8..fdd2145 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/impl/ResourceRequestImpl.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/impl/ResourceRequestImpl.java
@@ -20,20 +20,13 @@ import java.util.Enumeration;
 import java.util.Map;
 
 import javax.portlet.CacheControl;
-import javax.portlet.PortletConfig;
 import javax.portlet.PortletRequest;
 import javax.portlet.ResourceParameters;
 import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
 import javax.servlet.AsyncContext;
 import javax.servlet.DispatcherType;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
 
-import org.apache.pluto.container.PortletInvokerService;
-import org.apache.pluto.container.PortletRequestContext;
 import org.apache.pluto.container.PortletResourceRequestContext;
 import org.apache.pluto.container.PortletResourceResponseContext;
 import org.slf4j.Logger;

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
new file mode 100644
index 0000000..2e0288d
--- /dev/null
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextImpl.java
@@ -0,0 +1,181 @@
+/*  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+
+package org.apache.pluto.driver.services.container;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.AsyncListener;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.pluto.container.PortletAsyncContext;
+import org.apache.pluto.container.PortletResourceRequestContext;
+
+/**
+ * Wrapper class for the AsyncContext obtained from the servlet container. Provides
+ * a couple of work-arounds for Tomcat async bugs as well as portlet-specific listener
+ * support.
+ * 
+ * @author Scott Nicklous
+ *
+ */
+public class PortletAsyncContextImpl implements PortletAsyncContext {
+
+   private AsyncContext actx;
+   private final HttpServletRequest hreq;
+
+   public PortletAsyncContextImpl(AsyncContext actx, HttpServletRequest hreq) {
+      this.actx = actx;
+      this.hreq = hreq;
+   }
+
+   /* (non-Javadoc)
+    * @see org.apache.pluto.driver.services.container.PortletAsyncContext#requestComplete(org.apache.pluto.container.PortletResourceRequestContext)
+    */
+   @Override
+   public void requestComplete(PortletResourceRequestContext prctx) {
+
+      // get the original container req & resp to pass to listener for resource releasing
+
+      HttpServletRequest creq = prctx.getContainerRequest();
+      HttpServletResponse cresp = prctx.getContainerResponse();
+
+      PortletAsyncListener pal = new PortletAsyncListener();
+      actx.addListener(pal, creq, cresp);
+   }
+   
+   /* (non-Javadoc)
+    * @see org.apache.pluto.driver.services.container.PortletAsyncContext#setWrapped(javax.servlet.AsyncContext)
+    */
+   @Override
+   public void setWrapped(AsyncContext actx) {
+      this.actx = actx;
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#addListener(javax.servlet.AsyncListener)
+    */
+   @Override
+   public void addListener(AsyncListener l) {
+      actx.addListener(l);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#addListener(javax.servlet.AsyncListener, javax.servlet.ServletRequest, javax.servlet.ServletResponse)
+    */
+   @Override
+   public void addListener(AsyncListener l, ServletRequest req, ServletResponse resp) {
+      actx.addListener(l, req, resp);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#complete()
+    */
+   @Override
+   public void complete() {
+      actx.complete();
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#createListener(java.lang.Class)
+    */
+   @Override
+   public <T extends AsyncListener> T createListener(Class<T> cls) throws ServletException {
+      return actx.createListener(cls);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#dispatch()
+    */
+   @Override
+   public void dispatch() {
+      // workaround for Tomcat bug 59213
+      actx.dispatch(hreq.getServletContext(), hreq.getServletPath());
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#dispatch(java.lang.String)
+    */
+   @Override
+   public void dispatch(String path) {
+      // workaround for Tomcat bug 59213
+      actx.dispatch(hreq.getServletContext(), path);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#dispatch(javax.servlet.ServletContext, java.lang.String)
+    */
+   @Override
+   public void dispatch(ServletContext sctx, String path) {
+      actx.dispatch(sctx, path);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#getRequest()
+    */
+   @Override
+   public ServletRequest getRequest() {
+      return actx.getRequest();
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#getResponse()
+    */
+   @Override
+   public ServletResponse getResponse() {
+      return actx.getResponse();
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#getTimeout()
+    */
+   @Override
+   public long getTimeout() {
+      return actx.getTimeout();
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#hasOriginalRequestAndResponse()
+    */
+   @Override
+   public boolean hasOriginalRequestAndResponse() {
+      return actx.hasOriginalRequestAndResponse();
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#setTimeout(long)
+    */
+   @Override
+   public void setTimeout(long time) {
+      actx.setTimeout(time);
+   }
+
+   /* (non-Javadoc)
+    * @see javax.servlet.AsyncContext#start(java.lang.Runnable)
+    */
+   @Override
+   public void start(Runnable run) {
+      actx.start(run);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/78dee92d/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceRequestContextImpl.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceRequestContextImpl.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceRequestContextImpl.java
index 35909c0..cadc36f 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceRequestContextImpl.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletResourceRequestContextImpl.java
@@ -26,10 +26,13 @@ import javax.portlet.ResourceRequest;
 import javax.portlet.ResourceResponse;
 import javax.servlet.AsyncContext;
 import javax.servlet.DispatcherType;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import javax.servlet.http.HttpSession;
 
+import org.apache.pluto.container.PortletAsyncContext;
 import org.apache.pluto.container.PortletContainer;
 import org.apache.pluto.container.PortletInvokerService;
 import org.apache.pluto.container.PortletResourceRequestContext;
@@ -43,62 +46,61 @@ import org.slf4j.LoggerFactory;
 
 /**
  * @version $Id$
- *
+ * 
  */
 public class PortletResourceRequestContextImpl extends PortletRequestContextImpl implements
-                PortletResourceRequestContext
-{
-   
+      PortletResourceRequestContext {
+
    /** Logger. */
-   private static final Logger LOG = LoggerFactory.getLogger(PortletResourceRequestContextImpl.class);
+   private static final Logger  LOG     = LoggerFactory.getLogger(PortletResourceRequestContextImpl.class);
    @SuppressWarnings("unused")
    private static final boolean isDebug = LOG.isDebugEnabled();
    private static final boolean isTrace = LOG.isTraceEnabled();
+
+   private String               pageState;
+   private ResourceResponse     response;
+   private PortletAsyncContextImpl  actx;
+
+   public PortletResourceRequestContextImpl(PortletContainer container, HttpServletRequest containerRequest,
+         HttpServletResponse containerResponse, PortletWindow window, String pageState) {
+      // if pageState != null, we're dealing with a Partial Action request, so
+      // the servlet parameters are not to be used. Otherwise, resource params could be
+      // passed as servlet parameters.
+      super(container, containerRequest, containerResponse, window, (pageState == null));
+      this.pageState = pageState;
+   }
    
-   
-   private String pageState;
-   private ResourceResponse response;
-   private AsyncContext actx = null;
-   
-   
-    public PortletResourceRequestContextImpl(PortletContainer container, HttpServletRequest containerRequest,
-                                             HttpServletResponse containerResponse, PortletWindow window,
-                                             String pageState)
-    {
-       // if pageState != null, we're dealing with a Partial Action request, so 
-       // the servlet parameters are not to be used. Otherwise, resource params could be
-       // passed as servlet parameters.
-        super(container, containerRequest, containerResponse, window, (pageState==null));
-        this.pageState = pageState;
-    }
-
-    @Override
-    public String getCacheability()
-    {
-        return getPortalURL().getCacheability();
-    }
-
-    @Override
-    public Map<String, String[]> getPrivateRenderParameterMap()
-    {
-        return paramFactory.getResourceRenderParameterMap(window.getId().getStringId());
-    }
-
-    @Override
-    public String getResourceID()
-    {
-        return getPortalURL().getResourceID();
-    }
-
-   /* (non-Javadoc)
+   @Override
+   public PortletAsyncContext getPortletAsyncContext() {
+      return actx;
+   }
+
+   @Override
+   public String getCacheability() {
+      return getPortalURL().getCacheability();
+   }
+
+   @Override
+   public Map<String, String[]> getPrivateRenderParameterMap() {
+      return paramFactory.getResourceRenderParameterMap(window.getId().getStringId());
+   }
+
+   @Override
+   public String getResourceID() {
+      return getPortalURL().getResourceID();
+   }
+
+   /*
+    * (non-Javadoc)
+    * 
     * @see org.apache.pluto.container.PortletResourceRequestContext#getPageState()
     */
-    @Override
+   @Override
    public String getPageState() {
       return pageState;
    }
 
-    @Override
+   @Override
    public ResourceParameters getResourceParameters() {
       return new ResourceParametersImpl(urlProvider, windowId);
    }
@@ -106,159 +108,193 @@ public class PortletResourceRequestContextImpl extends PortletRequestContextImpl
    /**
     * @return the response
     */
-    @Override
+   @Override
    public ResourceResponse getResponse() {
       return response;
    }
 
    /**
-    * @param response the response to set
+    * @param response
+    *           the response to set
     */
-    @Override
+   @Override
    public void setResponse(ResourceResponse response) {
       this.response = response;
    }
 
-    @Override
-    public AsyncContext startAsync(ResourceRequest request) throws IllegalStateException {
-       return startAsync(request, response);
-    }
-
-    @Override
-    public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
-       
-       HttpServletRequest hreq = getServletRequest();
-       HttpServletResponse hresp = getServletResponse();
-//       ServletContext ctx = getServletContext();
-//       HttpSession sess = getSession();
-       PortletConfig cfg = getPortletConfig(); 
-       
-       if (isTrace) {
-          List<String> attrNames = Collections.list(hreq.getAttributeNames());
-          StringBuilder txt = new StringBuilder(128);
-          txt.append("Start async before:");
-          txt.append("\nAttribute names: ").append(attrNames);
-          txt.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
-          txt.append("\nasync_context_path:      ").append((String) hreq.getAttribute("javax.servlet.async.context_path"));
-          txt.append("\nasync_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.async.servlet_path"));
-          txt.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
-          txt.append("\nasync_query_string:      ").append((String) hreq.getAttribute("javax.servlet.async.query_string"));
-          txt.append("\nforward_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.forward.request_uri"));
-          txt.append("\nforward_context_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.context_path"));
-          txt.append("\nforward_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
-          txt.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
-          txt.append("\nforward_query_string:      ").append((String) hreq.getAttribute("javax.servlet.forward.query_string"));
-          txt.append("\ninclude_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.include.request_uri"));
-          txt.append("\ninclude_context_path:      ").append((String) hreq.getAttribute("javax.servlet.include.context_path"));
-          txt.append("\ninclude_servlet_path:      ").append((String) hreq.getAttribute("javax.servlet.include.servlet_path"));
-          txt.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
-          txt.append("\ninclude_query_string:      ").append((String) hreq.getAttribute("javax.servlet.include.query_string"));
-          txt.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
-          txt.append("\nmethod_context_path:      ").append(hreq.getContextPath());
-          txt.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
-          txt.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
-          txt.append("\nmethod_query_string:      ").append(hreq.getQueryString());
-          LOG.debug(txt.toString());
-       }
-
-
-       // Set portlet-scoped attributes directly on resource request
-       
-       request.setAttribute(PortletInvokerService.PORTLET_CONFIG, cfg);
-       request.setAttribute(PortletInvokerService.PORTLET_REQUEST, request);
-       request.setAttribute(PortletInvokerService.PORTLET_RESPONSE, response);
-
-       // Wrap http req & response. 
-       
-       HttpServletRequest wreq = new PortletAsyncRequestWrapper(hreq, request, this);
-//       HttpServletRequest wreq = new HttpServletPortletRequestWrapper(hreq, ctx, sess, request, true, false);
-       HttpServletResponse wresp = new HttpServletPortletResponseWrapper(hresp, request, response, false);
-
-       // get the original container req & resp to pass to listener for resource releasing
-
-       HttpServletRequest creq = getContainerRequest();     
-       HttpServletResponse cresp = getContainerResponse();
-
-       // Start async, add listener to release resources upon async complete only once.
-       
-       if (actx == null) {
-          actx = hreq.startAsync(wreq, wresp);
-//          actx = hreq.startAsync(hreq, hresp);
-          PortletAsyncListener pal = new PortletAsyncListener();
-          actx.addListener(pal, creq, cresp);
-       } else {
-//          actx = hreq.startAsync(hreq, hresp);
-          actx = hreq.startAsync(wreq, wresp);
-       }
-
-       
-       if (isTrace) {
-          List<String> attrNames = Collections.list(hreq.getAttributeNames());
-          StringBuilder txt = new StringBuilder(128);
-          txt.append("Start async after (wreq):");
-          txt.append("\nAttribute names: ").append(attrNames);
-          txt.append("\nasync_request_uri:      ").append((String) wreq.getAttribute("javax.servlet.async.request_uri"));
-          txt.append("\nasync_context_path:      ").append((String) wreq.getAttribute("javax.servlet.async.context_path"));
-          txt.append("\nasync_servlet_path:      ").append((String) wreq.getAttribute("javax.servlet.async.servlet_path"));
-          txt.append("\nasync_path_info:      ").append((String) wreq.getAttribute("javax.servlet.async.path_info"));
-          txt.append("\nasync_query_string:      ").append((String) wreq.getAttribute("javax.servlet.async.query_string"));
-          txt.append("\nforward_request_uri:      ").append((String) wreq.getAttribute("javax.servlet.forward.request_uri"));
-          txt.append("\nforward_context_path:      ").append((String) wreq.getAttribute("javax.servlet.forward.context_path"));
-          txt.append("\nforward_servlet_path:      ").append((String) wreq.getAttribute("javax.servlet.forward.servlet_path"));
-          txt.append("\nforward_path_info:      ").append((String) wreq.getAttribute("javax.servlet.forward.path_info"));
-          txt.append("\nforward_query_string:      ").append((String) wreq.getAttribute("javax.servlet.forward.query_string"));
-          txt.append("\ninclude_request_uri:      ").append((String) wreq.getAttribute("javax.servlet.include.request_uri"));
-          txt.append("\ninclude_context_path:      ").append((String) wreq.getAttribute("javax.servlet.include.context_path"));
-          txt.append("\ninclude_servlet_path:      ").append((String) wreq.getAttribute("javax.servlet.include.servlet_path"));
-          txt.append("\ninclude_path_info:      ").append((String) wreq.getAttribute("javax.servlet.include.path_info"));
-          txt.append("\ninclude_query_string:      ").append((String) wreq.getAttribute("javax.servlet.include.query_string"));
-          txt.append("\nmethod_request_uri:      ").append(wreq.getRequestURI());
-          txt.append("\nmethod_context_path:      ").append(wreq.getContextPath());
-          txt.append("\nmethod_servlet_path:      ").append(wreq.getServletPath());
-          txt.append("\nmethod_path_info:      ").append(wreq.getPathInfo());
-          txt.append("\nmethod_query_string:      ").append(wreq.getQueryString());
-          LOG.debug(txt.toString());
-       }
-
-       return actx;
-    }
-
-    @Override
-    public boolean isAsyncStarted() {
-       return getServletRequest().isAsyncStarted();
-    }
-
-    @Override
-    public boolean isAsyncSupported() {
-       return getServletRequest().isAsyncSupported();
-    }
-
-    @Override
-    public AsyncContext getAsyncContext() {
-       return getServletRequest().getAsyncContext();
-    }
-
-    @Override
-    public DispatcherType getDispatcherType() {
-       return getServletRequest().getDispatcherType();
-    }
-
-    // For use within the wrapper. 
-    // PLT.10.4.3. Proxied session is created and passed if 
-    // javax.portlet.servletDefaultSessionScope == PORTLET_SCOPE
-    @SuppressWarnings("unused")
-   private HttpSession getSession() {
-       HttpSession sess = null;
-
-       PortletConfig portletConfig = getPortletConfig();
-       Map<String, String[]> containerRuntimeOptions = portletConfig.getContainerRuntimeOptions();
-       String[] values = containerRuntimeOptions.get("javax.portlet.servletDefaultSessionScope");
-
-       if ((values != null) && (values.length > 0) && "PORTLET_SCOPE".equals(values[0])) {
-          String portletWindowId = getPortletWindow().getId().getStringId();
-          sess = ServletPortletSessionProxy.createProxy(getServletRequest(), portletWindowId);
-       }
-
-       return sess;
-    }
+   @Override
+   public AsyncContext startAsync(ResourceRequest request) throws IllegalStateException {
+      return startAsync(request, response);
+   }
+
+   @Override
+   public AsyncContext startAsync(ResourceRequest request, ResourceResponse response) throws IllegalStateException {
+
+      HttpServletRequest hreq = getServletRequest();
+      HttpServletResponse hresp = getServletResponse();
+      PortletConfig cfg = getPortletConfig();
+
+      if (isTrace) {
+         List<String> attrNames = Collections.list(hreq.getAttributeNames());
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("Start async before:");
+         txt.append("\nAttribute names: ").append(attrNames);
+         txt.append("\nasync_request_uri:      ").append((String) hreq.getAttribute("javax.servlet.async.request_uri"));
+         txt.append("\nasync_context_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.async.context_path"));
+         txt.append("\nasync_servlet_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.async.servlet_path"));
+         txt.append("\nasync_path_info:      ").append((String) hreq.getAttribute("javax.servlet.async.path_info"));
+         txt.append("\nasync_query_string:      ").append(
+               (String) hreq.getAttribute("javax.servlet.async.query_string"));
+         txt.append("\nforward_request_uri:      ").append(
+               (String) hreq.getAttribute("javax.servlet.forward.request_uri"));
+         txt.append("\nforward_context_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.forward.context_path"));
+         txt.append("\nforward_servlet_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.forward.servlet_path"));
+         txt.append("\nforward_path_info:      ").append((String) hreq.getAttribute("javax.servlet.forward.path_info"));
+         txt.append("\nforward_query_string:      ").append(
+               (String) hreq.getAttribute("javax.servlet.forward.query_string"));
+         txt.append("\ninclude_request_uri:      ").append(
+               (String) hreq.getAttribute("javax.servlet.include.request_uri"));
+         txt.append("\ninclude_context_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.include.context_path"));
+         txt.append("\ninclude_servlet_path:      ").append(
+               (String) hreq.getAttribute("javax.servlet.include.servlet_path"));
+         txt.append("\ninclude_path_info:      ").append((String) hreq.getAttribute("javax.servlet.include.path_info"));
+         txt.append("\ninclude_query_string:      ").append(
+               (String) hreq.getAttribute("javax.servlet.include.query_string"));
+         txt.append("\nmethod_request_uri:      ").append(hreq.getRequestURI());
+         txt.append("\nmethod_context_path:      ").append(hreq.getContextPath());
+         txt.append("\nmethod_servlet_path:      ").append(hreq.getServletPath());
+         txt.append("\nmethod_path_info:      ").append(hreq.getPathInfo());
+         txt.append("\nmethod_query_string:      ").append(hreq.getQueryString());
+         LOG.debug(txt.toString());
+      }
+
+      // Set portlet-scoped attributes directly on resource request
+
+      request.setAttribute(PortletInvokerService.PORTLET_CONFIG, cfg);
+      request.setAttribute(PortletInvokerService.PORTLET_REQUEST, request);
+      request.setAttribute(PortletInvokerService.PORTLET_RESPONSE, response);
+
+      // Wrap http req & response.
+
+      HttpServletRequest wreq = new PortletAsyncRequestWrapper(hreq, request, this);
+      HttpServletResponse wresp = new HttpServletPortletResponseWrapper(hresp, request, response, false);
+
+      // Start async, add listener to release resources upon async complete only once.
+
+      actx = new PortletAsyncContextImpl(hreq.startAsync(wreq, wresp), wreq);
+
+      if (isTrace) {
+         List<String> attrNames = Collections.list(hreq.getAttributeNames());
+         StringBuilder txt = new StringBuilder(128);
+         txt.append("Start async after (wreq):");
+         txt.append("\nAttribute names: ").append(attrNames);
+         txt.append("\nasync_request_uri:      ").append((String) wreq.getAttribute("javax.servlet.async.request_uri"));
+         txt.append("\nasync_context_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.async.context_path"));
+         txt.append("\nasync_servlet_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.async.servlet_path"));
+         txt.append("\nasync_path_info:      ").append((String) wreq.getAttribute("javax.servlet.async.path_info"));
+         txt.append("\nasync_query_string:      ").append(
+               (String) wreq.getAttribute("javax.servlet.async.query_string"));
+         txt.append("\nforward_request_uri:      ").append(
+               (String) wreq.getAttribute("javax.servlet.forward.request_uri"));
+         txt.append("\nforward_context_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.forward.context_path"));
+         txt.append("\nforward_servlet_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.forward.servlet_path"));
+         txt.append("\nforward_path_info:      ").append((String) wreq.getAttribute("javax.servlet.forward.path_info"));
+         txt.append("\nforward_query_string:      ").append(
+               (String) wreq.getAttribute("javax.servlet.forward.query_string"));
+         txt.append("\ninclude_request_uri:      ").append(
+               (String) wreq.getAttribute("javax.servlet.include.request_uri"));
+         txt.append("\ninclude_context_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.include.context_path"));
+         txt.append("\ninclude_servlet_path:      ").append(
+               (String) wreq.getAttribute("javax.servlet.include.servlet_path"));
+         txt.append("\ninclude_path_info:      ").append((String) wreq.getAttribute("javax.servlet.include.path_info"));
+         txt.append("\ninclude_query_string:      ").append(
+               (String) wreq.getAttribute("javax.servlet.include.query_string"));
+         txt.append("\nmethod_request_uri:      ").append(wreq.getRequestURI());
+         txt.append("\nmethod_context_path:      ").append(wreq.getContextPath());
+         txt.append("\nmethod_servlet_path:      ").append(wreq.getServletPath());
+         txt.append("\nmethod_path_info:      ").append(wreq.getPathInfo());
+         txt.append("\nmethod_query_string:      ").append(wreq.getQueryString());
+         LOG.debug(txt.toString());
+      }
+
+      return actx;
+   }
+
+   // For wrapper use
+   @Override
+   public AsyncContext startAsync() {
+      AsyncContext ac = getServletRequest().startAsync();
+      if (actx == null) {
+         // this should not happen, the wrapper is created during the resource request
+         LOG.error("====>>> Wrapper invocation invalid before resource async started.");
+      } else {
+         actx.setWrapped(ac);
+      }
+      return actx;
+   }
+
+   // for wrapper use
+   @Override
+   public AsyncContext startAsync(ServletRequest request, ServletResponse response) {
+      AsyncContext ac = getServletRequest().startAsync(request, response);
+      if (actx == null) {
+         // this should not happen, the wrapper is created during the resource request
+         LOG.error("====>>> Wrapper invocation invalid before resource async started.");
+      } else {
+         actx.setWrapped(ac);
+      }
+      return actx;
+   }
+
+   @Override
+   public boolean isAsyncStarted() {
+      return getServletRequest().isAsyncStarted();
+   }
+
+   @Override
+   public boolean isAsyncSupported() {
+      return getServletRequest().isAsyncSupported();
+   }
+
+   @Override
+   public AsyncContext getAsyncContext() {
+      if (actx != null) {
+         return actx;
+      }
+      return getServletRequest().getAsyncContext();
+   }
+
+   @Override
+   public DispatcherType getDispatcherType() {
+      return getServletRequest().getDispatcherType();
+   }
+
+   // For use within the wrapper.
+   // PLT.10.4.3. Proxied session is created and passed if
+   // javax.portlet.servletDefaultSessionScope == PORTLET_SCOPE
+   @Override
+   public HttpSession getSession() {
+      HttpSession sess = null;
+
+      PortletConfig portletConfig = getPortletConfig();
+      Map<String, String[]> containerRuntimeOptions = portletConfig.getContainerRuntimeOptions();
+      String[] values = containerRuntimeOptions.get("javax.portlet.servletDefaultSessionScope");
+
+      if ((values != null) && (values.length > 0) && "PORTLET_SCOPE".equals(values[0])) {
+         String portletWindowId = getPortletWindow().getId().getStringId();
+         sess = ServletPortletSessionProxy.createProxy(getServletRequest(), portletWindowId);
+      }
+
+      return sess;
+   }
 }