Repository: deltaspike Updated Branches: refs/heads/master 3b0abce3c -> 8048657e2
DELTASPIKE-745 fix cdictrl-weld to be able to run on new Threads I also improved OWB ContextControl to behave the same as in weld Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/8048657e Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/8048657e Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/8048657e Branch: refs/heads/master Commit: 8048657e265ab4f39b8b2e42425602bf151c7b91 Parents: 3b0abce Author: Mark Struberg <[email protected]> Authored: Wed Oct 22 01:15:06 2014 +0200 Committer: Mark Struberg <[email protected]> Committed: Wed Oct 22 01:15:06 2014 +0200 ---------------------------------------------------------------------- .../deltaspike/cdise/owb/MockHttpSession.java | 8 ++ .../cdise/owb/OpenWebBeansContainerControl.java | 1 + .../cdise/owb/OpenWebBeansContextControl.java | 42 ++++++++- .../apache/deltaspike/cdise/owb/OwbHelper.java | 14 --- .../cdise/weld/ContextController.java | 92 ++++++++++++++------ .../cdise/weld/WeldContextControl.java | 81 ++--------------- .../cdise/tck/ContainerCtrlTckTest.java | 30 +++---- 7 files changed, 140 insertions(+), 128 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8048657e/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/MockHttpSession.java ---------------------------------------------------------------------- diff --git a/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/MockHttpSession.java b/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/MockHttpSession.java index 80a53b7..8ce7dea 100644 --- a/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/MockHttpSession.java +++ b/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/MockHttpSession.java @@ -143,4 +143,12 @@ public class MockHttpSession implements HttpSession { return sessionId != null ? sessionId.hashCode() : 0; } + + @Override + public String toString() + { + return "MockHttpSession{" + + "sessionId='" + sessionId + '\'' + + '}'; + } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8048657e/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OpenWebBeansContainerControl.java ---------------------------------------------------------------------- diff --git a/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OpenWebBeansContainerControl.java b/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OpenWebBeansContainerControl.java index c8c3671..8ac6326 100644 --- a/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OpenWebBeansContainerControl.java +++ b/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OpenWebBeansContainerControl.java @@ -89,6 +89,7 @@ public class OpenWebBeansContainerControl implements CdiContainer // contexts likely already stopped } ctxCtrlBean.destroy(ctxCtrl, ctxCtrlCreationalContext); + ctxCtrl = null; } if (lifecycle != null) http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8048657e/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OpenWebBeansContextControl.java ---------------------------------------------------------------------- diff --git a/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OpenWebBeansContextControl.java b/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OpenWebBeansContextControl.java index 9e8ba98..a0001cb 100644 --- a/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OpenWebBeansContextControl.java +++ b/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OpenWebBeansContextControl.java @@ -26,6 +26,8 @@ import javax.enterprise.context.SessionScoped; import javax.inject.Singleton; import java.lang.annotation.Annotation; +import java.util.WeakHashMap; +import java.util.concurrent.atomic.AtomicInteger; import org.apache.deltaspike.cdise.api.ContextControl; import org.apache.webbeans.config.WebBeansContext; @@ -38,6 +40,10 @@ import org.apache.webbeans.spi.ContextsService; @SuppressWarnings("UnusedDeclaration") public class OpenWebBeansContextControl implements ContextControl { + + private static WeakHashMap<ContextsService, AtomicInteger> sessionRefCounters + = new WeakHashMap<ContextsService, AtomicInteger>(); + @Override public void startContexts() { @@ -149,6 +155,7 @@ public class OpenWebBeansContextControl implements ContextControl { mockSession = OwbHelper.getMockSession(); } + incrementSessionRefCount(contextsService); contextsService.startContext(SessionScoped.class, mockSession); } @@ -203,7 +210,10 @@ public class OpenWebBeansContextControl implements ContextControl { mockSession = OwbHelper.getMockSession(); } - contextsService.endContext(SessionScoped.class, mockSession); + if (decrementSessionRefCount(contextsService)) + { + contextsService.endContext(SessionScoped.class, mockSession); + } } private void stopRequestScope() @@ -225,4 +235,34 @@ public class OpenWebBeansContextControl implements ContextControl WebBeansContext webBeansContext = WebBeansContext.currentInstance(); return webBeansContext.getContextsService(); } + + + private synchronized void incrementSessionRefCount(ContextsService contextsService) + { + AtomicInteger sessionRefCounter = sessionRefCounters.get(contextsService); + if (sessionRefCounter == null) + { + sessionRefCounter = new AtomicInteger(1); + sessionRefCounters.put(contextsService, sessionRefCounter); + } + else + { + sessionRefCounter.incrementAndGet(); + } + } + + /** + * @return true if the refCounter is back to zero + */ + private synchronized boolean decrementSessionRefCount(ContextsService contextsService) + { + AtomicInteger sessionRefCounter = sessionRefCounters.get(contextsService); + if (sessionRefCounter == null) + { + return false; + } + + return sessionRefCounter.decrementAndGet() <= 0; + } + } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8048657e/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OwbHelper.java ---------------------------------------------------------------------- diff --git a/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OwbHelper.java b/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OwbHelper.java index b4ff77f..f543ba7 100644 --- a/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OwbHelper.java +++ b/deltaspike/cdictrl/impl-owb/src/main/java/org/apache/deltaspike/cdise/owb/OwbHelper.java @@ -45,18 +45,4 @@ public class OwbHelper return MockServletContext.getInstance(); } - - public static boolean isServletApiAvailable() - { - try - { - Class servletClass = Class.forName("javax.servlet.http.HttpSession"); - return servletClass != null; - } - catch (ClassNotFoundException e) - { - return false; - } - } - } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8048657e/deltaspike/cdictrl/impl-weld/src/main/java/org/apache/deltaspike/cdise/weld/ContextController.java ---------------------------------------------------------------------- diff --git a/deltaspike/cdictrl/impl-weld/src/main/java/org/apache/deltaspike/cdise/weld/ContextController.java b/deltaspike/cdictrl/impl-weld/src/main/java/org/apache/deltaspike/cdise/weld/ContextController.java index f6c7eaf..99a87db 100644 --- a/deltaspike/cdictrl/impl-weld/src/main/java/org/apache/deltaspike/cdise/weld/ContextController.java +++ b/deltaspike/cdictrl/impl-weld/src/main/java/org/apache/deltaspike/cdise/weld/ContextController.java @@ -26,12 +26,13 @@ import org.jboss.weld.context.bound.BoundSessionContext; import org.jboss.weld.context.bound.MutableBoundRequest; import javax.enterprise.context.RequestScoped; -import javax.enterprise.context.SessionScoped; +import javax.enterprise.inject.Instance; import javax.enterprise.inject.Typed; import javax.inject.Inject; import javax.inject.Singleton; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.atomic.AtomicInteger; /** * Weld specific controller for all supported context implementations @@ -39,6 +40,8 @@ import java.util.Map; @Typed() public class ContextController { + private static ThreadLocal<RequestContextHolder> requestContexts = new ThreadLocal<RequestContextHolder>(); + @Inject private ApplicationContext applicationContext; @@ -46,14 +49,13 @@ public class ContextController private BoundSessionContext sessionContext; @Inject - private BoundRequestContext requestContext; + private Instance<BoundRequestContext> requestContextFactory; @Inject private BoundConversationContext conversationContext; - private Map<String, Object> sessionMap; - private Map<String, Object> requestMap; + private AtomicInteger sessionRefCounter = new AtomicInteger(0); private boolean singletonScopeStarted; @@ -91,71 +93,109 @@ public class ContextController singletonScopeStarted = false; } - void startSessionScope() + synchronized void startSessionScope() { if (sessionMap == null) { sessionMap = new HashMap<String, Object>(); } - else - { - throw new IllegalStateException(SessionScoped.class.getName() + " started already"); - } + sessionRefCounter.incrementAndGet(); sessionContext.associate(sessionMap); sessionContext.activate(); } - void stopSessionScope() + synchronized void stopSessionScope() { if (sessionContext.isActive()) { sessionContext.invalidate(); sessionContext.deactivate(); sessionContext.dissociate(sessionMap); - sessionMap = null; + if (sessionRefCounter.decrementAndGet() <= 0) + { + sessionMap = null; + } } } - void startConversationScope(String cid) + synchronized void startConversationScope(String cid) { - conversationContext.associate(new MutableBoundRequest(requestMap, sessionMap)); + RequestContextHolder rcHolder = requestContexts.get(); + if (rcHolder == null) + { + startRequestScope(); + rcHolder = requestContexts.get(); + } + conversationContext.associate(new MutableBoundRequest(rcHolder.requestMap, sessionMap)); conversationContext.activate(cid); } - void stopConversationScope() + synchronized void stopConversationScope() { + RequestContextHolder rcHolder = requestContexts.get(); + if (rcHolder == null) + { + startRequestScope(); + rcHolder = requestContexts.get(); + } if (conversationContext.isActive()) { conversationContext.invalidate(); conversationContext.deactivate(); - conversationContext.dissociate(new MutableBoundRequest(requestMap, sessionMap)); + conversationContext.dissociate(new MutableBoundRequest(rcHolder.getRequestMap(), sessionMap)); } } - void startRequestScope() + synchronized void startRequestScope() { - if (requestMap == null) + RequestContextHolder rcHolder = requestContexts.get(); + if (rcHolder == null) { - requestMap = new HashMap<String, Object>(); + rcHolder = new RequestContextHolder(requestContextFactory.get(), new HashMap<String, Object>()); + requestContexts.set(rcHolder); } else { throw new IllegalStateException(RequestScoped.class.getName() + " started already"); } - requestContext.associate(requestMap); - requestContext.activate(); + rcHolder.getBoundRequestContext().associate(rcHolder.getRequestMap()); + rcHolder.getBoundRequestContext().activate(); } - void stopRequestScope() + synchronized void stopRequestScope() { - if (requestContext.isActive()) + RequestContextHolder rcHolder = requestContexts.get(); + if (rcHolder != null && rcHolder.getBoundRequestContext().isActive()) + { + rcHolder.getBoundRequestContext().invalidate(); + rcHolder.getBoundRequestContext().deactivate(); + rcHolder.getBoundRequestContext().dissociate(rcHolder.getRequestMap()); + requestContexts.set(null); + requestContexts.remove(); + } + } + + private static class RequestContextHolder + { + private final BoundRequestContext boundRequestContext; + private final Map<String, Object> requestMap; + + private RequestContextHolder(BoundRequestContext boundRequestContext, Map<String, Object> requestMap) + { + this.boundRequestContext = boundRequestContext; + this.requestMap = requestMap; + } + + public BoundRequestContext getBoundRequestContext() + { + return boundRequestContext; + } + + public Map<String, Object> getRequestMap() { - requestContext.invalidate(); - requestContext.deactivate(); - requestContext.dissociate(requestMap); - requestMap = null; + return requestMap; } } } http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8048657e/deltaspike/cdictrl/impl-weld/src/main/java/org/apache/deltaspike/cdise/weld/WeldContextControl.java ---------------------------------------------------------------------- diff --git a/deltaspike/cdictrl/impl-weld/src/main/java/org/apache/deltaspike/cdise/weld/WeldContextControl.java b/deltaspike/cdictrl/impl-weld/src/main/java/org/apache/deltaspike/cdise/weld/WeldContextControl.java index 188f651..e3aff58 100644 --- a/deltaspike/cdictrl/impl-weld/src/main/java/org/apache/deltaspike/cdise/weld/WeldContextControl.java +++ b/deltaspike/cdictrl/impl-weld/src/main/java/org/apache/deltaspike/cdise/weld/WeldContextControl.java @@ -120,50 +120,22 @@ public class WeldContextControl implements ContextControl */ private void startApplicationScope() { - try - { - getContextController().startApplicationScope(); - } - catch (IllegalStateException ise) - { - // weld throws an ISE if the context was already started... - } + getContextController().startApplicationScope(); } private void startSessionScope() { - try - { - getContextController().startSessionScope(); - } - catch (IllegalStateException ise) - { - // weld throws an ISE if the context was already started... - } + getContextController().startSessionScope(); } private void startConversationScope() { - try - { - getContextController().startConversationScope(null); - } - catch (IllegalStateException ise) - { - // weld throws an ISE if the context was already started... - } + getContextController().startConversationScope(null); } private void startRequestScope() { - try - { - getContextController().startRequestScope(); - } - catch (IllegalStateException ise) - { - // weld throws an ISE if the context was already started... - } + getContextController().startRequestScope(); } /* @@ -172,62 +144,27 @@ public class WeldContextControl implements ContextControl private void stopApplicationScope() { - try - { - getContextController().stopApplicationScope(); - } - catch (IllegalStateException ise) - { - // weld throws an ISE if the context was already stopped... - } + getContextController().stopApplicationScope(); } private void stopSessionScope() { - try - { - getContextController().stopSessionScope(); - } - catch (IllegalStateException ise) - { - // weld throws an ISE if the context was already stopped... - } + getContextController().stopSessionScope(); } private void stopConversationScope() { - try - { - getContextController().stopConversationScope(); - } - catch (IllegalStateException ise) - { - // weld throws an ISE if the context was already stopped... - } + getContextController().stopConversationScope(); } private void stopRequestScope() { - try - { - getContextController().stopRequestScope(); - } - catch (IllegalStateException ise) - { - // weld throws an ISE if the context was already stopped... - } + getContextController().stopRequestScope(); } private void stopSingletonScope() { - try - { - getContextController().stopSingletonScope(); - } - catch (IllegalStateException ise) - { - // weld throws an ISE if the context was already stopped... - } + getContextController().stopSingletonScope(); } private ContextController getContextController() http://git-wip-us.apache.org/repos/asf/deltaspike/blob/8048657e/deltaspike/cdictrl/tck/src/main/java/org/apache/deltaspike/cdise/tck/ContainerCtrlTckTest.java ---------------------------------------------------------------------- diff --git a/deltaspike/cdictrl/tck/src/main/java/org/apache/deltaspike/cdise/tck/ContainerCtrlTckTest.java b/deltaspike/cdictrl/tck/src/main/java/org/apache/deltaspike/cdise/tck/ContainerCtrlTckTest.java index 388ff2c..0edf022 100644 --- a/deltaspike/cdictrl/tck/src/main/java/org/apache/deltaspike/cdise/tck/ContainerCtrlTckTest.java +++ b/deltaspike/cdictrl/tck/src/main/java/org/apache/deltaspike/cdise/tck/ContainerCtrlTckTest.java @@ -50,7 +50,7 @@ import org.junit.Test; public class ContainerCtrlTckTest { private static final Logger log = Logger.getLogger(ContainerCtrlTckTest.class.getName()); - private static final int NUM_THREADS = 100; + private static final int NUM_THREADS = 10; @Rule public VersionControlRule versionControlRule = new VersionControlRule(); @@ -92,41 +92,41 @@ public class ContainerCtrlTckTest Assert.assertNotNull(bm); final AtomicInteger numErrors = new AtomicInteger(0); + final ContextControl contextControl = cc.getContextControl(); Runnable runnable = new Runnable() { @Override public void run() { - ContextControl contextControl = cc.getContextControl(); - contextControl.startContext(SessionScoped.class); - contextControl.startContext(RequestScoped.class); + try + { + contextControl.startContext(SessionScoped.class); + contextControl.startContext(RequestScoped.class); - Set<Bean<?>> beans = bm.getBeans(CarRepair.class); - Bean<?> bean = bm.resolve(beans); + Set<Bean<?>> beans = bm.getBeans(CarRepair.class); + Bean<?> bean = bm.resolve(beans); - CarRepair carRepair = (CarRepair) - bm.getReference(bean, CarRepair.class, bm.createCreationalContext(bean)); - Assert.assertNotNull(carRepair); + CarRepair carRepair = (CarRepair) + bm.getReference(bean, CarRepair.class, bm.createCreationalContext(bean)); + Assert.assertNotNull(carRepair); - try - { for (int i = 0; i < 100000; i++) { // we need the threads doing something ;) Assert.assertNotNull(carRepair.getCar()); Assert.assertNotNull(carRepair.getCar().getUser()); - Assert.assertNotNull(carRepair.getCar().getUser().getName()); + Assert.assertNull(carRepair.getCar().getUser().getName()); } + contextControl.stopContext(RequestScoped.class); + contextControl.stopContext(SessionScoped.class); } - catch (Exception e) + catch (Throwable e) { log.log(Level.SEVERE, "An exception happened on a new worker thread", e); numErrors.incrementAndGet(); } - contextControl.stopContext(RequestScoped.class); - contextControl.stopContext(SessionScoped.class); } };
