From e3ddebe346a0fac2c8eb90cc061bb55cfc304236 Mon Sep 17 00:00:00 2001 From: Matej Novotny Date: Fri, 1 Sep 2023 12:26:37 +0200 Subject: [PATCH] Properly support lookup with qualifiers, create test coverage for it --- .../events/ProcessManagedBeanImpl.java | 2 +- .../events/ProcessSessionBeanImpl.java | 2 +- .../invokable/AbstractInvokerBuilder.java | 5 +- .../weld/invokable/InvokerBuilderImpl.java | 5 +- .../org/jboss/weld/invokable/InvokerImpl.java | 78 ++++++++++++++----- .../weld/invokable/InvokerInfoBuilder.java | 5 +- .../tests/invokable/lookup/BeanProducer.java | 44 +++++++++++ .../tests/invokable/lookup/InvokableBean.java | 32 ++++++++ .../lookup/InvokableMethodLookupTest.java | 77 ++++++++++++++++++ .../lookup/InvokerRegistreringExtension.java | 62 +++++++++++++++ .../tests/invokable/lookup/MyQualifier1.java | 16 ++++ .../tests/invokable/lookup/MyQualifier2.java | 11 +++ .../tests/invokable/lookup/MyQualifier3.java | 12 +++ .../tests/invokable/lookup/MyQualifier4.java | 14 ++++ .../tests/invokable/lookup/MyQualifier5.java | 11 +++ .../tests/invokable/lookup/NotAQualifier.java | 9 +++ .../tests/invokable/lookup/ToBeQualifier.java | 9 +++ .../extension/translator/BeanInfoImpl.java | 2 +- 18 files changed, 368 insertions(+), 28 deletions(-) create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/BeanProducer.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableBean.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableMethodLookupTest.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokerRegistreringExtension.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier1.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier2.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier3.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier4.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier5.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/NotAQualifier.java create mode 100644 tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ToBeQualifier.java diff --git a/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessManagedBeanImpl.java b/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessManagedBeanImpl.java index db8da27467..2b0f44e934 100644 --- a/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessManagedBeanImpl.java +++ b/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessManagedBeanImpl.java @@ -54,7 +54,7 @@ public Collection> getInvokableMethods() { @Override public InvokerBuilder> createInvoker(AnnotatedMethod annotatedMethod) { checkWithinObserverNotification(); - return new InvokerBuilderImpl<>(getBean().getType(), annotatedMethod.getJavaMember()); + return new InvokerBuilderImpl<>(getBean().getType(), annotatedMethod.getJavaMember(), getBeanManager()); } } diff --git a/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessSessionBeanImpl.java b/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessSessionBeanImpl.java index 39857d7405..65ea078fae 100644 --- a/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessSessionBeanImpl.java +++ b/impl/src/main/java/org/jboss/weld/bootstrap/events/ProcessSessionBeanImpl.java @@ -75,6 +75,6 @@ public Collection> getInvokableMethods() { @Override public InvokerBuilder> createInvoker(AnnotatedMethod annotatedMethod) { checkWithinObserverNotification(); - return new InvokerBuilderImpl<>(getBean().getEjbDescriptor().getBeanClass(), annotatedMethod.getJavaMember()); + return new InvokerBuilderImpl<>(getBean().getEjbDescriptor().getBeanClass(), annotatedMethod.getJavaMember(), getBeanManager()); } } diff --git a/impl/src/main/java/org/jboss/weld/invokable/AbstractInvokerBuilder.java b/impl/src/main/java/org/jboss/weld/invokable/AbstractInvokerBuilder.java index 54baa9948d..e72471011a 100644 --- a/impl/src/main/java/org/jboss/weld/invokable/AbstractInvokerBuilder.java +++ b/impl/src/main/java/org/jboss/weld/invokable/AbstractInvokerBuilder.java @@ -1,5 +1,6 @@ package org.jboss.weld.invokable; +import jakarta.enterprise.inject.spi.BeanManager; import jakarta.enterprise.invoke.InvokerBuilder; import java.lang.reflect.Method; @@ -13,6 +14,7 @@ abstract class AbstractInvokerBuilder implements InvokerBuilder { boolean instanceLookup; boolean[] argLookup; + BeanManager beanManager; TransformerMetadata instanceTransformer; TransformerMetadata returnValueTransformer; TransformerMetadata exceptionTransformer; @@ -20,11 +22,12 @@ abstract class AbstractInvokerBuilder implements InvokerBuilder { final TransformerMetadata[] argTransformers; // TODO Class is rawtype otherwise we cannot use it from InvokerInfoBuilder, can we improve this? - public AbstractInvokerBuilder(Class beanClass, Method method) { + public AbstractInvokerBuilder(Class beanClass, Method method, BeanManager beanManager) { this.beanClass = beanClass; this.method = method; this.argLookup = new boolean[method.getParameters().length]; this.argTransformers = new TransformerMetadata[method.getParameters().length]; + this.beanManager = beanManager; } diff --git a/impl/src/main/java/org/jboss/weld/invokable/InvokerBuilderImpl.java b/impl/src/main/java/org/jboss/weld/invokable/InvokerBuilderImpl.java index 96da556fcb..aaaf69f320 100644 --- a/impl/src/main/java/org/jboss/weld/invokable/InvokerBuilderImpl.java +++ b/impl/src/main/java/org/jboss/weld/invokable/InvokerBuilderImpl.java @@ -1,13 +1,14 @@ package org.jboss.weld.invokable; +import jakarta.enterprise.inject.spi.BeanManager; import jakarta.enterprise.invoke.Invoker; import java.lang.reflect.Method; public class InvokerBuilderImpl extends AbstractInvokerBuilder { - public InvokerBuilderImpl(Class beanClass, Method method) { - super(beanClass, method); + public InvokerBuilderImpl(Class beanClass, Method method, BeanManager beanManager) { + super(beanClass, method, beanManager); } @Override diff --git a/impl/src/main/java/org/jboss/weld/invokable/InvokerImpl.java b/impl/src/main/java/org/jboss/weld/invokable/InvokerImpl.java index 7697494395..5da0d49bd1 100644 --- a/impl/src/main/java/org/jboss/weld/invokable/InvokerImpl.java +++ b/impl/src/main/java/org/jboss/weld/invokable/InvokerImpl.java @@ -1,17 +1,22 @@ package org.jboss.weld.invokable; import jakarta.enterprise.context.Dependent; +import jakarta.enterprise.inject.Default; import jakarta.enterprise.inject.Instance; import jakarta.enterprise.inject.build.compatible.spi.InvokerInfo; +import jakarta.enterprise.inject.spi.BeanManager; import jakarta.enterprise.inject.spi.CDI; import jakarta.enterprise.inject.spi.DeploymentException; import jakarta.enterprise.invoke.Invoker; +import jakarta.inject.Named; +import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -23,19 +28,20 @@ public class InvokerImpl implements Invoker, InvokerInfo { private final MethodHandle beanMethodHandle; private final MethodHandle invocationWrapper; private final Method method; - private final boolean instanceLookup; - private final boolean[] argLookup; + // null if no lookup is to be done + private final Annotation[] instanceLookupQualifiers; + private final Annotation[][] argLookupQualifiers; private final boolean hasInstanceTransformer; private final Class beanClass; private final InvokerCleanupActions cleanupActions; // this variant is only used for invocation wrapper and assumes fully-initialized state - private InvokerImpl(MethodHandle beanMethodHandle, boolean instanceLookup, boolean[] argLookup, + private InvokerImpl(MethodHandle beanMethodHandle, Annotation[] instanceLookupQualifiers, Annotation[][] argLookupQualifiers, boolean hasInstanceTransformer, InvokerCleanupActions cleanupActions, Class beanClass, Method method) { this.beanMethodHandle = beanMethodHandle; - this.instanceLookup = instanceLookup; - this.argLookup = argLookup; + this.instanceLookupQualifiers = instanceLookupQualifiers; + this.argLookupQualifiers = argLookupQualifiers; this.hasInstanceTransformer = hasInstanceTransformer; this.cleanupActions = cleanupActions; this.beanClass = beanClass; @@ -46,11 +52,21 @@ private InvokerImpl(MethodHandle beanMethodHandle, boolean instanceLookup, boole protected InvokerImpl(AbstractInvokerBuilder builder) { // needs to be initialized first, as can be used when creating method handles this.cleanupActions = new InvokerCleanupActions(); - - this.instanceLookup = builder.instanceLookup; - this.argLookup = builder.argLookup; this.beanClass = builder.beanClass; this.method = builder.method; + if (builder.instanceLookup) { + this.instanceLookupQualifiers = extractInstanceQualifiers(beanClass, builder.beanManager); + } else { + this.instanceLookupQualifiers = null; + } + this.argLookupQualifiers = new Annotation[builder.argLookup.length][]; + for (int i = 0; i < builder.argLookup.length; i++) { + // positions that remain null are those for which we don't perform lookup + if (builder.argLookup[i]) { + this.argLookupQualifiers[i] = extractParamQualifiers(method.getParameters()[i], builder.beanManager); + } + } + // handles transformers MethodHandle[] argTransformers = new MethodHandle[builder.argTransformers.length]; @@ -247,8 +263,8 @@ public R invoke(T instance, Object[] arguments) { // if there is an invocation wrapper, just invoke the wrapper immediately if (this.invocationWrapper != null) { try { - return (R) invocationWrapper.invoke(instance, arguments, new InvokerImpl<>(beanMethodHandle, instanceLookup, - argLookup, hasInstanceTransformer, cleanupActions, beanClass, method)); + return (R) invocationWrapper.invoke(instance, arguments, new InvokerImpl<>(beanMethodHandle, instanceLookupQualifiers, + argLookupQualifiers, hasInstanceTransformer, cleanupActions, beanClass, method)); } catch (Throwable e) { // invocation wrapper or the method itself threw an exception, we just rethrow throw new RuntimeException(e); @@ -256,16 +272,16 @@ public R invoke(T instance, Object[] arguments) { } // TODO do we want to verify that the T instance is the exact class of the bean? - if (arguments.length != argLookup.length) { + if (arguments.length != method.getParameterCount()) { // TODO better exception - throw new IllegalArgumentException("Wrong number of args for invoker! Expected: " + argLookup.length + " Provided: " + arguments); + throw new IllegalArgumentException("Wrong number of args for invoker! Expected: " + method.getParameterCount() + " Provided: " + arguments.length); } T beanInstance = instance; Instance cdiLookup = CDI.current().getBeanManager().createInstance(); - if (instanceLookup) { + if (instanceLookupQualifiers != null) { // instance lookup set, ignore the parameter we got and lookup the instance // standard CDI resolution errors can occur - beanInstance = getInstance(cdiLookup, beanClass); + beanInstance = getInstance(cdiLookup, beanClass, instanceLookupQualifiers); } else { // arg should not be null unless the method is (a) static, (b) has instance transformer, (c) has instance lookup if (beanInstance == null && !Modifier.isStatic(method.getModifiers()) && !hasInstanceTransformer) { @@ -274,10 +290,10 @@ public R invoke(T instance, Object[] arguments) { } } - List methodArgs = new ArrayList<>(argLookup.length + 1); - for (int i = 0; i < argLookup.length; i++) { - if (argLookup[i]) { - methodArgs.add(i, getInstance(cdiLookup, beanMethodHandle.type().parameterType(Modifier.isStatic(method.getModifiers()) ? i : i + 1))); + List methodArgs = new ArrayList<>(argLookupQualifiers.length + 1); + for (int i = 0; i < argLookupQualifiers.length; i++) { + if (argLookupQualifiers[i] != null) { + methodArgs.add(i, getInstance(cdiLookup, beanMethodHandle.type().parameterType(Modifier.isStatic(method.getModifiers()) ? i : i + 1), argLookupQualifiers[i])); } else { methodArgs.add(i, arguments[i]); } @@ -304,12 +320,34 @@ public R invoke(T instance, Object[] arguments) { } } - private TYPE getInstance(Instance lookup, Class classToLookup) { - Instance.Handle handle = lookup.select(classToLookup).getHandle(); + private TYPE getInstance(Instance lookup, Class classToLookup, Annotation... qualifiers) { + Instance.Handle handle = lookup.select(classToLookup, qualifiers).getHandle(); this.cleanupActions.addInstanceHandle(handle); return handle.get(); } + private Annotation[] extractInstanceQualifiers(Class beanClass, BeanManager bm) { + return extractQualifiers(beanClass.getAnnotations(), bm); + } + + private Annotation[] extractParamQualifiers(Parameter parameter, BeanManager bm) { + return extractQualifiers(parameter.getAnnotations(), bm); + } + + private Annotation[] extractQualifiers(Annotation[] annotations, BeanManager bm) { + List qualifiers = new ArrayList<>(); + for (Annotation a : annotations) { + if (bm.isQualifier(a.annotationType())) { + qualifiers.add(a); + } + } + // add default when there are no qualifiers or just @Named + if (qualifiers.size() == 0 || (qualifiers.size() == 1 && qualifiers.get(0).annotationType().equals(Named.class))) { + qualifiers.add(Default.Literal.INSTANCE); + } + return qualifiers.toArray(new Annotation[]{}); + } + private class InvokerCleanupActions implements Consumer { private List cleanupTasks = new ArrayList<>(); diff --git a/impl/src/main/java/org/jboss/weld/invokable/InvokerInfoBuilder.java b/impl/src/main/java/org/jboss/weld/invokable/InvokerInfoBuilder.java index 61c25c5ab3..7142eac221 100644 --- a/impl/src/main/java/org/jboss/weld/invokable/InvokerInfoBuilder.java +++ b/impl/src/main/java/org/jboss/weld/invokable/InvokerInfoBuilder.java @@ -1,13 +1,14 @@ package org.jboss.weld.invokable; import jakarta.enterprise.inject.build.compatible.spi.InvokerInfo; +import jakarta.enterprise.inject.spi.BeanManager; import java.lang.reflect.Method; public class InvokerInfoBuilder extends AbstractInvokerBuilder { - public InvokerInfoBuilder(Class beanClass, Method method) { - super(beanClass, method); + public InvokerInfoBuilder(Class beanClass, Method method, BeanManager beanManager) { + super(beanClass, method, beanManager); } @Override diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/BeanProducer.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/BeanProducer.java new file mode 100644 index 0000000000..67441197e1 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/BeanProducer.java @@ -0,0 +1,44 @@ +package org.jboss.weld.tests.invokable.lookup; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; + +@ApplicationScoped +public class BeanProducer { + + @Produces + @MyQualifier1("foo") + @MyQualifier4("binding") + public String produce1 () { + return MyQualifier1.class.getSimpleName() + MyQualifier4.class.getSimpleName(); + } + + @Produces + @MyQualifier2 + public String produce2 () { + return MyQualifier2.class.getSimpleName(); + } + + @Produces + @MyQualifier5 + public String produceAmbig1 () { + throw new IllegalStateException("Ambiguous producer should never be invoked"); + } + + @Produces + @MyQualifier5 + public String produceAmbig2 () { + throw new IllegalStateException("Ambiguous producer should never be invoked"); + } + + @Produces + public String producePlain () { + throw new IllegalStateException("No qualifier producer should never be invoked"); + } + + @Produces + @ToBeQualifier + public String produceQualified () { + return ToBeQualifier.class.getSimpleName(); + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableBean.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableBean.java new file mode 100644 index 0000000000..f0d81ea71b --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableBean.java @@ -0,0 +1,32 @@ +package org.jboss.weld.tests.invokable.lookup; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.invoke.Invokable; + +@ApplicationScoped +@MyQualifier1("myBean") +@Invokable +public class InvokableBean { + + public String instanceLookup() { + return InvokableBean.class.getSimpleName(); + } + + // there are two producers providing a bean for the first argument + public String ambiguousLookup(@MyQualifier5 String a) { + return a; + } + + // there is no bean with @MyQualifier3 + public String unsatisfiedLookup(@MyQualifier3 String a) { + return a; + } + + public String correctLookup (@MyQualifier1("noMatter") @MyQualifier4("binding") String a, @MyQualifier2 String b) { + return a + b; + } + + public String lookupWithRegisteredQualifier (@ToBeQualifier String a) { + return a; + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableMethodLookupTest.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableMethodLookupTest.java new file mode 100644 index 0000000000..02b87b2448 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokableMethodLookupTest.java @@ -0,0 +1,77 @@ +package org.jboss.weld.tests.invokable.lookup; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import jakarta.enterprise.inject.AmbiguousResolutionException; +import jakarta.enterprise.inject.UnsatisfiedResolutionException; +import jakarta.enterprise.inject.spi.Extension; +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.Test; +import org.junit.runner.RunWith; + +@RunWith(Arquillian.class) +public class InvokableMethodLookupTest { + + @Deployment + public static Archive getDeployment() { + return ShrinkWrap.create(BeanArchive.class, Utils.getDeploymentNameAsHash(InvokableMethodLookupTest.class)) + .addPackage(InvokableMethodLookupTest.class.getPackage()) + .addAsServiceProvider(Extension.class, InvokerRegistreringExtension.class); + } + + @Inject + InvokerRegistreringExtension extension; + + @Inject + @MyQualifier1("abc") + InvokableBean bean; + + @Test + public void testInstanceLookupWithQualifiers() { + Object invokerResult = extension.getInstanceLookupInvoker().invoke(null, new Object[]{}); + assertTrue(invokerResult instanceof String); + assertEquals(InvokableBean.class.getSimpleName(), invokerResult); + } + + @Test + public void testCorrectArqLookupWithQualifiers() { + Object invokerResult = extension.getCorrectLookupInvoker().invoke(bean, new Object[]{null, null}); + assertTrue(invokerResult instanceof String); + assertEquals(MyQualifier1.class.getSimpleName() + MyQualifier4.class.getSimpleName() + MyQualifier2.class.getSimpleName(), invokerResult); + } + + @Test + public void testLookupWithRegisteredQualifier() { + Object invokerResult = extension.getLookupWithRegisteredQualifier().invoke(bean, new Object[]{null}); + assertTrue(invokerResult instanceof String); + assertEquals(ToBeQualifier.class.getSimpleName(), invokerResult); + } + + @Test + public void testUnsatisfiedLookupWithQualifier() { + try { + Object invokerResult = extension.getUnsatisfiedLookupInvoker().invoke(bean, new Object[]{null}); + fail(); + } catch (UnsatisfiedResolutionException e) { + // expected + } + } + + @Test + public void testAmbigLookupWithQualifiers() { + try { + Object invokerResult = extension.getAmbiguousLookupInvoker().invoke(bean, new Object[]{null}); + fail(); + } catch (AmbiguousResolutionException e) { + // expected + } + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokerRegistreringExtension.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokerRegistreringExtension.java new file mode 100644 index 0000000000..585feb1681 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/InvokerRegistreringExtension.java @@ -0,0 +1,62 @@ +package org.jboss.weld.tests.invokable.lookup; + +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.spi.AnnotatedMethod; +import jakarta.enterprise.inject.spi.BeforeBeanDiscovery; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.enterprise.inject.spi.ProcessManagedBean; +import jakarta.enterprise.invoke.Invoker; +import org.junit.Assert; + +import java.util.Collection; + +public class InvokerRegistreringExtension implements Extension { + + private Invoker instanceLookupInvoker; + private Invoker unsatisfiedLookupInvoker; + private Invoker ambiguousLookupInvoker; + private Invoker correctLookupInvoker; + private Invoker lookupWithRegisteredQualifier; + + public Invoker getInstanceLookupInvoker() { + return instanceLookupInvoker; + } + + public Invoker getUnsatisfiedLookupInvoker() { + return unsatisfiedLookupInvoker; + } + + public Invoker getAmbiguousLookupInvoker() { + return ambiguousLookupInvoker; + } + + public Invoker getCorrectLookupInvoker() { + return correctLookupInvoker; + } + + public Invoker getLookupWithRegisteredQualifier() { + return lookupWithRegisteredQualifier; + } + + public void createInvokers(@Observes ProcessManagedBean pmb) { + Collection> invokableMethods = pmb.getInvokableMethods(); + Assert.assertEquals(5, invokableMethods.size()); + for (AnnotatedMethod invokableMethod : invokableMethods) { + if (invokableMethod.getJavaMember().getName().contains("instanceLookup")) { + instanceLookupInvoker = pmb.createInvoker(invokableMethod).setInstanceLookup().build(); + } else if (invokableMethod.getJavaMember().getName().contains("unsatisfiedLookup")) { + unsatisfiedLookupInvoker = pmb.createInvoker(invokableMethod).setArgumentLookup(0).build(); + } else if (invokableMethod.getJavaMember().getName().contains("ambiguousLookup")) { + ambiguousLookupInvoker = pmb.createInvoker(invokableMethod).setArgumentLookup(0).build(); + } else if (invokableMethod.getJavaMember().getName().contains("lookupWithRegisteredQualifier")) { + lookupWithRegisteredQualifier = pmb.createInvoker(invokableMethod).setArgumentLookup(0).build(); + } else { + correctLookupInvoker = pmb.createInvoker(invokableMethod).setArgumentLookup(0).setArgumentLookup(1).build(); + } + } + } + + public void registerQualifier(@Observes BeforeBeanDiscovery bbd) { + bbd.addQualifier(ToBeQualifier.class); + } +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier1.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier1.java new file mode 100644 index 0000000000..db73bef100 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier1.java @@ -0,0 +1,16 @@ +package org.jboss.weld.tests.invokable.lookup; + +import jakarta.enterprise.util.Nonbinding; +import jakarta.inject.Qualifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@Qualifier +public @interface MyQualifier1 { + + // non-binding + @Nonbinding + String value(); +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier2.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier2.java new file mode 100644 index 0000000000..b5b3cc1161 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier2.java @@ -0,0 +1,11 @@ +package org.jboss.weld.tests.invokable.lookup; + +import jakarta.inject.Qualifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@Qualifier +public @interface MyQualifier2 { +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier3.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier3.java new file mode 100644 index 0000000000..1698e22612 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier3.java @@ -0,0 +1,12 @@ +package org.jboss.weld.tests.invokable.lookup; + +import jakarta.inject.Qualifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +// no bean with this qualifier is supposed to exist +@Retention(RetentionPolicy.RUNTIME) +@Qualifier +public @interface MyQualifier3 { +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier4.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier4.java new file mode 100644 index 0000000000..059332ef29 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier4.java @@ -0,0 +1,14 @@ +package org.jboss.weld.tests.invokable.lookup; + +import jakarta.inject.Qualifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@Qualifier +public @interface MyQualifier4 { + + // binding value + String value(); +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier5.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier5.java new file mode 100644 index 0000000000..e411cf6e0e --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/MyQualifier5.java @@ -0,0 +1,11 @@ +package org.jboss.weld.tests.invokable.lookup; + +import jakarta.inject.Qualifier; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +@Qualifier +public @interface MyQualifier5 { +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/NotAQualifier.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/NotAQualifier.java new file mode 100644 index 0000000000..11a9a51c08 --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/NotAQualifier.java @@ -0,0 +1,9 @@ +package org.jboss.weld.tests.invokable.lookup; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +// deliberately not a qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface NotAQualifier { +} diff --git a/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ToBeQualifier.java b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ToBeQualifier.java new file mode 100644 index 0000000000..bae963e91e --- /dev/null +++ b/tests-arquillian/src/test/java/org/jboss/weld/tests/invokable/lookup/ToBeQualifier.java @@ -0,0 +1,9 @@ +package org.jboss.weld.tests.invokable.lookup; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +// an extension turns this annotation into a CDI qualifier +@Retention(RetentionPolicy.RUNTIME) +public @interface ToBeQualifier { +} diff --git a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/BeanInfoImpl.java b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/BeanInfoImpl.java index 0cbabce2b7..38bce790c9 100644 --- a/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/BeanInfoImpl.java +++ b/weld-lite-extension-translator/src/main/java/org/jboss/weld/lite/extension/translator/BeanInfoImpl.java @@ -169,7 +169,7 @@ public InvokerBuilder createInvoker(MethodInfo methodInfo) { } if (methodInfo instanceof MethodInfoImpl) { // at this point we can be sure it is a Method, not a Constructor, so we cast it - return new InvokerInfoBuilder(cdiBean.getBeanClass(), (java.lang.reflect.Method)((MethodInfoImpl) methodInfo).cdiDeclaration.getJavaMember()); + return new InvokerInfoBuilder(cdiBean.getBeanClass(), (java.lang.reflect.Method)((MethodInfoImpl) methodInfo).cdiDeclaration.getJavaMember(), bm); } else { // TODO better exception throw new IllegalArgumentException("Custom implementations of MethodInfo are not supported!");