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 d93a124  [OWB-1353][OWB-1354] adding 
ActivateRequestContextInterceptorBean and ensure lifecycle methods dont trigger 
unexpected interceptors
d93a124 is described below

commit d93a1248e079f083dc7e7343c7c0c5474cceb35c
Author: Romain Manni-Bucau <rmannibu...@gmail.com>
AuthorDate: Thu Nov 12 10:50:19 2020 +0100

    [OWB-1353][OWB-1354] adding ActivateRequestContextInterceptorBean and 
ensure lifecycle methods dont trigger unexpected interceptors
---
 .../org/apache/webbeans/config/BeansDeployer.java  |   7 +-
 .../ActivateRequestContextInterceptorBean.java     | 167 +++++++++++++++++++++
 .../intercept/InterceptorResolutionService.java    |  20 ++-
 .../webbeans/intercept/InterceptorsManager.java    |   4 +-
 .../webbeans/portable/InjectionTargetImpl.java     |   7 +-
 .../org/apache/webbeans/util/WebBeansUtil.java     |  10 ++
 .../ActivateRequestContextInterceptorBeanTest.java |  78 ++++++++++
 7 files changed, 285 insertions(+), 8 deletions(-)

diff --git 
a/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java 
b/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java
index aec5393..20489b1 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/config/BeansDeployer.java
@@ -43,6 +43,7 @@ import org.apache.webbeans.container.AnnotatedTypeWrapper;
 import org.apache.webbeans.container.BeanManagerImpl;
 import org.apache.webbeans.container.InjectableBeanManager;
 import org.apache.webbeans.container.InjectionResolver;
+import 
org.apache.webbeans.context.control.ActivateRequestContextInterceptorBean;
 import org.apache.webbeans.corespi.se.DefaultJndiService;
 import org.apache.webbeans.decorator.DecoratorsManager;
 import org.apache.webbeans.deployment.StereoTypeManager;
@@ -228,6 +229,10 @@ public class BeansDeployer
                 
webBeansContext.getBeanManagerImpl().addInternalBean(webBeansContext.getWebBeansUtil().getManagerBean());
                 // Register built-in RequestContextController
                 
webBeansContext.getBeanManagerImpl().addInternalBean(webBeansContext.getWebBeansUtil().getRequestContextControllerBean());
+                
webBeansContext.getInterceptorsManager().addCdiInterceptor(webBeansContext.getWebBeansUtil().getRequestContextInterceptorBean());
+                
webBeansContext.getInterceptorsManager().addPriorityClazzInterceptor(
+                        
ActivateRequestContextInterceptorBean.InterceptorClass.class,
+                        javax.interceptor.Interceptor.Priority.PLATFORM_BEFORE 
+ 100);
 
                 //Fire Event
                 fireBeforeBeanDiscoveryEvent();
@@ -618,7 +623,7 @@ public class BeansDeployer
                 if (priority != null)
                 {
                     Class<?> javaClass = annotatedType.getJavaClass();
-                    interceptorsManager.addPriorityClazzInterceptor(javaClass, 
priority);
+                    interceptorsManager.addPriorityClazzInterceptor(javaClass, 
priority.value());
                 }
             }
             if (annotatedType.getAnnotation(javax.decorator.Decorator.class) 
!= null)
diff --git 
a/webbeans-impl/src/main/java/org/apache/webbeans/context/control/ActivateRequestContextInterceptorBean.java
 
