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/14 14:29:23 UTC
[43/50] [abbrv] portals-pluto git commit: worked on contextual
enablement in AsyncContext.start() thread.
worked on contextual enablement in AsyncContext.start() thread.
Project: http://git-wip-us.apache.org/repos/asf/portals-pluto/repo
Commit: http://git-wip-us.apache.org/repos/asf/portals-pluto/commit/27e17ae6
Tree: http://git-wip-us.apache.org/repos/asf/portals-pluto/tree/27e17ae6
Diff: http://git-wip-us.apache.org/repos/asf/portals-pluto/diff/27e17ae6
Branch: refs/heads/master
Commit: 27e17ae6445ec12d0d68517e08c379461a382371
Parents: aae89a3
Author: Scott Nicklous <ms...@apache.org>
Authored: Mon Apr 4 17:03:52 2016 +0200
Committer: Scott Nicklous <ms...@apache.org>
Committed: Mon Apr 4 17:03:52 2016 +0200
----------------------------------------------------------------------
.../apache/portals/samples/AsyncDialogBean.java | 45 ++++-
.../portals/samples/AsyncPortletResource.java | 35 ++--
.../samples/PortletRequestRandomNumberBean.java | 3 +-
.../src/main/webapp/WEB-INF/jsp/asyncDialog.jsp | 14 +-
.../src/main/webapp/WEB-INF/jsp/asyncOutput.jsp | 6 +-
.../pluto/container/PortletAsyncContext.java | 11 +-
.../pluto/container/driver/PortletServlet3.java | 59 +++----
.../PortletRequestScopedBeanHolder.java | 25 ++-
.../processor/PortletSessionBeanHolder.java | 21 +++
.../processor/PortletStateScopedBeanHolder.java | 25 ++-
.../container/PortletAsyncContextImpl.java | 167 +++++++++++++++----
.../container/PortletAsyncContextualRunner.java | 68 ++++++++
.../container/PortletAsyncListener.java | 27 ++-
13 files changed, 419 insertions(+), 87 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
index 5fa7245..c5717bc 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncDialogBean.java
@@ -30,7 +30,6 @@ import javax.portlet.annotations.ActionMethod;
import javax.portlet.annotations.PortletSerializable;
import javax.portlet.annotations.RenderMethod;
import javax.portlet.annotations.RenderStateScoped;
-import javax.servlet.DispatcherType;
/**
* Render state scoped bean. The bean is stored as a render parameter, so it
@@ -41,9 +40,16 @@ import javax.servlet.DispatcherType;
public class AsyncDialogBean implements PortletSerializable {
private static final Logger LOGGER = Logger.getLogger(AsyncDialogBean.class.getName());
+ // defines how output is to be generated
public enum OutputType {
TEXT, INC, FWD, DISPATCH, AUTO
}
+
+ // defines how timeouts are to be handled by the listener
+ // Ignore, complete, or dispatch
+ public enum TimeoutType {
+ NOP, CPL, DIS;
+ }
public static final String PARAM_MSG = "msg";
public static final String PARAM_DELAY = "delay";
@@ -55,6 +61,10 @@ public class AsyncDialogBean implements PortletSerializable {
public static final String PARAM_TYPE_INC = OutputType.INC.toString();
public static final String PARAM_TYPE_FWD = OutputType.FWD.toString();
public static final String PARAM_TYPE_DIS = OutputType.DISPATCH.toString();
+ public static final String PARAM_TO = "toType";
+ public static final String PARAM_TO_NOP = TimeoutType.NOP.toString();
+ public static final String PARAM_TO_CPL = TimeoutType.CPL.toString();
+ public static final String PARAM_TO_DIS = TimeoutType.DIS.toString();
private int delay;
private int reps;
@@ -62,6 +72,7 @@ public class AsyncDialogBean implements PortletSerializable {
private String msg;
private boolean autoDispatch;
private boolean useFilter;
+ private TimeoutType handleTimeout;
/**
* This method is called by the portlet container to initialize the bean at
@@ -70,12 +81,14 @@ public class AsyncDialogBean implements PortletSerializable {
@Override
public void deserialize(String[] state) {
if (state.length == 0) {
+ // set default values
delay = 1000;
reps = 1;
type = OutputType.TEXT;
msg = null;
autoDispatch = true;
useFilter = false;
+ handleTimeout = TimeoutType.CPL;
} else {
delay = Integer.parseInt(state[0]);
reps = Integer.parseInt(state[1]);
@@ -83,6 +96,7 @@ public class AsyncDialogBean implements PortletSerializable {
msg = state[3];
autoDispatch = Boolean.parseBoolean(state[4]);
useFilter = Boolean.parseBoolean(state[5]);
+ handleTimeout = TimeoutType.valueOf(state[6]);
}
LOGGER.fine("deserialized: " + Arrays.asList(state).toString());
}
@@ -93,7 +107,8 @@ public class AsyncDialogBean implements PortletSerializable {
*/
@Override
public String[] serialize() {
- String[] state = { "" + delay, "" + reps, type.toString(), msg, ""+autoDispatch, ""+useFilter };
+ String[] state = { "" + delay, "" + reps, type.toString(), msg,
+ ""+autoDispatch, ""+useFilter, handleTimeout.toString() };
LOGGER.fine("serialized: " + Arrays.asList(state).toString());
return state;
}
@@ -188,6 +203,20 @@ public class AsyncDialogBean implements PortletSerializable {
}
/**
+ * @return the handleTimeout
+ */
+ public TimeoutType getHandleTimeout() {
+ return handleTimeout;
+ }
+
+ /**
+ * @param handleTimeout the handleTimeout to set
+ */
+ public void setHandleTimeout(TimeoutType handleTimeout) {
+ this.handleTimeout = handleTimeout;
+ }
+
+ /**
* Displays the dialog
*
* @return the action form as string
@@ -263,7 +292,17 @@ public class AsyncDialogBean implements PortletSerializable {
useFilter = false;
}
- String[] state = { "" + delay, "" + reps, type.toString(), msg, "" + autoDispatch };
+ String strto = req.getActionParameters().getValue(PARAM_TO);
+ if (strto != null) {
+ try {
+ handleTimeout = TimeoutType.valueOf(strto);
+ } catch (Exception e) {
+ msg = "try again. bad timeout handling: " + strto;
+ }
+ }
+
+ String[] state = { "" + delay, "" + reps, type.toString(), msg,
+ ""+autoDispatch, ""+useFilter, handleTimeout.toString() };
LOGGER.fine("Resulting params: " + Arrays.asList(state).toString());
}
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/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 6cad2fb..6cbaebc 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/AsyncPortletResource.java
@@ -53,19 +53,21 @@ public class AsyncPortletResource {
private final static String ATTRIB_AUTO = "auto";
public final static String ATTRIB_TITLE = "title";
- private class AsyncRunnable implements Runnable {
+ public static class AsyncRunnable implements Runnable {
- private final AsyncContext ctx;
- private final int delay;
- private final OutputType type;
+ private AsyncContext ctx;
+ private int delay;
+ private OutputType type;
+
+ @Inject private PortletRequestRandomNumberBean reqnum;
- public AsyncRunnable(AsyncContext ctx, int delay, OutputType type) {
+ public void init(AsyncContext ctx, int delay, OutputType type) {
this.ctx = ctx;
this.delay = delay;
this.type = type;
StringBuilder txt = new StringBuilder(128);
- txt.append("Constructing runnable.");
+ txt.append("Initializing runnable.");
txt.append(" delay: ").append(delay);
txt.append(", type: ").append(type);
LOGGER.fine(txt.toString());
@@ -93,8 +95,12 @@ public class AsyncPortletResource {
LOGGER.fine("Producing text output.");
StringBuilder txt = new StringBuilder(128);
txt.append("<h5>Thread producing text output for portlet: " + portletName + "</h5>");
- txt.append("<p>dispatcher type: ").append(hreq.getDispatcherType().toString());
- txt.append("</p><hr>");
+ txt.append("<p>Dispatcher type: ").append(hreq.getDispatcherType().toString());
+ txt.append("<span style='margin-left: 2em;'>Request #: ");
+ try { // in case context not active
+ txt.append(reqnum.getRandomNumber());
+ } catch (Exception e) {}
+ txt.append("</span></p><hr>");
hresp.getWriter().write(txt.toString());
ctx.complete();
break;
@@ -138,8 +144,9 @@ public class AsyncPortletResource {
}
- @Inject
- private AsyncDialogBean adb;
+ @Inject private AsyncDialogBean adb;
+ @Inject private PortletRequestRandomNumberBean reqnum;
+ @Inject private AsyncRunnable runner;
@ServeResourceMethod(portletNames = "AsyncPortlet", asyncSupported = true)
public void getResource(ResourceRequest req, ResourceResponse resp) throws IOException, PortletException {
@@ -221,7 +228,9 @@ public class AsyncPortletResource {
txt.setLength(0);
txt.append("<h5>Resource method producing text output for portlet: " + portletName + "</h5>");
txt.append("<p>dispatcher type: ").append(req.getDispatcherType().toString());
- txt.append("</p><hr>");
+ txt.append("<span style='margin-left: 2em;'>Request #: ");
+ txt.append(reqnum.getRandomNumber());
+ txt.append("</span></p><hr>");
resp.getWriter().write(txt.toString());
resp.flushBuffer();
if (done) {
@@ -240,8 +249,8 @@ public class AsyncPortletResource {
type = OutputType.AUTO;
}
- AsyncRunnable ar = new AsyncRunnable(ctx, adb.getDelay(), type);
- ctx.start(ar);
+ runner.init(ctx, adb.getDelay(), type);
+ ctx.start(runner);
}
}
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PortletRequestRandomNumberBean.java
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PortletRequestRandomNumberBean.java b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PortletRequestRandomNumberBean.java
index 407d561..4889827 100644
--- a/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PortletRequestRandomNumberBean.java
+++ b/PortletV3AnnotatedDemo/src/main/java/org/apache/portals/samples/PortletRequestRandomNumberBean.java
@@ -19,6 +19,7 @@
package org.apache.portals.samples;
+import javax.inject.Named;
import javax.portlet.annotations.PortletRequestScoped;
/**
@@ -26,7 +27,7 @@ import javax.portlet.annotations.PortletRequestScoped;
* @author Scott Nicklous
*
*/
-@PortletRequestScoped
+@PortletRequestScoped @Named("reqnum")
public class PortletRequestRandomNumberBean {
private int randomNumber;
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
index fd7e941..355ce90 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncDialog.jsp
@@ -25,7 +25,6 @@ limitations under the License.
<h3>Async Portlet</h3>
<div class='parmbox'>
-${adb.getMsg()}
<FORM ACTION='<portlet:actionURL/>' id='<portlet:namespace/>-setParams' method='POST' enctype='application/x-www-form-urlencoded'>
<table style='width:100%;'><tr><td align='left'>
@@ -40,6 +39,15 @@ ${adb.getMsg()}
<input name='<%=PARAM_AUTO%>' value='<%=PARAM_AUTO%>' type='checkbox' ${adb.isAutoDispatch() ? "checked" : "" } > recursive
</td></tr><tr><td>
+ Handle timeout:
+ </td><td>
+ <input type='radio' name='<%=PARAM_TO%>' value='<%=PARAM_TO_NOP%>' ${adb.getHandleTimeout() == "NOP" ? "checked" : "" } > ignore
+ </td><td>
+ <input type='radio' name='<%=PARAM_TO%>' value='<%=PARAM_TO_CPL%>' ${adb.getHandleTimeout() == "CPL" ? "checked" : "" } > complete
+ </td><td>
+ <input type='radio' name='<%=PARAM_TO%>' value='<%=PARAM_TO_DIS%>' ${adb.getHandleTimeout() == "DIS" ? "checked" : "" } > dispatch
+
+ </td></tr><tr><td>
Output type:
</td><td>
<input type='radio' name='<%=PARAM_TYPE%>' value='<%=PARAM_TYPE_TXT%>' ${adb.getType() == "TEXT" ? "checked" : "" } > text
@@ -56,6 +64,10 @@ ${adb.getMsg()}
<input name='<%=PARAM_FILTER%>' value='<%=PARAM_FILTER%>' type='checkbox' ${adb.isUseFilter() ? "checked" : "" } > show filter
</td></tr></table>
</FORM>
+<p>
+Request #: ${reqnum.getRandomNumber()}
+<span style='margin-left: 2em;'>${adb.getMsg()}</span>
+</p>
</div>
<div class='infobox' id='<portlet:namespace/>putResourceHere'></div>
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
----------------------------------------------------------------------
diff --git a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
index 9297b6b..1c7024e 100644
--- a/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
+++ b/PortletV3AnnotatedDemo/src/main/webapp/WEB-INF/jsp/asyncOutput.jsp
@@ -7,5 +7,9 @@
<portlet:defineObjects />
<h5><%=request.getAttribute("title") %> for portlet: <%=portletConfig.getPortletName() %></h5>
-<p>Dispatch type: <%=request.getDispatcherType() %></p>
+<p>Dispatch type: <%=request.getDispatcherType() %>
+<c:catch var ="catchException">
+ <span style='margin-left: 2em;'>Request #: ${reqnum.getRandomNumber()}</span>
+</c:catch>
+</p>
<hr>
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/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
index 709306e..c4c9966 100644
--- 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
@@ -1,14 +1,15 @@
package org.apache.pluto.container;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.portlet.ResourceRequest;
import javax.servlet.AsyncContext;
public interface PortletAsyncContext extends AsyncContext {
- void init(PortletResourceRequestContext prctx);
-
- /**
- * @param actx the async context to set
- */
+ void init(PortletResourceRequestContext prctx, ResourceRequest resreq, BeanManager beanmgr);
void setWrapped(AsyncContext actx);
+ void registerContext();
+ void deregisterContext();
+ void removeContext();
}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/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 c48ee4d..820ab14 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
@@ -326,7 +326,6 @@ public class PortletServlet3 extends HttpServlet {
wreq = ((ServletRequestWrapper) wreq).getRequest();
}
-
if (wreq instanceof PortletAsyncRequestWrapper) {
HttpServletRequest hreq = (HttpServletRequest) ((PortletAsyncRequestWrapper) wreq).getRequest();
@@ -340,13 +339,20 @@ public class PortletServlet3 extends HttpServlet {
} else {
LOG.debug("Couldn't find the portlet async wrapper.");
}
+
+ // enable contextual support for async
+ ((PortletResourceRequestContext)requestContext).getPortletAsyncContext().registerContext();
} else {
- // the contexts are already initialized if this is part of a resource request async sequence
+ // Not an async dispatch
+
requestContext.init(portletConfig, getServletContext(), request, response);
requestContext.setExecutingRequestBody(true);
responseContext.init(request, response);
+
+ // enable contextual support
+ beforeInvoke(portletRequest, portletResponse, portletConfig);
}
@@ -356,8 +362,6 @@ public class PortletServlet3 extends HttpServlet {
notify(event, true, null);
try {
-
- beforeInvoke(portletRequest, portletResponse, portletConfig);
// The requested method is RENDER: call Portlet.render(..)
if (methodId == PortletInvokerService.METHOD_RENDER) {
@@ -451,43 +455,40 @@ public class PortletServlet3 extends HttpServlet {
} finally {
requestContext.setExecutingRequestBody(false);
- afterInvoke(portletResponse);
// If an async request is running or has been dispatched, resources
// will be released by the PortletAsyncListener. Otherwise release here.
- if (!request.isAsyncStarted()) {
-
- LOG.debug("Async not started, releasing resources. executing req body: " + requestContext.isExecutingRequestBody());
-
- if (request.getDispatcherType() != DispatcherType.ASYNC) {
+ if (!request.isAsyncStarted() && (request.getDispatcherType() != DispatcherType.ASYNC)) {
- request.removeAttribute(PortletInvokerService.METHOD_ID);
- request.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
- request.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
- request.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+ LOG.debug("Async not being processed, releasing resources. executing req body: " + requestContext.isExecutingRequestBody());
+
+ request.removeAttribute(PortletInvokerService.METHOD_ID);
+ request.removeAttribute(PortletInvokerService.PORTLET_REQUEST);
+ request.removeAttribute(PortletInvokerService.PORTLET_RESPONSE);
+ request.removeAttribute(PortletInvokerService.FILTER_MANAGER);
+
+ afterInvoke(portletResponse);
- }
} else {
LOG.debug("Async started, not releasing resources. executing req body: " + requestContext.isExecutingRequestBody());
- // Initialize the async context after the request during which async is
- // first started.
-
- if (request.getDispatcherType() != DispatcherType.ASYNC) {
- if (requestContext instanceof PortletResourceRequestContext) {
- PortletResourceRequestContext resctx = (PortletResourceRequestContext)requestContext;
- PortletAsyncContext pac = resctx.getPortletAsyncContext();
- if (pac != null) {
- pac.init(resctx);
- } else {
- LOG.warn("Couldn't get portlet async context.");
+ if (requestContext instanceof PortletResourceRequestContext) {
+ PortletResourceRequestContext resctx = (PortletResourceRequestContext)requestContext;
+ PortletAsyncContext pac = resctx.getPortletAsyncContext();
+ if (pac != null) {
+ if (request.getDispatcherType() != DispatcherType.ASYNC) {
+ // initialize only on the first time thru
+ pac.init(resctx, (ResourceRequest) portletRequest, beanmgr);
}
+ pac.deregisterContext();
} else {
- LOG.warn("Wrong kind of request context: " + requestContext.getClass().getCanonicalName());
+ LOG.warn("Couldn't get portlet async context.");
}
- }
-
+ } else {
+ LOG.warn("Wrong kind of request context: " + requestContext.getClass().getCanonicalName());
+ }
+
}
}
}
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletRequestScopedBeanHolder.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletRequestScopedBeanHolder.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletRequestScopedBeanHolder.java
index 468e1f0..34538b3 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletRequestScopedBeanHolder.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletRequestScopedBeanHolder.java
@@ -91,7 +91,9 @@ public class PortletRequestScopedBeanHolder implements Serializable {
public static void removeBeanHolder() {
PortletRequestScopedBeanHolder bh = getBeanHolder();
- bh.removeAll();
+ if (bh != null) {
+ bh.removeAll();
+ }
holders.remove();
if (isTrace) {
@@ -110,6 +112,27 @@ public class PortletRequestScopedBeanHolder implements Serializable {
public static PortletRequestScopedBeanHolder getBeanHolder() {
return holders.get();
}
+
+ /**
+ * Removes the bean holder for the current thread and
+ * returns the removed instance to the caller.
+ *
+ * @return the removed bean holder
+ */
+ public static PortletRequestScopedBeanHolder deregister() {
+ PortletRequestScopedBeanHolder holder = holders.get();
+ holders.remove();
+ return holder;
+ }
+
+ /**
+ * Registers the provided bean holder for the current thread.
+ *
+ * @param holder the bean holder to register
+ */
+ public static void register(PortletRequestScopedBeanHolder holder) {
+ holders.set(holder);
+ }
/**
* Returns existing instance of object, or null if no instance exists.
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
index 6d97539..b8d5a23 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletSessionBeanHolder.java
@@ -120,6 +120,27 @@ public class PortletSessionBeanHolder implements Serializable {
public static PortletSessionBeanHolder getBeanHolder() {
return holders.get();
}
+
+ /**
+ * Removes the bean holder for the current thread and
+ * returns the removed instance to the caller.
+ *
+ * @return the removed bean holder
+ */
+ public static PortletSessionBeanHolder deregister() {
+ PortletSessionBeanHolder holder = holders.get();
+ holders.remove();
+ return holder;
+ }
+
+ /**
+ * Registers the provided bean holder for the current thread.
+ *
+ * @param holder the bean holder to register
+ */
+ public static void register(PortletSessionBeanHolder holder) {
+ holders.set(holder);
+ }
/**
* Returns an instance for the contextual type, or null if none available.
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletStateScopedBeanHolder.java
----------------------------------------------------------------------
diff --git a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletStateScopedBeanHolder.java b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletStateScopedBeanHolder.java
index d0ec561..24ca9ca 100644
--- a/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletStateScopedBeanHolder.java
+++ b/pluto-container/src/main/java/org/apache/pluto/container/bean/processor/PortletStateScopedBeanHolder.java
@@ -104,7 +104,9 @@ public class PortletStateScopedBeanHolder implements Serializable {
public static void removeBeanHolder(StateAwareResponse resp) {
PortletStateScopedBeanHolder bh = getBeanHolder();
- bh.removeAll(resp);
+ if (bh != null) {
+ bh.removeAll(resp);
+ }
holders.remove();
if (isTrace) {
@@ -123,6 +125,27 @@ public class PortletStateScopedBeanHolder implements Serializable {
public static PortletStateScopedBeanHolder getBeanHolder() {
return holders.get();
}
+
+ /**
+ * Removes the bean holder for the current thread and
+ * returns the removed instance to the caller.
+ *
+ * @return the removed bean holder
+ */
+ public static PortletStateScopedBeanHolder deregister() {
+ PortletStateScopedBeanHolder holder = holders.get();
+ holders.remove();
+ return holder;
+ }
+
+ /**
+ * Registers the provided bean holder for the current thread.
+ *
+ * @param holder the bean holder to register
+ */
+ public static void register(PortletStateScopedBeanHolder holder) {
+ holders.set(holder);
+ }
/**
* Returns existing instance of object, or null if no instance exists.
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/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
index d638db1..2df6a2f 100644
--- 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
@@ -16,9 +16,13 @@
* under the License.
*/
-
package org.apache.pluto.driver.services.container;
+import java.util.Set;
+
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.portlet.ResourceRequest;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncListener;
import javax.servlet.ServletContext;
@@ -30,41 +34,121 @@ import javax.servlet.http.HttpServletResponse;
import org.apache.pluto.container.PortletAsyncContext;
import org.apache.pluto.container.PortletResourceRequestContext;
+import org.apache.pluto.container.bean.processor.PortletArtifactProducer;
+import org.apache.pluto.container.bean.processor.PortletRequestScopedBeanHolder;
+import org.apache.pluto.container.bean.processor.PortletSessionBeanHolder;
+import org.apache.pluto.container.bean.processor.PortletStateScopedBeanHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
- * 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.
+ * 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 static final Logger LOG = LoggerFactory.getLogger(PortletAsyncContextImpl.class);
+ private static final boolean isDebug = LOG.isDebugEnabled();
+ private static final boolean isTrace = LOG.isTraceEnabled();
+
+
+
+ private AsyncContext actx;
+ private final HttpServletRequest hreq;
- private AsyncContext actx;
- private final HttpServletRequest hreq;
+ private PortletResourceRequestContext prctx;
+ private ResourceRequest resreq;
+ private PortletSessionBeanHolder sessbh;
+ private PortletStateScopedBeanHolder statebh;
+ private PortletRequestScopedBeanHolder reqbh;
+ private BeanManager beanmgr;
+
+ private Runnable pendingRunner;
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)
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.pluto.driver.services.container.PortletAsyncContext#requestComplete(org.apache.pluto.container.
+ * PortletResourceRequestContext)
*/
@Override
- public void init(PortletResourceRequestContext prctx) {
+ public void init(PortletResourceRequestContext prctx, ResourceRequest resreq, BeanManager beanmgr) {
+ this.prctx = prctx;
+ this.resreq = resreq;
+ this.beanmgr = beanmgr;
// 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();
+ PortletAsyncListener pal = new PortletAsyncListener(this);
actx.addListener(pal, creq, cresp);
+
}
-
- /* (non-Javadoc)
+
+ /**
+ * Called when a new thread begins running in order to set up contextual support
+ */
+ @Override
+ public void registerContext() {
+ PortletSessionBeanHolder.register(sessbh);
+ PortletStateScopedBeanHolder.register(statebh);
+ PortletRequestScopedBeanHolder.register(reqbh);
+ PortletArtifactProducer.setPrecursors(resreq, prctx.getResponse(), prctx.getPortletConfig());
+ }
+
+ /**
+ * Called when exiting portlet handling for this thread. The bean holders are deregistered from the thread but are
+ * saved rather than destroyed.
+ */
+ @Override
+ public void deregisterContext() {
+ this.sessbh = PortletSessionBeanHolder.deregister();
+ this.statebh = PortletStateScopedBeanHolder.deregister();
+ this.reqbh = PortletRequestScopedBeanHolder.deregister();
+ PortletArtifactProducer.remove();
+
+ // now if a runner is pending, initialize the contextual runnable and start it
+
+ if (pendingRunner != null) {
+ PortletAsyncContextualRunner runner = new PortletAsyncContextualRunner();
+
+ if (isDebug) {
+ StringBuilder txt = new StringBuilder();
+ txt.append("Executing Portlet Runnable: " + pendingRunner.getClass().getCanonicalName());
+ LOG.debug(txt.toString());
+ }
+
+ runner.init(this, pendingRunner);
+ pendingRunner = null;
+ actx.start(runner);
+ }
+
+ }
+
+ /**
+ * Called when exiting portlet handling for this thread. The bean holders are deregistered from the thread and any
+ * beans contained are destroyed.
+ */
+ @Override
+ public void removeContext() {
+ PortletSessionBeanHolder.removeBeanHolder();
+ PortletStateScopedBeanHolder.removeBeanHolder(null);
+ PortletRequestScopedBeanHolder.removeBeanHolder();
+ PortletArtifactProducer.remove();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
* @see org.apache.pluto.driver.services.container.PortletAsyncContext#setWrapped(javax.servlet.AsyncContext)
*/
@Override
@@ -72,7 +156,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
this.actx = actx;
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#addListener(javax.servlet.AsyncListener)
*/
@Override
@@ -80,15 +166,20 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
actx.addListener(l);
}
- /* (non-Javadoc)
- * @see javax.servlet.AsyncContext#addListener(javax.servlet.AsyncListener, javax.servlet.ServletRequest, javax.servlet.ServletResponse)
+ /*
+ * (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)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#complete()
*/
@Override
@@ -96,7 +187,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
actx.complete();
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#createListener(java.lang.Class)
*/
@Override
@@ -104,7 +197,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
return actx.createListener(cls);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#dispatch()
*/
@Override
@@ -113,7 +208,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
actx.dispatch(hreq.getServletContext(), hreq.getServletPath());
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#dispatch(java.lang.String)
*/
@Override
@@ -122,7 +219,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
actx.dispatch(hreq.getServletContext(), path);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#dispatch(javax.servlet.ServletContext, java.lang.String)
*/
@Override
@@ -130,7 +229,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
actx.dispatch(sctx, path);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#getRequest()
*/
@Override
@@ -138,7 +239,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
return actx.getRequest();
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#getResponse()
*/
@Override
@@ -146,7 +249,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
return actx.getResponse();
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#getTimeout()
*/
@Override
@@ -154,7 +259,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
return actx.getTimeout();
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#hasOriginalRequestAndResponse()
*/
@Override
@@ -162,7 +269,9 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
return actx.hasOriginalRequestAndResponse();
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#setTimeout(long)
*/
@Override
@@ -170,12 +279,14 @@ public class PortletAsyncContextImpl implements PortletAsyncContext {
actx.setTimeout(time);
}
- /* (non-Javadoc)
+ /*
+ * (non-Javadoc)
+ *
* @see javax.servlet.AsyncContext#start(java.lang.Runnable)
*/
@Override
public void start(Runnable run) {
- actx.start(run);
+ pendingRunner = run;
}
}
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
new file mode 100644
index 0000000..6dcac04
--- /dev/null
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncContextualRunner.java
@@ -0,0 +1,68 @@
+/* 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 org.apache.pluto.container.PortletAsyncContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Runner that is launched in thread on behalf of the portlet application runnable
+ * in order to initialize contextual information.
+ *
+ * @author Scott Nicklous
+ *
+ */
+public class PortletAsyncContextualRunner implements Runnable {
+ private static final Logger LOG = LoggerFactory.getLogger(PortletAsyncContextualRunner.class);
+ private static final boolean isDebug = LOG.isDebugEnabled();
+ @SuppressWarnings("unused")
+ private static final boolean isTrace = LOG.isTraceEnabled();
+
+
+ private PortletAsyncContext pactx;
+ private Runnable targetRunner;
+
+ public PortletAsyncContextualRunner() {
+ }
+
+ public void init(PortletAsyncContext pactx, Runnable targetRunner) {
+ this.pactx = pactx;
+ this.targetRunner = targetRunner;
+ }
+
+ @Override
+ public void run() {
+ if (isDebug) {
+ LOG.debug("Initializing contextual environment and launching runner in thread: " + Thread.currentThread().getId());
+ }
+
+ pactx.registerContext();
+ try {
+ targetRunner.run();
+ } finally {
+ if (isDebug) {
+ LOG.debug("Shutting down contextual environment for thread: " + Thread.currentThread().getId());
+ }
+ pactx.deregisterContext();
+ }
+}
+
+}
http://git-wip-us.apache.org/repos/asf/portals-pluto/blob/27e17ae6/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncListener.java
----------------------------------------------------------------------
diff --git a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncListener.java b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncListener.java
index 97b77c6..d546986 100644
--- a/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncListener.java
+++ b/pluto-portal-driver-impl/src/main/java/org/apache/pluto/driver/services/container/PortletAsyncListener.java
@@ -25,10 +25,9 @@ import javax.portlet.ResourceRequest;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;
-import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import org.apache.pluto.container.PortletAsyncContext;
import org.apache.pluto.container.PortletInvokerService;
import org.apache.pluto.container.PortletResourceResponseContext;
@@ -40,7 +39,12 @@ import org.apache.pluto.container.PortletResourceResponseContext;
public class PortletAsyncListener implements AsyncListener {
private static final Logger LOGGER = Logger.getLogger(PortletAsyncListener.class.getName());
- private long start = System.currentTimeMillis();
+ private long start = System.currentTimeMillis();
+ private final PortletAsyncContext pactx;
+
+ public PortletAsyncListener(PortletAsyncContext pactx) {
+ this.pactx = pactx;
+ }
/*
* (non-Javadoc)
@@ -87,8 +91,11 @@ public class PortletAsyncListener implements AsyncListener {
hreq.removeAttribute(PortletInvokerService.FILTER_MANAGER);
} else {
- txt.append("... nothing. Couldn't get servlet request.");
+ txt.append("... no servlet request stuff. Couldn't get servlet request.");
}
+
+ txt.append(" Removing contextual info.");
+ pactx.removeContext();
LOGGER.fine(txt.toString());
@@ -104,6 +111,18 @@ public class PortletAsyncListener implements AsyncListener {
long delta = System.currentTimeMillis() - start;
StringBuilder txt = new StringBuilder(128);
txt.append("Error after ").append(delta).append(" milliseconds.");
+
+ // attempt to complete
+
+ try {
+ AsyncContext ctx = evt.getAsyncContext();
+ ctx.complete();
+ txt.append(" Portlet container completed request processing on behalf of the application.");
+ } catch (IllegalStateException e) {
+ txt.append(" An earlier listener has already dispatched or completed request.");
+ } catch (Exception e) {
+ }
+
txt.append(", Exception: ").append(evt.getThrowable().getMessage());
LOGGER.fine(txt.toString());
}