This is an automated email from the ASF dual-hosted git repository. rmannibucau pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/openwebbeans.git
The following commit(s) were added to refs/heads/master by this push: new e933276 [OWB-1384][OWB-1385] ensure OwbRequestContextController is thread safe and BaseSeContextsService respects supportsConversation flag e933276 is described below commit e9332767af5abd81867b21b8a4d10718733fb188 Author: Romain Manni-Bucau <rmannibu...@gmail.com> AuthorDate: Fri May 14 12:04:27 2021 +0200 [OWB-1384][OWB-1385] ensure OwbRequestContextController is thread safe and BaseSeContextsService respects supportsConversation flag --- .../control/OwbRequestContextController.java | 59 ++++++++++++++++++++-- .../webbeans/corespi/se/BaseSeContextsService.java | 8 +++ .../webbeans/lifecycle/StandaloneLifeCycle.java | 8 +-- .../control/OwbRequestContextControllerTest.java | 2 + .../conversation/ConversationScopedTest.java | 53 +++++++------------ 5 files changed, 87 insertions(+), 43 deletions(-) diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/context/control/OwbRequestContextController.java b/webbeans-impl/src/main/java/org/apache/webbeans/context/control/OwbRequestContextController.java index 1c45dd5..a6f66f8 100644 --- a/webbeans-impl/src/main/java/org/apache/webbeans/context/control/OwbRequestContextController.java +++ b/webbeans-impl/src/main/java/org/apache/webbeans/context/control/OwbRequestContextController.java @@ -27,15 +27,18 @@ import javax.enterprise.context.ContextNotActiveException; import javax.enterprise.context.RequestScoped; import javax.enterprise.context.control.RequestContextController; import javax.enterprise.context.spi.Context; +import java.util.ArrayList; +import java.util.List; public class OwbRequestContextController implements RequestContextController { private final ContextsService contextsService; - private boolean didActivate = false; + private final ThreadLocal<List<Op>> deactivateOperations; - OwbRequestContextController(WebBeansContext context) + OwbRequestContextController(final WebBeansContext context) { this.contextsService = context.getContextsService(); + this.deactivateOperations = findThreadLocal(context); } @Override @@ -45,20 +48,66 @@ public class OwbRequestContextController implements RequestContextController if (ctx == null || !ctx.isActive()) { contextsService.startContext(RequestScoped.class, null); - didActivate = true; + final List<Op> ops = new ArrayList<>(); + ops.add(Op.DEACTIVATE); + deactivateOperations.set(ops); return true; } + List<Op> deactivateOps = deactivateOperations.get(); + if (deactivateOps == null) + { + deactivateOps = new ArrayList<>(); + deactivateOperations.set(deactivateOps); + } + deactivateOps.add(Op.NOOP); return false; } @Override public void deactivate() throws ContextNotActiveException { - // spec says we only must deactivate the RequestContest "f it was activated by this context controller" - if (didActivate) + // spec says we only must deactivate the RequestContest "if it was activated by this context controller" + final List<Op> ops = deactivateOperations.get(); + if (ops == null) + { + return; + } + if (ops.remove(ops.size() - 1) == Op.DEACTIVATE) { contextsService.endContext(RequestScoped.class, null); RequestScopedBeanInterceptorHandler.removeThreadLocals(); } + if (ops.isEmpty()) + { + deactivateOperations.remove(); + } + } + + // must be per webbeanscontext + private ThreadLocal<List<Op>> findThreadLocal(final WebBeansContext context) + { + ThreadLocalService service = context.getService(ThreadLocalService.class); + if (service == null) + { + synchronized (context) + { + if (service == null) + { + service = new ThreadLocalService(); + context.registerService(ThreadLocalService.class, service); + } + } + } + return service.instance; + } + + private enum Op + { + DEACTIVATE, NOOP + } + + private static class ThreadLocalService + { + private final ThreadLocal<List<Op>> instance = new ThreadLocal<>(); } } diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/corespi/se/BaseSeContextsService.java b/webbeans-impl/src/main/java/org/apache/webbeans/corespi/se/BaseSeContextsService.java index 3df8f18..c2bec79 100644 --- a/webbeans-impl/src/main/java/org/apache/webbeans/corespi/se/BaseSeContextsService.java +++ b/webbeans-impl/src/main/java/org/apache/webbeans/corespi/se/BaseSeContextsService.java @@ -307,6 +307,10 @@ public abstract class BaseSeContextsService extends AbstractContextsService private void startConversationContext() { + if (!supportsConversation) + { + return; + } ConversationManager conversationManager = webBeansContext.getConversationManager(); ConversationContext ctx = conversationManager.getConversationContext(getCurrentSessionContext()); ctx.setActive(true); @@ -393,6 +397,10 @@ public abstract class BaseSeContextsService extends AbstractContextsService private void stopConversationContext() { + if (!supportsConversation) + { + return; + } if(conversationContext.get() != null) { conversationContext.get().destroy(); diff --git a/webbeans-impl/src/main/java/org/apache/webbeans/lifecycle/StandaloneLifeCycle.java b/webbeans-impl/src/main/java/org/apache/webbeans/lifecycle/StandaloneLifeCycle.java index cfb6e73..7afa83e 100644 --- a/webbeans-impl/src/main/java/org/apache/webbeans/lifecycle/StandaloneLifeCycle.java +++ b/webbeans-impl/src/main/java/org/apache/webbeans/lifecycle/StandaloneLifeCycle.java @@ -59,6 +59,10 @@ public class StandaloneLifeCycle extends AbstractLifeCycle @Override protected void afterStartApplication(Object startupObject) { + webBeansContext.getContextsService().startContext(RequestScoped.class, null); + webBeansContext.getContextsService().startContext(SessionScoped.class, null); + webBeansContext.getContextsService().startContext(ConversationScoped.class, null); + if (!BaseSeContextsService.class.isInstance(webBeansContext.getContextsService()) || BaseSeContextsService.class.cast(webBeansContext.getContextsService()).fireApplicationScopeEvents()) { @@ -67,10 +71,6 @@ public class StandaloneLifeCycle extends AbstractLifeCycle webBeansContext.getBeanManagerImpl().fireContextLifecyleEvent( new Object(), InitializedLiteral.INSTANCE_APPLICATION_SCOPED); } - - webBeansContext.getContextsService().startContext(RequestScoped.class, null); - webBeansContext.getContextsService().startContext(SessionScoped.class, null); - webBeansContext.getContextsService().startContext(ConversationScoped.class, null); } @Override diff --git a/webbeans-impl/src/test/java/org/apache/webbeans/context/control/OwbRequestContextControllerTest.java b/webbeans-impl/src/test/java/org/apache/webbeans/context/control/OwbRequestContextControllerTest.java index f8521a0..e6edd6e 100644 --- a/webbeans-impl/src/test/java/org/apache/webbeans/context/control/OwbRequestContextControllerTest.java +++ b/webbeans-impl/src/test/java/org/apache/webbeans/context/control/OwbRequestContextControllerTest.java @@ -45,6 +45,8 @@ public class OwbRequestContextControllerTest extends AbstractUnitTest assertFalse(getInstance(RequestContextController.class).activate()); assertTrue(cs.getCurrentContext(RequestScoped.class).isActive()); controller.deactivate(); + controller.deactivate(); + controller.deactivate(); assertNull(cs.getCurrentContext(RequestScoped.class)); } } diff --git a/webbeans-impl/src/test/java/org/apache/webbeans/test/contexts/conversation/ConversationScopedTest.java b/webbeans-impl/src/test/java/org/apache/webbeans/test/contexts/conversation/ConversationScopedTest.java index d3b4512..936e175 100644 --- a/webbeans-impl/src/test/java/org/apache/webbeans/test/contexts/conversation/ConversationScopedTest.java +++ b/webbeans-impl/src/test/java/org/apache/webbeans/test/contexts/conversation/ConversationScopedTest.java @@ -42,56 +42,41 @@ public class ConversationScopedTest extends AbstractUnitTest @Test public void testTransientConversation() throws Exception { - try - { - System.setProperty(OpenWebBeansConfiguration.APPLICATION_SUPPORTS_CONVERSATION, "true"); - startContainer(ConversationScopedBean.class); + addConfiguration(OpenWebBeansConfiguration.APPLICATION_SUPPORTS_CONVERSATION, "true"); + startContainer(ConversationScopedBean.class); - ConversationScopedBean instance = getInstance(ConversationScopedBean.class); - instance.setValue("a"); - instance.begin(); - ensureSerialisableContext(); + ConversationScopedBean instance = getInstance(ConversationScopedBean.class); + instance.setValue("a"); + instance.begin(); + ensureSerialisableContext(); - restartContext(RequestScoped.class); + restartContext(RequestScoped.class); - instance.end(); - Assert.assertNull(instance.getValue()); - - } - finally - { - System.clearProperty(OpenWebBeansConfiguration.APPLICATION_SUPPORTS_CONVERSATION); - } + instance.end(); + Assert.assertNull(instance.getValue()); } @Test public void testConversationEvents() throws Exception { - try - { - ConversationScopedInitBean.gotStarted = false; - EndConversationObserver.endConversationCalled = false; + ConversationScopedInitBean.gotStarted = false; + EndConversationObserver.endConversationCalled = false; - System.setProperty(OpenWebBeansConfiguration.APPLICATION_SUPPORTS_CONVERSATION, "true"); - startContainer(ConversationScopedInitBean.class, EndConversationObserver.class); + addConfiguration(OpenWebBeansConfiguration.APPLICATION_SUPPORTS_CONVERSATION, "true"); + startContainer(ConversationScopedInitBean.class, EndConversationObserver.class); - ConversationScopedInitBean instance = getInstance(ConversationScopedInitBean.class); - instance.ping(); + ConversationScopedInitBean instance = getInstance(ConversationScopedInitBean.class); + instance.ping(); - Assert.assertTrue(ConversationScopedInitBean.gotStarted); + Assert.assertTrue(ConversationScopedInitBean.gotStarted); - ensureSerialisableContext(); + ensureSerialisableContext(); - shutDownContainer(); + shutDownContainer(); - Assert.assertTrue(EndConversationObserver.endConversationCalled); - } - finally - { - System.clearProperty(OpenWebBeansConfiguration.APPLICATION_SUPPORTS_CONVERSATION); - } + Assert.assertTrue(EndConversationObserver.endConversationCalled); } private void ensureSerialisableContext() throws IOException, ClassNotFoundException