b/webbeans-impl/src/main/java/org/apache/webbeans/context/control/ActivateRequestContextInterceptorBean.java
new file mode 100644
index 0000000..093d844
--- /dev/null
+++ 
b/webbeans-impl/src/main/java/org/apache/webbeans/context/control/ActivateRequestContextInterceptorBean.java
@@ -0,0 +1,167 @@
+/*
+ * 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.webbeans.context.control;
+
+import org.apache.webbeans.annotation.EmptyAnnotationLiteral;
+import org.apache.webbeans.config.WebBeansContext;
+import org.apache.webbeans.util.AnnotationUtil;
+
+import javax.enterprise.context.Dependent;
+import javax.enterprise.context.control.ActivateRequestContext;
+import javax.enterprise.context.control.RequestContextController;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.InjectionPoint;
+import javax.enterprise.inject.spi.InterceptionType;
+import javax.enterprise.inject.spi.Interceptor;
+import javax.interceptor.InvocationContext;
+import java.io.Serializable;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+import java.util.Set;
+
+import static java.util.Collections.emptySet;
+import static java.util.Collections.singleton;
+
+public class ActivateRequestContextInterceptorBean
+        implements 
Interceptor<ActivateRequestContextInterceptorBean.InterceptorClass>, 
Serializable
+{
+    private static final Set<Annotation> BINDING = singleton(new 
ActivateRequestContextLiteral());
+    private static final Set<Type> TYPES = singleton(Object.class);
+    private static final InterceptorClass INSTANCE = new InterceptorClass();
+
+    private final WebBeansContext webBeansContext;
+    private transient RequestContextController contextController;
+
+    public ActivateRequestContextInterceptorBean(final WebBeansContext 
webBeansContext)
+    {
+        this.webBeansContext = webBeansContext;
+        this.contextController = new 
OwbRequestContextController(webBeansContext);
+    }
+
+    @Override
+    public Set<Annotation> getInterceptorBindings()
+    {
+        return BINDING;
+    }
+
+    @Override
+    public boolean intercepts(final InterceptionType type)
+    {
+        return true;
+    }
+
+    @Override
+    public Object intercept(final InterceptionType type, final 
InterceptorClass instance,
+                            final InvocationContext ctx) throws Exception
+    {
+        if (contextController == null) // synchro is not needed since the 
instance is backed by contextsservice
+        {
+            contextController = new 
OwbRequestContextController(webBeansContext);
+        }
+        final boolean activated = contextController.activate();
+        try
+        {
+            return ctx.proceed();
+        }
+        finally
+        {
+            if (activated)
+            {
+                contextController.deactivate();
+            }
+        }
+    }
+
+    @Override
+    public InterceptorClass create(final CreationalContext<InterceptorClass> 
context)
+    {
+        return INSTANCE;
+    }
+
+    @Override
+    public void destroy(final InterceptorClass instance, final 
CreationalContext<InterceptorClass> context)
+    {
+        // no-op
+    }
+
+    @Override
+    public Set<InjectionPoint> getInjectionPoints()
+    {
+        return emptySet();
+    }
+
+    @Override
+    public Class<?> getBeanClass()
+    {
+        return InterceptorClass.class;
+    }
+
+    @Override
+    public boolean isNullable()
+    {
+        return false;
+    }
+
+    @Override
+    public Set<Type> getTypes()
+    {
+        return TYPES;
+    }
+
+    @Override
+    public Set<Annotation> getQualifiers()
+    {
+        return AnnotationUtil.DEFAULT_AND_ANY_ANNOTATION_SET;
+    }
+
+    @Override
+    public Class<? extends Annotation> getScope()
+    {
+        return Dependent.class;
+    }
+
+    @Override
+    public String getName()
+    {
+        return null;
+    }
+
+    @Override
+    public Set<Class<? extends Annotation>> getStereotypes()
+    {
+        return emptySet();
+    }
+
+    @Override
+    public boolean isAlternative()
+    {
+        return false;
+    }
+
+    public static class ActivateRequestContextLiteral
+            extends EmptyAnnotationLiteral<ActivateRequestContext>
+            implements ActivateRequestContext
+    {
+    }
+
+    public static class InterceptorClass implements Serializable
+    {
+    }
+}
diff --git 
a/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorResolutionService.java
 
b/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorResolutionService.java
index fee04fd..9a02b7c 100644
--- 
a/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorResolutionService.java
+++ 
b/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorResolutionService.java
@@ -142,6 +142,9 @@ public class InterceptorResolutionService
         Map<Method, BusinessMethodInterceptorInfo> 
businessMethodInterceptorInfos = new HashMap<>();
         Map<Constructor<?>, BusinessMethodInterceptorInfo> 
constructorInterceptorInfos = new HashMap<>();
 
+        List<Interceptor<?>> classCdiInterceptors = new 
ArrayList<>(allUsedCdiInterceptors);
+        classCdiInterceptors.sort(new InterceptorComparator(webBeansContext));
+
         List<Method> nonInterceptedMethods = new ArrayList<>();
 
         SelfInterceptorBean<T> selfInterceptorBean = 
resolveSelfInterceptorBean(annotatedType);
@@ -245,7 +248,8 @@ public class InterceptorResolutionService
                                        cdiInterceptors, 
cdiConstructorInterceptors,
                                        selfInterceptorBean,
                                        constructorInterceptorInfos, 
businessMethodInterceptorInfos,
-                                       nonInterceptedMethods, 
lifecycleMethodInterceptorInfos);
+                                       nonInterceptedMethods, 
lifecycleMethodInterceptorInfos,
+                                       classCdiInterceptors);
     }
 
     /**
@@ -877,11 +881,13 @@ public class InterceptorResolutionService
                                    Map<Constructor<?>, 
BusinessMethodInterceptorInfo> constructorInterceptorInfos,
                                    Map<Method, BusinessMethodInterceptorInfo> 
businessMethodsInfo,
                                    List<Method> nonInterceptedMethods,
-                                   Map<InterceptionType, LifecycleMethodInfo> 
lifecycleMethodInterceptorInfos)
+                                   Map<InterceptionType, LifecycleMethodInfo> 
lifecycleMethodInterceptorInfos,
+                                   List<Interceptor<?>> classCdiInterceptors)
         {
             this.decorators = decorators;
             this.ejbInterceptors = ejbInterceptors;
             this.cdiInterceptors = cdiInterceptors;
+            this.classCdiInterceptors = classCdiInterceptors;
             this.constructorCdiInterceptors = constructorCdiInterceptors;
             this.selfInterceptorBean = selfInterceptorBean;
             this.businessMethodsInfo = businessMethodsInfo;
@@ -903,6 +909,11 @@ public class InterceptorResolutionService
          */
         private List<Interceptor<?>> cdiInterceptors;
 
