Skip to content

Commit

Permalink
Merge pull request #20097 from mkouba/arc-qualifier-default-values-bug
Browse files Browse the repository at this point in the history
ArC bean resolution - handle qualifier default values correctly
  • Loading branch information
mkouba authored Sep 15, 2021
2 parents 5fe9d4c + e8fad02 commit 8f1fa77
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,13 @@
import io.grpc.Channel;
import io.quarkus.arc.deployment.AdditionalBeanBuildItem;
import io.quarkus.arc.deployment.BeanDiscoveryFinishedBuildItem;
import io.quarkus.arc.deployment.InjectionPointTransformerBuildItem;
import io.quarkus.arc.deployment.SyntheticBeanBuildItem;
import io.quarkus.arc.deployment.UnremovableBeanBuildItem;
import io.quarkus.arc.processor.Annotations;
import io.quarkus.arc.processor.DotNames;
import io.quarkus.arc.processor.InjectionPointInfo;
import io.quarkus.arc.processor.InjectionPointsTransformer;
import io.quarkus.deployment.annotations.BuildProducer;
import io.quarkus.deployment.annotations.BuildStep;
import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
Expand Down Expand Up @@ -277,6 +280,39 @@ public void validateInjectedServiceInterfaces(CombinedIndexBuildItem index,
}
}

@BuildStep
InjectionPointTransformerBuildItem transformInjectionPoints() {
return new InjectionPointTransformerBuildItem(new InjectionPointsTransformer() {

@Override
public void transform(TransformationContext ctx) {
// If annotated with @GrpcClient and no explicit value is used, i.e. @GrpcClient(),
// then we need to determine the service name from the annotated element and transform the injection point
AnnotationInstance clientAnnotation = Annotations.find(ctx.getQualifiers(), GrpcDotNames.GRPC_CLIENT);
if (clientAnnotation != null && clientAnnotation.value() == null) {
String clientName = null;
if (ctx.getTarget().kind() == Kind.FIELD) {
clientName = clientAnnotation.target().asField().name();
} else if (ctx.getTarget().kind() == Kind.METHOD_PARAMETER) {
MethodParameterInfo param = clientAnnotation.target().asMethodParameter();
// We don't need to check if parameter names are recorded - that's validated elsewhere
clientName = param.method().parameterName(param.position());
}
if (clientName != null) {
ctx.transform().remove(GrpcDotNames::isGrpcClient)
.add(GrpcDotNames.GRPC_CLIENT, AnnotationValue.createStringValue("value", clientName)).done();
}
}
}

@Override
public boolean appliesTo(Type requiredType) {
return true;
}

});
}

private DeploymentException invalidInjectionPoint(InjectionPointInfo injectionPoint) {
return new DeploymentException(
injectionPoint.getRequiredType() + " cannot be injected into " + injectionPoint.getTargetInfo()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.function.BiFunction;

import org.jboss.jandex.AnnotationInstance;
import org.jboss.jandex.DotName;

import io.grpc.BindableService;
Expand Down Expand Up @@ -60,4 +61,8 @@ public class GrpcDotNames {
static final MethodDescriptor GET_STUB_CONFIGURATOR = MethodDescriptor.ofMethod(GrpcClientConfigProvider.class,
"getStubConfigurator", BiFunction.class);

static boolean isGrpcClient(AnnotationInstance instance) {
return instance.name().equals(GRPC_CLIENT);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ static boolean hasQualifier(BeanDeployment beanDeployment, AnnotationInstance re
ClassInfo requiredClazz = beanDeployment.getQualifier(requiredQualifier.name());
List<AnnotationValue> values = new ArrayList<>();
Set<String> nonBindingFields = beanDeployment.getQualifierNonbindingMembers(requiredQualifier.name());
for (AnnotationValue val : requiredQualifier.values()) {
for (AnnotationValue val : requiredQualifier.valuesWithDefaults(beanDeployment.getBeanArchiveIndex())) {
if (!requiredClazz.method(val.name()).hasAnnotation(DotNames.NONBINDING)
&& !nonBindingFields.contains(val.name())) {
values.add(val);
Expand All @@ -695,7 +695,7 @@ static boolean hasQualifier(BeanDeployment beanDeployment, AnnotationInstance re
// Must have the same annotation member value for each member which is not annotated @Nonbinding
boolean matches = true;
for (AnnotationValue value : values) {
if (!value.equals(qualifier.value(value.name()))) {
if (!value.equals(qualifier.valueWithDefault(beanDeployment.getBeanArchiveIndex(), value.name()))) {
matches = false;
break;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.quarkus.arc.test.qualifiers.defaultvalues;

public interface Animal {

int noOfLeg();

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.quarkus.arc.test.qualifiers.defaultvalues;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.TYPE })
public @interface AnimalQualifier {

String value() default "";

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.quarkus.arc.test.qualifiers.defaultvalues;

import javax.enterprise.context.Dependent;

@Dependent
@AnimalQualifier("cat")
public class Cat implements Animal {

@Override
public int noOfLeg() {
return 4;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package io.quarkus.arc.test.qualifiers.defaultvalues;

import javax.enterprise.context.Dependent;

@Dependent
@AnimalQualifier
public class Owl implements Animal {

@Override
public int noOfLeg() {
return 2;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.quarkus.arc.test.qualifiers.defaultvalues;

import static org.junit.jupiter.api.Assertions.assertEquals;

import io.quarkus.arc.Arc;
import io.quarkus.arc.test.ArcTestContainer;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

public class QualifierDefaultValuesTest {

@RegisterExtension
public ArcTestContainer container = new ArcTestContainer(Consumer.class, Animal.class, AnimalQualifier.class, Cat.class,
Owl.class);

@Test
public void testDefaultValues() {
Consumer consumer = Arc.container().instance(Consumer.class).get();
assertEquals(2, consumer.animal.noOfLeg());
}

@Dependent
public static class Consumer {

@Inject
@AnimalQualifier
Animal animal;

}

}

0 comments on commit 8f1fa77

Please sign in to comment.