Skip to content

Commit

Permalink
WELD-2745 Add tests for getReference usage for interceptor instances …
Browse files Browse the repository at this point in the history
…and inside of synth beans' creational method
  • Loading branch information
manovotn committed Jul 4, 2023
1 parent 42bc33b commit fbf16af
Show file tree
Hide file tree
Showing 8 changed files with 223 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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<Interceptor<?>> 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);
}
}
Original file line number Diff line number Diff line change
@@ -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() {

}
}
Original file line number Diff line number Diff line change
@@ -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<MyBinding> implements MyBinding {

public static final Literal INSTANCE = new Literal();

}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.jboss.weld.tests.beanManager.getReference.synthBean;

public class Child {
}
Original file line number Diff line number Diff line change
@@ -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<Child> cc) -> createChild(cc))
.destroyWith((child, cc) -> destroyChild(cc));
event.addBean()
.addTransitiveTypeClosure(Parent.class)
.scope(Singleton.class)
.createWith((CreationalContext<Parent> cc) -> createParent(bm, cc))
.destroyWith((parent, cc) -> destroyParent(cc));
}

private Child createChild(final CreationalContext<Child> cc) {
final Child c = new Child();
this.childCreated = true;
return c;
}

private void destroyChild(CreationalContext<Child> cc) {
this.childDestroyed = true;
cc.release();
}

private Parent createParent(final BeanManager bm, final CreationalContext<Parent> 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<Parent> cc) {
this.parentDestroyed = true;
cc.release();
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
@@ -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.
* <p>
* 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<Parent> pb = (Bean<Parent>) bm.resolve(bm.getBeans(Parent.class));
final CreationalContext<Parent> 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);
}
}

0 comments on commit fbf16af

Please sign in to comment.