Skip to content

Commit

Permalink
ArC: fix treatment of injection points with @nAmed without value
Browse files Browse the repository at this point in the history
The specification is clear that field injection points with `@Named`
without value should use `@Named(fieldName)` as the qualifier. Other
such injection points lead to a definition error.
  • Loading branch information
Ladicek committed Jan 24, 2023
1 parent 0182e66 commit b5d825a
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Predicate;

import javax.enterprise.inject.spi.DefinitionException;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.AnnotationTarget;
import org.jboss.jandex.AnnotationTarget.Kind;
import org.jboss.jandex.AnnotationValue;
import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName;
import org.jboss.jandex.FieldInfo;
Expand All @@ -31,12 +34,28 @@
*/
public class InjectionPointInfo {

private static boolean isNamedWithoutValue(AnnotationInstance annotation) {
if (annotation.name().equals(DotNames.NAMED)) {
AnnotationValue name = annotation.value();
return name == null || name.asString().isEmpty();
}
return false;
}

static InjectionPointInfo fromField(FieldInfo field, ClassInfo beanClass, BeanDeployment beanDeployment,
InjectionPointModifier transformer) {
Set<AnnotationInstance> qualifiers = new HashSet<>();
Collection<AnnotationInstance> annotations = beanDeployment.getAnnotations(field);
for (AnnotationInstance annotation : annotations) {
beanDeployment.extractQualifiers(annotation).forEach(qualifiers::add);
for (AnnotationInstance annotationInstance : beanDeployment.extractQualifiers(annotation)) {
// if the qualifier is `@Named` without value, replace it with `@Named(fieldName)
if (isNamedWithoutValue(annotationInstance)) {
annotationInstance = AnnotationInstance.builder(annotationInstance.name())
.value(field.name())
.buildWithTarget(annotationInstance.target());
}
qualifiers.add(annotationInstance);
}
}
Type type = resolveType(field.type(), beanClass, field.declaringClass(), beanDeployment);
return new InjectionPointInfo(type,
Expand Down Expand Up @@ -70,7 +89,12 @@ static List<InjectionPointInfo> fromMethod(MethodInfo method, ClassInfo beanClas
}
Set<AnnotationInstance> paramQualifiers = new HashSet<>();
for (AnnotationInstance paramAnnotation : paramAnnotations) {
beanDeployment.extractQualifiers(paramAnnotation).forEach(paramQualifiers::add);
for (AnnotationInstance annotationInstance : beanDeployment.extractQualifiers(paramAnnotation)) {
if (isNamedWithoutValue(annotationInstance)) {
throw new DefinitionException("@Named without value may not be used on method parameter: " + method);
}
paramQualifiers.add(annotationInstance);
}
}
Type type = resolveType(paramType, beanClass, method.declaringClass(), beanDeployment);
injectionPoints.add(new InjectionPointInfo(type,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.quarkus.arc.test.name;

import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import javax.enterprise.context.Dependent;
import javax.enterprise.inject.spi.DefinitionException;
import javax.inject.Inject;
import javax.inject.Named;

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

import io.quarkus.arc.test.ArcTestContainer;

public class InvalidNamedInjectionPointTest {

@RegisterExtension
public ArcTestContainer container = ArcTestContainer.builder()
.beanClasses(Foo.class, Consumer.class)
.shouldFail()
.build();

@Test
public void test() {
assertNotNull(container.getFailure());
assertInstanceOf(DefinitionException.class, container.getFailure());
assertTrue(container.getFailure().getMessage().contains("@Named without value may not be used on method parameter"));
}

@Named("foo")
@Dependent
static class Foo {
}

@Dependent
static class Consumer {
@Inject
Consumer(@Named Foo foo) {
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.literal.NamedLiteral;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;

Expand All @@ -18,7 +19,7 @@
public class NameResolutionTest {

@RegisterExtension
public ArcTestContainer container = new ArcTestContainer(Bravo.class, Alpha.class);
public ArcTestContainer container = new ArcTestContainer(Bravo.class, Alpha.class, Consumer.class);

@Test
public void testBeanNames() {
Expand All @@ -29,6 +30,10 @@ public void testBeanNames() {
assertEquals(1, Arc.container().beanManager().getBeans("bongo").size());
// Test that for defaulted name the @Named qualifier is replaced the defaulted value
assertEquals("bing", Arc.container().instance(String.class, NamedLiteral.of("producedBing")).get());

Consumer consumer = Arc.container().instance(Consumer.class).get();
assertEquals("bing", consumer.producedBing);
assertEquals(12345, consumer.bongo);
}

@Named("A")
Expand All @@ -53,4 +58,14 @@ Integer getBongo() {

}

@Dependent
static class Consumer {
@Inject
@Named
String producedBing;

@Inject
@Named
Integer bongo;
}
}

0 comments on commit b5d825a

Please sign in to comment.