From 8d753f1ade9675179f624dfaf84dc212a699f666 Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Thu, 19 Sep 2024 11:21:25 +0200 Subject: [PATCH] WIP ArC: fix non-@Inherited transitive bindings on @Inherited bindings --- .../quarkus/arc/processor/BeanDeployment.java | 13 ++ .../io/quarkus/arc/processor/BeanInfo.java | 4 +- .../InheritedTransitiveBindingOnBeanTest.java | 116 ++++++++++++++++++ 3 files changed, 130 insertions(+), 3 deletions(-) create mode 100644 independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/bindings/inherited/transitive/InheritedTransitiveBindingOnBeanTest.java diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java index c7434b5700df87..005cb106d92fef 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanDeployment.java @@ -686,11 +686,24 @@ Collection extractQualifiers(AnnotationInstance annotation) * @return a collection of interceptor bindings or an empty collection */ public Collection extractInterceptorBindings(AnnotationInstance annotation) { + return extractInterceptorBindings(annotation, false); + } + + Collection extractInterceptorBindings(AnnotationInstance annotation, boolean onlyInherited) { Collection result = extractAnnotations(annotation, interceptorBindings, repeatingInterceptorBindingAnnotations); if (result.isEmpty()) { return result; } + if (onlyInherited) { + Set modifiedResult = new HashSet<>(); + for (AnnotationInstance ann : result) { + if (hasAnnotation(getInterceptorBinding(ann.name()), DotNames.INHERITED)) { + modifiedResult.add(ann); + } + } + result = modifiedResult; + } Set transitive = transitiveInterceptorBindings.get(annotation.name()); if (transitive != null) { result = new HashSet<>(result); diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java index 4ef5bb7b468f55..e27ea1d084e2e9 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/BeanInfo.java @@ -922,10 +922,8 @@ private void addClassLevelBindings(ClassInfo targetClass, Collection bindings, Set skip, boolean onlyInherited) { beanDeployment.getAnnotations(classInfo).stream() - .flatMap(a -> beanDeployment.extractInterceptorBindings(a).stream()) + .flatMap(a -> beanDeployment.extractInterceptorBindings(a, onlyInherited).stream()) .filter(a -> !skip.contains(a.name())) - .filter(a -> !onlyInherited - || beanDeployment.hasAnnotation(beanDeployment.getInterceptorBinding(a.name()), DotNames.INHERITED)) .forEach(bindings::add); if (classInfo.superClassType() != null && !classInfo.superClassType().name().equals(DotNames.OBJECT)) { ClassInfo superClass = getClassByName(beanDeployment.getBeanArchiveIndex(), classInfo.superName()); diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/bindings/inherited/transitive/InheritedTransitiveBindingOnBeanTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/bindings/inherited/transitive/InheritedTransitiveBindingOnBeanTest.java new file mode 100644 index 00000000000000..f0225788363fd7 --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/interceptors/bindings/inherited/transitive/InheritedTransitiveBindingOnBeanTest.java @@ -0,0 +1,116 @@ +package io.quarkus.arc.test.interceptors.bindings.inherited.transitive; + +import io.quarkus.arc.Arc; +import io.quarkus.arc.test.ArcTestContainer; +import jakarta.annotation.Priority; +import jakarta.inject.Singleton; +import jakarta.interceptor.AroundInvoke; +import jakarta.interceptor.Interceptor; +import jakarta.interceptor.InterceptorBinding; +import jakarta.interceptor.InvocationContext; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import java.lang.annotation.Documented; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +public class InheritedTransitiveBindingOnBeanTest { + @RegisterExtension + public ArcTestContainer container = new ArcTestContainer.Builder() + .beanClasses(MyBean.class, FooBinding.class, BarBinding.class, BazBinding.class, FooInterceptor.class, BarInterceptor.class, BazInterceptor.class) + .build(); + + @Test + public void testInterception() { + MyBean bean = Arc.container().instance(MyBean.class).get(); + assertNotNull(bean); + bean.doSomething(); + assertTrue(FooInterceptor.intercepted); + assertFalse(BarInterceptor.intercepted); + assertTrue(BazInterceptor.intercepted); + } + + @FooBinding + @BarBinding + static class MySuperclass { + } + + @Singleton + static class MyBean extends MySuperclass { + void doSomething() { + } + } + + @BazBinding + @Target({ TYPE, METHOD }) + @Retention(RUNTIME) + @Documented + @InterceptorBinding + @Inherited + @interface FooBinding { + } + + @Target({ TYPE, METHOD }) + @Retention(RUNTIME) + @Documented + @InterceptorBinding + // not @Inherited + @interface BarBinding { + } + + @Target({ TYPE, METHOD }) + @Retention(RUNTIME) + @Documented + @InterceptorBinding + // not @Inherited + @interface BazBinding { + } + + @FooBinding + @Interceptor + @Priority(1) + static class FooInterceptor { + static boolean intercepted = false; + + @AroundInvoke + Object intercept(InvocationContext ctx) throws Exception { + intercepted = true; + return ctx.proceed(); + } + } + + @BarBinding + @Interceptor + @Priority(1) + static class BarInterceptor { + static boolean intercepted = false; + + @AroundInvoke + Object intercept(InvocationContext ctx) throws Exception { + intercepted = true; + return ctx.proceed(); + } + } + + @BazBinding + @Interceptor + @Priority(1) + static class BazInterceptor { + static boolean intercepted = false; + + @AroundInvoke + Object intercept(InvocationContext ctx) throws Exception { + intercepted = true; + return ctx.proceed(); + } + } +}