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

Reply via email to