+        /**
+         * Class only interceptors (for lifecycle methods).
+         */
+        private List<Interceptor<?>> classCdiInterceptors;
+
         private final List<Interceptor<?>> constructorCdiInterceptors;
 
         /**
@@ -940,6 +951,11 @@ public class InterceptorResolutionService
             return decorators;
         }
 
+        public List<Interceptor<?>> getClassCdiInterceptors()
+        {
+            return classCdiInterceptors;
+        }
+
         public LinkedHashSet<Interceptor<?>> getEjbInterceptors()
         {
             return ejbInterceptors;
diff --git 
a/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorsManager.java
 
b/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorsManager.java
index 1428cb3..15c7ffe 100644
--- 
a/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorsManager.java
+++ 
b/webbeans-impl/src/main/java/org/apache/webbeans/intercept/InterceptorsManager.java
@@ -40,8 +40,6 @@ import 
org.apache.webbeans.component.creation.BeanAttributesBuilder;
 import org.apache.webbeans.component.creation.EjbInterceptorBeanBuilder;
 import org.apache.webbeans.config.WebBeansContext;
 import org.apache.webbeans.container.BeanManagerImpl;
-import javax.annotation.Priority;
-
 import org.apache.webbeans.exception.WebBeansDeploymentException;
 import org.apache.webbeans.util.AnnotationUtil;
 import org.apache.webbeans.util.Asserts;
@@ -359,7 +357,7 @@ public class InterceptorsManager
         return priorityInterceptors.getSorted();
     }
 
-    public void addPriorityClazzInterceptor(Class<?> javaClass, Priority 
priority)
+    public void addPriorityClazzInterceptor(Class<?> javaClass, int priority)
     {
         priorityInterceptors.add(javaClass, priority);
     }
diff --git 
a/webbeans-impl/src/main/java/org/apache/webbeans/portable/InjectionTargetImpl.java
 
b/webbeans-impl/src/main/java/org/apache/webbeans/portable/InjectionTargetImpl.java
index 0134846..e24d968 100644
--- 
a/webbeans-impl/src/main/java/org/apache/webbeans/portable/InjectionTargetImpl.java
+++ 
b/webbeans-impl/src/main/java/org/apache/webbeans/portable/InjectionTargetImpl.java
@@ -132,10 +132,13 @@ public class InjectionTargetImpl<T> extends 
AbstractProducer<T> implements Injec
         BeanInterceptorInfo interceptorInfo = getInterceptorInfo();
         
         postConstructInterceptors
-            = getLifecycleInterceptors(interceptorInfo.getEjbInterceptors(), 
interceptorInfo.getCdiInterceptors(), InterceptionType.POST_CONSTRUCT);
+            = getLifecycleInterceptors(interceptorInfo.getEjbInterceptors(), 
interceptorInfo.getClassCdiInterceptors(), InterceptionType.POST_CONSTRUCT);
 
         preDestroyInterceptors
-            = getLifecycleInterceptors(interceptorInfo.getEjbInterceptors(), 
interceptorInfo.getCdiInterceptors(), InterceptionType.PRE_DESTROY);
+            = getLifecycleInterceptors(interceptorInfo.getEjbInterceptors(), 
interceptorInfo.getClassCdiInterceptors(), InterceptionType.PRE_DESTROY);
+
+        // no more needed
+        interceptorInfo.getClassCdiInterceptors().clear();
 
         InterceptorResolutionService.BusinessMethodInterceptorInfo 
constructorInterceptorInfo =
                                 
interceptorInfo.getConstructorInterceptorInfos().get(getConstructor().getJavaMember());
diff --git 
a/webbeans-impl/src/main/java/org/apache/webbeans/util/WebBeansUtil.java 
b/webbeans-impl/src/main/java/org/apache/webbeans/util/WebBeansUtil.java
index 2c14c6b..2ddeead 100644
--- a/webbeans-impl/src/main/java/org/apache/webbeans/util/WebBeansUtil.java
+++ b/webbeans-impl/src/main/java/org/apache/webbeans/util/WebBeansUtil.java
@@ -55,6 +55,7 @@ import org.apache.webbeans.config.OwbWildcardTypeImpl;
 import org.apache.webbeans.config.WebBeansContext;
 import org.apache.webbeans.container.AnnotatedTypeWrapper;
 import org.apache.webbeans.container.InjectionResolver;
+import 
org.apache.webbeans.context.control.ActivateRequestContextInterceptorBean;
 import org.apache.webbeans.context.control.RequestContextControllerBean;
 import org.apache.webbeans.exception.WebBeansConfigurationException;
 
@@ -495,6 +496,15 @@ public final class WebBeansUtil
     }
 
     /**
+     * Creates a new bean for Request Context Interceptor.
+     * @return new request context interceptor bean instance
+     */
+    public Interceptor<?> getRequestContextInterceptorBean()
+    {
+        return new ActivateRequestContextInterceptorBean(webBeansContext);
+    }
+
+    /**
      * Creates a new instance bean.
      * @return new instance bean
      */
