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 <[email protected]>
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;
+ }
+ }
+ }
+}