Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ArC - fix CreationalContext handling when used directly with BeanManager #32945

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -471,12 +471,21 @@ private <T> InstanceHandle<T> instanceHandle(Type type, Annotation... qualifiers

static <T> InstanceHandle<T> beanInstanceHandle(InjectableBean<T> bean, CreationalContextImpl<T> parentContext,
boolean resetCurrentInjectionPoint, Consumer<T> destroyLogic) {
return beanInstanceHandle(bean, parentContext, resetCurrentInjectionPoint, destroyLogic, false);
}

static <T> InstanceHandle<T> beanInstanceHandle(InjectableBean<T> bean, CreationalContextImpl<T> parentContext,
boolean resetCurrentInjectionPoint, Consumer<T> destroyLogic, boolean useParentCreationalContextDirectly) {
if (bean != null) {
if (parentContext == null && Dependent.class.equals(bean.getScope())) {
parentContext = new CreationalContextImpl<>(null);
}
CreationalContextImpl<T> creationalContext = parentContext != null ? parentContext.child(bean)
: new CreationalContextImpl<>(bean);
CreationalContextImpl<T> creationalContext;
if (parentContext != null) {
creationalContext = useParentCreationalContextDirectly ? parentContext : parentContext.child(bean);
} else {
creationalContext = new CreationalContextImpl<>(bean);
}
InjectionPoint prev = null;
if (resetCurrentInjectionPoint) {
prev = InjectionPointProvider.set(CurrentInjectionPointProvider.EMPTY);
Expand All @@ -494,7 +503,7 @@ static <T> InstanceHandle<T> beanInstanceHandle(InjectableBean<T> bean, Creation
}
}

<T> InstanceHandle<T> beanInstanceHandle(InjectableBean<T> bean, CreationalContextImpl<T> parentContext) {
static <T> InstanceHandle<T> beanInstanceHandle(InjectableBean<T> bean, CreationalContextImpl<T> parentContext) {
return beanInstanceHandle(bean, parentContext, true, null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ public Object getReference(Bean<?> bean, Type beanType, CreationalContext<?> ctx
+ "; its bean types are: " + bean.getTypes());
}
if (bean instanceof InjectableBean && ctx instanceof CreationalContextImpl) {
return ArcContainerImpl.instance().beanInstanceHandle((InjectableBean) bean, (CreationalContextImpl) ctx).get();
return ArcContainerImpl.beanInstanceHandle((InjectableBean) bean, (CreationalContextImpl) ctx, true, null, true)
.get();
}
throw new IllegalArgumentException(
"Arguments must be instances of " + InjectableBean.class + " and " + CreationalContextImpl.class + ": \nbean: "
Expand All @@ -80,7 +81,7 @@ public Object getInjectableReference(InjectionPoint ij, CreationalContext<?> ctx
InjectableBean<?> bean = (InjectableBean<?>) resolve(beans);
InjectionPoint prev = InjectionPointProvider.set(ij);
try {
return ArcContainerImpl.beanInstanceHandle(bean, (CreationalContextImpl) ctx, false, null).get();
return ArcContainerImpl.beanInstanceHandle(bean, (CreationalContextImpl) ctx, false, null, true).get();
} finally {
InjectionPointProvider.set(prev);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@
<exclude name="testInstanceUsedForProducerMethodNotShared"/>
<exclude name="testContextIsActive"/>
<exclude name="testContextScopeType"/>
<!-- https://github.com/jakartaee/cdi-tck/issues/454 -->
<exclude name="testDependentScopedInterceptorsAreDependentObjectsOfBean"></exclude>
</methods>
</class>
<class name="org.jboss.cdi.tck.tests.lookup.manager.ManagerTest">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package io.quarkus.arc.test.bean.destroy;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import jakarta.annotation.PreDestroy;
import jakarta.annotation.Priority;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.inject.Inject;
import jakarta.interceptor.Interceptor;
import jakarta.interceptor.InterceptorBinding;
import jakarta.interceptor.InvocationContext;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.arc.Arc;
import io.quarkus.arc.test.ArcTestContainer;

public class DependentPreDestroyOnlyCalledOnceTest {
@RegisterExtension
ArcTestContainer container = new ArcTestContainer(MyDependency.class, MyBean.class, MyInterceptedBean.class,
MyInterceptorBinding.class, MyInterceptor.class);

@BeforeEach
public void setUp() {
MyDependency.preDestroy = 0;
MyBean.preDestroy = 0;
MyInterceptedBean.preDestroy = 0;
}

@SuppressWarnings("unchecked")
@Test
public void preDestroyOnBeanOnly() {
BeanManager beanManager = Arc.container().beanManager();
Bean<MyBean> bean = (Bean<MyBean>) beanManager.resolve(beanManager.getBeans(MyBean.class));
CreationalContext<MyBean> ctx = beanManager.createCreationalContext(bean);
MyBean instance = (MyBean) beanManager.getReference(bean, MyBean.class, ctx);
bean.destroy(instance, ctx);

assertEquals(1, MyDependency.preDestroy);
assertEquals(1, MyBean.preDestroy);
}

@SuppressWarnings("unchecked")
@Test
public void preDestroyOnBeanAndInterceptor() {
BeanManager beanManager = Arc.container().beanManager();
Bean<MyInterceptedBean> bean = (Bean<MyInterceptedBean>) beanManager.resolve(
beanManager.getBeans(MyInterceptedBean.class));
CreationalContext<MyInterceptedBean> ctx = beanManager.createCreationalContext(bean);
MyInterceptedBean instance = (MyInterceptedBean) beanManager.getReference(bean, MyInterceptedBean.class, ctx);
bean.destroy(instance, ctx);

assertEquals(1, MyDependency.preDestroy);
assertEquals(1, MyInterceptedBean.preDestroy);
assertEquals(1, MyInterceptor.preDestroy);
}

@Dependent
static class MyDependency {
static int preDestroy = 0;

@PreDestroy
void destroy() {
preDestroy++;
}
}

@Dependent
static class MyBean {
static int preDestroy = 0;

@Inject
MyDependency dependency;

@PreDestroy
void destroy() {
preDestroy++;
}
}

@Dependent
@MyInterceptorBinding
static class MyInterceptedBean {
static int preDestroy = 0;

@Inject
MyDependency dependency;

@PreDestroy
void destroy() {
preDestroy++;
}
}

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@InterceptorBinding
@interface MyInterceptorBinding {
}

@MyInterceptorBinding
@Interceptor
@Priority(1)
static class MyInterceptor {
static int preDestroy = 0;

@PreDestroy
void preDestroy(InvocationContext ctx) throws Exception {
preDestroy++;
ctx.proceed();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public void testGetReference() {
});
Legacy legacy = (Legacy) beanManager.getReference(legacyBean, Legacy.class, ctx);
assertNotNull(legacy.getBeanManager());
ctx.release();
legacyBean.destroy((AlternativeLegacy) legacy, ctx);
assertTrue(Legacy.DESTROYED.get());
}

Expand Down Expand Up @@ -179,7 +179,6 @@ public Annotated getAnnotated() {
assertNull(injectableReference.injectionPoint.getBean());
}

@SuppressWarnings("serial")
@Test
public void testResolveInterceptors() {
BeanManager beanManager = Arc.container().beanManager();
Expand Down