diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/ManualInterceptorInstanceRetrievalTest.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/ManualInterceptorInstanceRetrievalTest.java new file mode 100644 index 00000000000..3f81cea9025 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/ManualInterceptorInstanceRetrievalTest.java @@ -0,0 +1,46 @@ +package org.jboss.weld.tests.beanManager.getReference.interceptor; + +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.enterprise.inject.spi.InterceptionType; +import jakarta.enterprise.inject.spi.Interceptor; +import jakarta.inject.Inject; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.BeanArchive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.weld.test.util.Utils; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.util.List; + +/** + * NOTE: The functionality tested here (using BM#getReference for interceptor instances) isn't rooted in CDI spec but + * seems to be something intergrators have relied on in the past. One such example is GF resolving interceptors as part + * of their EJB integration. Another case used to be MP REST using this to simulate their own interceptor chain. + */ +@RunWith(Arquillian.class) +public class ManualInterceptorInstanceRetrievalTest { + + @Deployment + public static Archive getDeployment() { + return ShrinkWrap.create(BeanArchive.class, + Utils.getDeploymentNameAsHash(ManualInterceptorInstanceRetrievalTest.class)).addPackage(ManualInterceptorInstanceRetrievalTest.class.getPackage()); + } + + @Inject + BeanManager bm; + + @Test + public void testGetReferenceForInterceptorInstance() { + List> interceptors = bm.resolveInterceptors(InterceptionType.AROUND_INVOKE, MyBinding.Literal.INSTANCE); + Assert.assertTrue(interceptors.size() == 1); + Interceptor interceptor = interceptors.get(0); + CreationalContext creationalContext = bm.createCreationalContext(interceptor); + Object reference = bm.getReference(interceptor, MyInterceptor.class, creationalContext); + Assert.assertNotNull(reference); + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/MyBean.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/MyBean.java new file mode 100644 index 00000000000..b0937a5d0bd --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/MyBean.java @@ -0,0 +1,12 @@ +package org.jboss.weld.tests.beanManager.getReference.interceptor; + +import jakarta.enterprise.context.Dependent; + +@Dependent +@MyBinding +public class MyBean { + + public void ping() { + + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/MyBinding.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/MyBinding.java new file mode 100644 index 00000000000..33f55ff002b --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/MyBinding.java @@ -0,0 +1,21 @@ +package org.jboss.weld.tests.beanManager.getReference.interceptor; + +import jakarta.enterprise.util.AnnotationLiteral; +import jakarta.interceptor.InterceptorBinding; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@InterceptorBinding +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) +public @interface MyBinding { + + public static class Literal extends AnnotationLiteral implements MyBinding { + + public static final Literal INSTANCE = new Literal(); + + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/MyInterceptor.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/MyInterceptor.java new file mode 100644 index 00000000000..03f9fe2a3c7 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/interceptor/MyInterceptor.java @@ -0,0 +1,24 @@ +package org.jboss.weld.tests.beanManager.getReference.interceptor; + +import jakarta.annotation.Priority; +import jakarta.enterprise.inject.Intercepted; +import jakarta.enterprise.inject.spi.Bean; +import jakarta.inject.Inject; +import jakarta.interceptor.AroundInvoke; +import jakarta.interceptor.Interceptor; +import jakarta.interceptor.InvocationContext; + +@Interceptor +@Priority(1) +@MyBinding +public class MyInterceptor { + + @Inject + @Intercepted + Bean bean; + + @AroundInvoke + public Object intercept(InvocationContext ic) throws Exception { + return ic.proceed(); + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/Child.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/Child.java new file mode 100644 index 00000000000..e4e5598db5d --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/Child.java @@ -0,0 +1,4 @@ +package org.jboss.weld.tests.beanManager.getReference.synthBean; + +public class Child { +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/MyExtension.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/MyExtension.java new file mode 100644 index 00000000000..3b964cd82a2 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/MyExtension.java @@ -0,0 +1,52 @@ +package org.jboss.weld.tests.beanManager.getReference.synthBean; + +import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.spi.AfterBeanDiscovery; +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.inject.Singleton; + +public class MyExtension implements Extension { + + public static boolean childCreated; + public static boolean childDestroyed; + public static boolean parentCreated; + public static boolean parentDestroyed; + + final void registerBeans(@Observes final AfterBeanDiscovery event, final BeanManager bm) { + event.addBean() + .addTransitiveTypeClosure(Child.class) + .scope(Dependent.class) + .createWith((CreationalContext cc) -> createChild(cc)) + .destroyWith((child, cc) -> destroyChild(cc)); + event.addBean() + .addTransitiveTypeClosure(Parent.class) + .scope(Singleton.class) + .createWith((CreationalContext cc) -> createParent(bm, cc)) + .destroyWith((parent, cc) -> destroyParent(cc)); + } + + private Child createChild(final CreationalContext cc) { + final Child c = new Child(); + this.childCreated = true; + return c; + } + + private void destroyChild(CreationalContext cc) { + this.childDestroyed = true; + cc.release(); + } + + private Parent createParent(final BeanManager bm, final CreationalContext cc) { + final Parent p = new Parent((Child)bm.getReference(bm.resolve(bm.getBeans(Child.class)), Child.class, cc)); + this.parentCreated = true; + return p; + } + + private void destroyParent(final CreationalContext cc) { + this.parentDestroyed = true; + cc.release(); + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/Parent.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/Parent.java new file mode 100644 index 00000000000..829bd418c82 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/Parent.java @@ -0,0 +1,11 @@ +package org.jboss.weld.tests.beanManager.getReference.synthBean; + +public class Parent { + + private final Child child; + + Parent(final Child child) { + super(); + this.child = child; + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/SimulateSynthBeanCreationalContextHierarchyTest.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/SimulateSynthBeanCreationalContextHierarchyTest.java new file mode 100644 index 00000000000..1aa39854664 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/beanManager/getReference/synthBean/SimulateSynthBeanCreationalContextHierarchyTest.java @@ -0,0 +1,53 @@ +package org.jboss.weld.tests.beanManager.getReference.synthBean; + +import static org.junit.Assert.assertTrue; + +import jakarta.enterprise.context.spi.AlterableContext; +import jakarta.enterprise.context.spi.CreationalContext; +import jakarta.enterprise.inject.spi.Bean; +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.inject.Inject; +import jakarta.inject.Singleton; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.shrinkwrap.api.Archive; +import org.jboss.shrinkwrap.api.BeanArchive; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.weld.test.util.Utils; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * NOTE: The functionality this test asserts is not explicitly stated in the spec but it turned out to be relied on in + * some cases. We therefore want to have a test coverage for it. + *

+ * This test aims to create two synthetic beans and use their creational context to create a link between then so that + * once one gets destroyed, so should the other. + */ +@RunWith(Arquillian.class) +public class SimulateSynthBeanCreationalContextHierarchyTest { + + @Deployment + public static Archive getDeployment() { + return ShrinkWrap.create(BeanArchive.class, Utils.getDeploymentNameAsHash(SimulateSynthBeanCreationalContextHierarchyTest.class)) + .addPackage(SimulateSynthBeanCreationalContextHierarchyTest.class.getPackage()) + .addAsServiceProvider(Extension.class, MyExtension.class); + } + + @Inject + BeanManager bm; + + @Test + public void testSimulatingCCHierarchyOnSyntBeans() { + final Bean pb = (Bean) bm.resolve(bm.getBeans(Parent.class)); + final CreationalContext pcc = bm.createCreationalContext(pb); + final Parent p = (Parent) bm.getReference(pb, Parent.class, pcc); + assertTrue(MyExtension.parentCreated); + assertTrue(MyExtension.childCreated); + final AlterableContext singletonContext = (AlterableContext) bm.getContext(Singleton.class); + singletonContext.destroy(pb); + assertTrue(MyExtension.parentDestroyed); + assertTrue(MyExtension.childDestroyed); + } +}