diff --git a/extensions/spring-di/deployment/pom.xml b/extensions/spring-di/deployment/pom.xml index 565c46f63bf0f..24f4a05d46599 100644 --- a/extensions/spring-di/deployment/pom.xml +++ b/extensions/spring-di/deployment/pom.xml @@ -28,6 +28,11 @@ quarkus-junit5-internal test + + org.assertj + assertj-core + test + diff --git a/extensions/spring-di/deployment/src/main/java/io/quarkus/spring/di/deployment/SpringDIProcessor.java b/extensions/spring-di/deployment/src/main/java/io/quarkus/spring/di/deployment/SpringDIProcessor.java index 15ea530b98433..1c0ea355fa5de 100644 --- a/extensions/spring-di/deployment/src/main/java/io/quarkus/spring/di/deployment/SpringDIProcessor.java +++ b/extensions/spring-di/deployment/src/main/java/io/quarkus/spring/di/deployment/SpringDIProcessor.java @@ -24,6 +24,8 @@ import org.jboss.jandex.FieldInfo; import org.jboss.jandex.IndexView; import org.jboss.jandex.MethodInfo; +import org.jboss.jandex.MethodParameterInfo; +import org.jboss.jandex.Type; import io.quarkus.arc.deployment.AdditionalStereotypeBuildItem; import io.quarkus.arc.deployment.AnnotationsTransformerBuildItem; @@ -76,6 +78,7 @@ public class SpringDIProcessor { private static final DotName CDI_NAMED_ANNOTATION = DotNames.NAMED; private static final DotName CDI_INJECT_ANNOTATION = DotNames.INJECT; private static final DotName CDI_PRODUCES_ANNOTATION = DotNames.PRODUCES; + private static final DotName QUARKUS_ALL_ANNOTATION = DotNames.ALL; private static final DotName MP_CONFIG_PROPERTY_ANNOTATION = DotName.createSimple(ConfigProperty.class.getName()); @BuildStep @@ -384,6 +387,14 @@ Set getAnnotationsToAdd( Collections.singletonList((AnnotationValue.createStringValue("value", value))))); } } + + // in Spring List means that all instances of SomeBean should be injected + if (fieldInfo.type().name().equals(DotNames.LIST)) { + annotationsToAdd.add(create( + QUARKUS_ALL_ANNOTATION, + target, + Collections.emptyList())); + } } else if (fieldInfo.hasAnnotation(SPRING_VALUE_ANNOTATION)) { final AnnotationInstance annotation = fieldInfo.annotation(SPRING_VALUE_ANNOTATION); addSpringValueAnnotations(target, annotation, true, annotationsToAdd); @@ -418,6 +429,18 @@ Set getAnnotationsToAdd( CDI_INJECT_ANNOTATION, target, Collections.emptyList())); + // in Spring List means that all instances of SomeBean should be injected + List parameters = methodInfo.parameters(); + for (int i = 0; i < parameters.size(); i++) { + Type parameter = parameters.get(i); + if (parameter.name().equals(DotNames.LIST)) { + annotationsToAdd.add(create( + QUARKUS_ALL_ANNOTATION, + MethodParameterInfo.create(methodInfo, (short) i), + Collections.emptyList())); + } + } + } // add method parameter conversion annotations diff --git a/extensions/spring-di/deployment/src/test/java/io/quarkus/spring/di/deployment/ListOfBeansTest.java b/extensions/spring-di/deployment/src/test/java/io/quarkus/spring/di/deployment/ListOfBeansTest.java new file mode 100644 index 0000000000000..c1197cee9628c --- /dev/null +++ b/extensions/spring-di/deployment/src/test/java/io/quarkus/spring/di/deployment/ListOfBeansTest.java @@ -0,0 +1,94 @@ +package io.quarkus.spring.di.deployment; + +import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat; + +import java.util.List; + +import javax.inject.Inject; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Repository; + +import io.quarkus.test.QuarkusUnitTest; + +public class ListOfBeansTest { + + @RegisterExtension + static final QuarkusUnitTest config = new QuarkusUnitTest() + .withApplicationRoot((jar) -> jar + .addClasses(Foo.class, ServiceAlpha.class, ServiceBravo.class, Service.class, + Converter.class, ConverterAlpha.class, ConverterBravo.class)); + + @Inject + Foo foo; + + @Test + public void testInjection() { + assertThat(foo.services).hasSize(2).extractingResultOf("ping").containsExactlyInAnyOrder("alpha", "bravo"); + assertThat(foo.converters).hasSize(2).extractingResultOf("pong").containsExactlyInAnyOrder("alpha", "bravo"); + } + + @org.springframework.stereotype.Service + public static class Foo { + + @Autowired + List services; + + final List converters; + + @Autowired + Foo(List converters) { + this.converters = converters; + } + + } + + public interface Service { + + String ping(); + } + + public interface Converter { + + String pong(); + } + + @Component + public static class ServiceAlpha implements Service { + + public String ping() { + return "alpha"; + } + } + + @Component + public static class ServiceBravo implements Service { + + public String ping() { + return "bravo"; + } + } + + @org.springframework.stereotype.Service + public static class ConverterAlpha implements Converter { + + @Override + public String pong() { + return "alpha"; + } + + } + + @Repository + public static class ConverterBravo implements Converter { + + @Override + public String pong() { + return "bravo"; + } + + } +}