diff --git 
a/webbeans-impl/src/test/java/org/apache/webbeans/context/control/ActivateRequestContextInterceptorBeanTest.java
 
b/webbeans-impl/src/test/java/org/apache/webbeans/context/control/ActivateRequestContextInterceptorBeanTest.java
new file mode 100644
index 0000000..813bf15
--- /dev/null
+++ 
b/webbeans-impl/src/test/java/org/apache/webbeans/context/control/ActivateRequestContextInterceptorBeanTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.webbeans.context.control;
+
+import org.apache.webbeans.test.AbstractUnitTest;
+import org.junit.Test;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.ContextNotActiveException;
+import javax.enterprise.context.RequestScoped;
+import javax.enterprise.context.control.ActivateRequestContext;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class ActivateRequestContextInterceptorBeanTest extends AbstractUnitTest
+{
+    @Test
+    public void autoStartRequestScope()
+    {
+        startContainer(Service.class);
+        final Service service = getInstance(Service.class);
+        
getWebBeansContext().getContextsService().endContext(RequestScoped.class, null);
+        assertFalse(service.isStarted());
+        assertTrue(service.isStartedWithInterceptor());
+        assertFalse(service.isStarted());
+    }
+
+    @ApplicationScoped
+    public static class Service
+    {
+        @Inject
+        private BeanManager beanManager;
+
+        @PostConstruct
+        private void postConstruct()
+        {
+            assertFalse(isStarted());
+        }
+
+        @ActivateRequestContext
+        public boolean isStartedWithInterceptor()
+        {
+            return isStarted();
+        }
+
+        public boolean isStarted()
+        {
+            try
+            {
+                return beanManager.getContext(RequestScoped.class).isActive();
+            }
+            catch (final ContextNotActiveException cnae)
+            {
+                return false;
+            }
+        }
+    }
+}

Reply via email to