From b842d28a2f63bf450f49f6b9d0e2910e9db91334 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Fri, 11 Jan 2019 20:00:00 +0200 Subject: [PATCH 1/2] Add simple Spring DI support Support is provided my mapping Spring DI annotations to their CDI counterparts leveraging the annotation transformation mechanism that Arc provides --- build-parent/pom.xml | 7 +- extensions/pom.xml | 3 + extensions/spring-di/deployment/pom.xml | 50 ++++ .../spring/deployment/SpringDIProcessor.java | 273 ++++++++++++++++++ extensions/spring-di/pom.xml | 35 +++ .../jboss/protean/arc/processor/Beans.java | 9 +- .../arc/processor/InjectionPointInfo.java | 4 +- integration-tests/pom.xml | 1 + integration-tests/spring-di/pom.xml | 133 +++++++++ .../spring/tests/AppConfiguration.java | 31 ++ .../jboss/shamrock/spring/tests/Dummy.java | 23 ++ .../shamrock/spring/tests/GreeterBean.java | 48 +++ .../tests/InjectedSpringBeansResource.java | 36 +++ .../spring/tests/MessageProducer.java | 31 ++ .../tests/MultiplierStringFunction.java | 28 ++ .../shamrock/spring/tests/MyApplication.java | 25 ++ .../tests/NoOpSingleStringFunction.java | 28 ++ .../shamrock/spring/tests/OtherDummy.java | 30 ++ .../shamrock/spring/tests/StringFunction.java | 23 ++ .../META-INF/microprofile-config.properties | 2 + .../tests/InjectedSpringBeansResourceIT.java | 24 ++ .../InjectedSpringBeansResourceTest.java | 34 +++ 22 files changed, 872 insertions(+), 6 deletions(-) create mode 100644 extensions/spring-di/deployment/pom.xml create mode 100644 extensions/spring-di/deployment/src/main/java/org/jboss/shamrock/spring/deployment/SpringDIProcessor.java create mode 100644 extensions/spring-di/pom.xml create mode 100644 integration-tests/spring-di/pom.xml create mode 100644 integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/AppConfiguration.java create mode 100644 integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/Dummy.java create mode 100644 integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/GreeterBean.java create mode 100644 integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResource.java create mode 100644 integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MessageProducer.java create mode 100644 integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MultiplierStringFunction.java create mode 100644 integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MyApplication.java create mode 100644 integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/NoOpSingleStringFunction.java create mode 100644 integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/OtherDummy.java create mode 100644 integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/StringFunction.java create mode 100644 integration-tests/spring-di/src/main/resources/META-INF/microprofile-config.properties create mode 100644 integration-tests/spring-di/src/test/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResourceIT.java create mode 100644 integration-tests/spring-di/src/test/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResourceTest.java diff --git a/build-parent/pom.xml b/build-parent/pom.xml index 361bfc6a40b32..c1035ae2d8348 100644 --- a/build-parent/pom.xml +++ b/build-parent/pom.xml @@ -401,6 +401,11 @@ shamrock-reactive-messaging-runtime ${project.version} + + org.jboss.shamrock + shamrock-spring-di-deployment + ${project.version} + org.jboss.logging jboss-logging-embedded @@ -1138,7 +1143,7 @@ quartz ${quartz.version} - + io.smallrye.reactive smallrye-reactive-messaging-provider diff --git a/extensions/pom.xml b/extensions/pom.xml index 38c97b87b6d59..8f8bb4b1827e8 100644 --- a/extensions/pom.xml +++ b/extensions/pom.xml @@ -62,6 +62,9 @@ jdbc jpa bean-validation + + + spring-di diff --git a/extensions/spring-di/deployment/pom.xml b/extensions/spring-di/deployment/pom.xml new file mode 100644 index 0000000000000..83a2963912c1c --- /dev/null +++ b/extensions/spring-di/deployment/pom.xml @@ -0,0 +1,50 @@ + + + + + shamrock-spring-di + org.jboss.shamrock + 1.0.0.Alpha1-SNAPSHOT + ../ + + + 4.0.0 + + shamrock-spring-di-deployment + Shamrock - Spring - DI - Deployment + + + + org.jboss.shamrock + shamrock-core-deployment + + + org.jboss.shamrock + shamrock-arc-deployment + + + + org.jboss.shamrock + shamrock-junit + + + + + + \ No newline at end of file diff --git a/extensions/spring-di/deployment/src/main/java/org/jboss/shamrock/spring/deployment/SpringDIProcessor.java b/extensions/spring-di/deployment/src/main/java/org/jboss/shamrock/spring/deployment/SpringDIProcessor.java new file mode 100644 index 0000000000000..56863d4626d22 --- /dev/null +++ b/extensions/spring-di/deployment/src/main/java/org/jboss/shamrock/spring/deployment/SpringDIProcessor.java @@ -0,0 +1,273 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.deployment; + +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.jboss.jandex.*; +import org.jboss.logging.Logger; +import org.jboss.protean.arc.processor.AnnotationsTransformer; +import org.jboss.protean.arc.processor.DotNames; +import org.jboss.protean.arc.processor.ScopeInfo; +import org.jboss.protean.arc.processor.Transformation; +import org.jboss.shamrock.annotations.BuildStep; +import org.jboss.shamrock.arc.deployment.AnnotationsTransformerBuildItem; + +import javax.enterprise.context.ApplicationScoped; +import javax.enterprise.context.Dependent; +import javax.enterprise.inject.Produces; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import static org.jboss.jandex.AnnotationInstance.create; + +/* + * A simple processor that maps annotations Spring DI annotation to CDI annotation + * Arc's handling of annotation mapping (by creating an extra abstraction layer on top of the Jandex index) + * suits this sort of handling perfectly + */ +public class SpringDIProcessor { + + private static final Logger LOGGER = Logger.getLogger("org.jboss.shamrock.spring.deployment.SpringProcessor"); + + private static final DotName SPRING_SCOPE_ANNOTATION + = DotName.createSimple("org.springframework.context.annotation.Scope"); + + private static final DotName[] SPRING_STEREOTYPE_ANNOTATIONS = { + DotName.createSimple("org.springframework.stereotype.Component"), + DotName.createSimple("org.springframework.stereotype.Service"), + DotName.createSimple("org.springframework.stereotype.Repository"), + }; + + private static final DotName CONFIGURATION_ANNOTATION + = DotName.createSimple("org.springframework.context.annotation.Configuration"); + + private static final DotName BEAN_ANNOTATION + = DotName.createSimple("org.springframework.context.annotation.Bean"); + + private static final DotName AUTOWIRED_ANNOTATION + = DotName.createSimple("org.springframework.beans.factory.annotation.Autowired"); + + private static final DotName SPRING_QUALIFIER_ANNOTATION + = DotName.createSimple("org.springframework.beans.factory.annotation.Qualifier"); + + private static final DotName VALUE_ANNOTATION + = DotName.createSimple("org.springframework.beans.factory.annotation.Value"); + + private static final DotName CDI_SINGLETON_ANNOTATION = ScopeInfo.SINGLETON.getDotName(); + private static final DotName CDI_DEPENDENT_ANNOTATION = ScopeInfo.DEPENDENT.getDotName(); + private static final DotName CDI_APP_SCOPED_ANNOTATION = ScopeInfo.APPLICATION.getDotName(); + 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 MP_CONFIG_PROPERTY_ANNOTATION = DotName.createSimple(ConfigProperty.class.getName()); + + @BuildStep + AnnotationsTransformerBuildItem beanTransformer() { + return new AnnotationsTransformerBuildItem(new AnnotationsTransformer() { + @Override + public void transform(TransformationContext context) { + if (context.getAnnotations().isEmpty()) { + return; + } + + final Set annotationsToAdd = new HashSet<>(); + + //if it's a class, it's a Bean or a Bean producer + if(context.isClass()) { + final ClassInfo classInfo = context.getTarget().asClass(); + for (DotName springStereotypeAnnotation : SPRING_STEREOTYPE_ANNOTATIONS) { + if (classInfo.annotations().containsKey(springStereotypeAnnotation)) { + //we use Singleton as the default scope (since that's what Spring DI does) + //but will switch to Dependent if the is a Scope annotation with the value of prototype + DotName cdiAnnotation = CDI_SINGLETON_ANNOTATION; + if (classInfo.annotations().containsKey(SPRING_SCOPE_ANNOTATION)) { + final AnnotationInstance annotation = classInfo.classAnnotation(SPRING_SCOPE_ANNOTATION); + final AnnotationValue springScopeAnnotationValue = annotation.value(); + if(springScopeAnnotationValue != null && + "prototype".equals(springScopeAnnotationValue.asString())) { + cdiAnnotation = CDI_DEPENDENT_ANNOTATION; + } + } + annotationsToAdd.add(create( + cdiAnnotation, + context.getTarget(), + new ArrayList<>() + )); + + //check if the spring annotation defines a name for the bean + final AnnotationValue beanNameAnnotationValue + = classInfo.classAnnotation(springStereotypeAnnotation).value(); + addCDINamedAnnotation(context, beanNameAnnotationValue, annotationsToAdd); + + break; + } + } + + if (classInfo.annotations().containsKey(CONFIGURATION_ANNOTATION)) { + annotationsToAdd.add(create( + CDI_APP_SCOPED_ANNOTATION, + context.getTarget(), + new ArrayList<>() + )); + + } + } else if(context.isField()) { // here we check for @Autowired and @Value annotations + final FieldInfo fieldInfo = context.getTarget().asField(); + if (fieldInfo.hasAnnotation(AUTOWIRED_ANNOTATION)) { + annotationsToAdd.add(create( + CDI_INJECT_ANNOTATION, + context.getTarget(), + new ArrayList<>() + )); + + if (fieldInfo.hasAnnotation(SPRING_QUALIFIER_ANNOTATION)) { + final AnnotationInstance annotation = fieldInfo.annotation(SPRING_QUALIFIER_ANNOTATION); + final AnnotationValue annotationValue = annotation.value(); + if (annotationValue != null) { + final String value = annotationValue.asString(); + annotationsToAdd.add(create( + CDI_NAMED_ANNOTATION, + context.getTarget(), + new ArrayList() {{ + add(AnnotationValue.createStringValue("value", value)); + }} + )); + } + } + } else if (fieldInfo.hasAnnotation(VALUE_ANNOTATION)) { + final AnnotationInstance annotation = fieldInfo.annotation(VALUE_ANNOTATION); + final AnnotationValue annotationValue = annotation.value(); + if (annotationValue != null) { + String defaultValue = null; + String propertyName = annotationValue.asString().replace("${", "").replace("}", ""); + if (propertyName.contains(":")) { + final int index = propertyName.indexOf(':'); + if (index < propertyName.length() - 1) { + defaultValue = propertyName.substring(index + 1); + } + propertyName = propertyName.substring(0, index); + + } + final List annotationValues = new ArrayList<>(); + annotationValues.add(AnnotationValue.createStringValue("name", propertyName)); + if (defaultValue != null && !defaultValue.isEmpty()) { + annotationValues.add(AnnotationValue.createStringValue("defaultValue", defaultValue)); + } + annotationsToAdd.add(create( + MP_CONFIG_PROPERTY_ANNOTATION, + context.getTarget(), + annotationValues + )); + annotationsToAdd.add(create( + CDI_INJECT_ANNOTATION, + context.getTarget(), + new ArrayList<>() + )); + } + } + } else if (context.isMethod()) { + final MethodInfo methodInfo = context.getTarget().asMethod(); + if (methodInfo.hasAnnotation(BEAN_ANNOTATION)) { + annotationsToAdd.add(create( + CDI_PRODUCES_ANNOTATION, + context.getTarget(), + new ArrayList<>() + )); + annotationsToAdd.add(create( + CDI_DEPENDENT_ANNOTATION, + context.getTarget(), + new ArrayList<>() + )); + + //check if the spring annotation defines a name for the bean + final AnnotationValue beanNameAnnotationValue + = methodInfo.annotation(BEAN_ANNOTATION).value("name"); + final AnnotationValue beanValueAnnotationValue + = methodInfo.annotation(BEAN_ANNOTATION).value("value"); + if(!addCDINamedAnnotation(context, beanNameAnnotationValue, annotationsToAdd)) { + addCDINamedAnnotation(context, beanValueAnnotationValue, annotationsToAdd); + } + } + + // add method parameter conversion annotations + for (AnnotationInstance annotation : methodInfo.annotations()) { + if (annotation.target().kind() == AnnotationTarget.Kind.METHOD_PARAMETER && annotation.name().equals(SPRING_QUALIFIER_ANNOTATION)) { + final AnnotationValue annotationValue = annotation.value(); + if (annotationValue != null) { + final String value = annotationValue.asString(); + annotationsToAdd.add(create( + CDI_NAMED_ANNOTATION, + annotation.target(), + new ArrayList() {{ + add(AnnotationValue.createStringValue("value", value)); + }} + )); + } + } + } + + } + + if(!annotationsToAdd.isEmpty()) { + final Transformation transform = context.transform(); + for (AnnotationInstance annotationInstance : annotationsToAdd) { + transform.add(annotationInstance); + } + transform.done(); + } + } + + private boolean addCDINamedAnnotation(TransformationContext context, + AnnotationValue annotationValue, + Set annotationsToAdd) { + if (annotationValue == null) { + return false; + } + + final String beanName = determineName(annotationValue); + if (beanName != null && !"".equals(beanName)) { + annotationsToAdd.add(create( + CDI_NAMED_ANNOTATION, + context.getTarget(), + new ArrayList() {{ + add(AnnotationValue.createStringValue("value", beanName)); + }} + )); + + return true; + } + + return false; + } + + private String determineName(AnnotationValue annotationValue) { + final String className = annotationValue.getClass().getName(); + if (className.contains("ArrayValue")) { + return annotationValue.asStringArray()[0]; + } else if (className.contains("StringValue")) { + return annotationValue.asString(); + } + return null; + } + }); + } +} diff --git a/extensions/spring-di/pom.xml b/extensions/spring-di/pom.xml new file mode 100644 index 0000000000000..502e3aa2d05f3 --- /dev/null +++ b/extensions/spring-di/pom.xml @@ -0,0 +1,35 @@ + + + + + + shamrock-build-parent + org.jboss.shamrock + 1.0.0.Alpha1-SNAPSHOT + ../../build-parent/pom.xml + + 4.0.0 + + shamrock-spring-di + Shamrock - Spring - DI + pom + + deployment + + \ No newline at end of file diff --git a/independent-projects/arc/processor/src/main/java/org/jboss/protean/arc/processor/Beans.java b/independent-projects/arc/processor/src/main/java/org/jboss/protean/arc/processor/Beans.java index ec4325af698a6..7b0936fb87ec9 100644 --- a/independent-projects/arc/processor/src/main/java/org/jboss/protean/arc/processor/Beans.java +++ b/independent-projects/arc/processor/src/main/java/org/jboss/protean/arc/processor/Beans.java @@ -121,8 +121,11 @@ static BeanInfo createProducerMethod(MethodInfo producerMethod, BeanInfo declari List stereotypes = new ArrayList<>(); String name = null; - for (AnnotationInstance annotation : producerMethod.annotations()) { - if (beanDeployment.getQualifier(annotation.name()) != null) { + for (AnnotationInstance annotation : beanDeployment.getAnnotations(producerMethod)) { + //only check for method annotations since at this point we will get both + // method and method param annotations + if (annotation.target().kind() == AnnotationTarget.Kind.METHOD + && beanDeployment.getQualifier(annotation.name()) != null) { qualifiers.add(annotation); if (DotNames.NAMED.equals(annotation.name())) { AnnotationValue nameValue = annotation.value(); @@ -186,7 +189,7 @@ static BeanInfo createProducerField(FieldInfo producerField, BeanInfo declaringB List stereotypes = new ArrayList<>(); String name = null; - for (AnnotationInstance annotation : producerField.annotations()) { + for (AnnotationInstance annotation : beanDeployment.getAnnotations(producerField)) { if (beanDeployment.getQualifier(annotation.name()) != null) { qualifiers.add(annotation); if (DotNames.NAMED.equals(annotation.name())) { diff --git a/independent-projects/arc/processor/src/main/java/org/jboss/protean/arc/processor/InjectionPointInfo.java b/independent-projects/arc/processor/src/main/java/org/jboss/protean/arc/processor/InjectionPointInfo.java index ec3109f01eace..1406a0cea8e24 100644 --- a/independent-projects/arc/processor/src/main/java/org/jboss/protean/arc/processor/InjectionPointInfo.java +++ b/independent-projects/arc/processor/src/main/java/org/jboss/protean/arc/processor/InjectionPointInfo.java @@ -39,7 +39,7 @@ public class InjectionPointInfo { static InjectionPointInfo fromField(FieldInfo field, BeanDeployment beanDeployment) { Set qualifiers = new HashSet<>(); - for (AnnotationInstance annotation : field.annotations()) { + for (AnnotationInstance annotation : beanDeployment.getAnnotations(field)) { if (beanDeployment.getQualifier(annotation.name()) != null) { qualifiers.add(annotation); } @@ -60,7 +60,7 @@ static List fromMethod(MethodInfo method, BeanDeployment bea for (ListIterator iterator = method.parameters().listIterator(); iterator.hasNext();) { Type paramType = iterator.next(); Set paramAnnotations = new HashSet<>(); - for (AnnotationInstance annotation : method.annotations()) { + for (AnnotationInstance annotation : beanDeployment.getAnnotations(method)) { if (org.jboss.jandex.AnnotationTarget.Kind.METHOD_PARAMETER.equals(annotation.target().kind()) && annotation.target().asMethodParameter().position() == iterator.previousIndex()) { paramAnnotations.add(annotation); diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index 4d2b146afd33b..18086b7d44609 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -47,5 +47,6 @@ jpa-mariadb jpa-h2 vertx + spring-di diff --git a/integration-tests/spring-di/pom.xml b/integration-tests/spring-di/pom.xml new file mode 100644 index 0000000000000..dc3420824b418 --- /dev/null +++ b/integration-tests/spring-di/pom.xml @@ -0,0 +1,133 @@ + + + + 4.0.0 + + + shamrock-integration-tests-parent + org.jboss.shamrock + 1.0.0.Alpha1-SNAPSHOT + ../ + + + shamrock-integration-test-spring-di + Shamrock - Integration Tests - Spring DI + + + + org.jboss.shamrock + shamrock-jaxrs-deployment + provided + + + org.jboss.shamrock + shamrock-arc-deployment + provided + + + org.jboss.shamrock + shamrock-spring-di-deployment + provided + + + + org.springframework + spring-context + 5.1.4.RELEASE + + + + org.jboss.shamrock + shamrock-junit + test + + + io.rest-assured + rest-assured + test + + + + + + + ${project.groupId} + shamrock-maven-plugin + ${project.version} + + + + build + + + + + + + + + + native-image + + + native + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + + + + + + + ${project.groupId} + shamrock-maven-plugin + ${project.version} + + + native-image + + native-image + + + true + true + ${graalvmHome} + + + + + + + + + \ No newline at end of file diff --git a/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/AppConfiguration.java b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/AppConfiguration.java new file mode 100644 index 0000000000000..e12c12770fb82 --- /dev/null +++ b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/AppConfiguration.java @@ -0,0 +1,31 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class AppConfiguration { + + @Bean(name = "cap") + public StringFunction capitalizer(@Qualifier("dumb") Dummy notUsedJustMakingSureDIInMethodsWorks, + OtherDummy alsoNotUsed) { + return String::toUpperCase; + } +} diff --git a/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/Dummy.java b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/Dummy.java new file mode 100644 index 0000000000000..696c66c8415bb --- /dev/null +++ b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/Dummy.java @@ -0,0 +1,23 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import org.springframework.stereotype.Repository; + +@Repository("dumb") +public class Dummy { +} diff --git a/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/GreeterBean.java b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/GreeterBean.java new file mode 100644 index 0000000000000..35aa929845dc3 --- /dev/null +++ b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/GreeterBean.java @@ -0,0 +1,48 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class GreeterBean { + + private final MessageProducer messageProducer; + + @Autowired + @Qualifier("noop") + private StringFunction noopStringFunction; + + @Autowired + @Qualifier("cap") + private StringFunction capitalizerStringFunction; + + @Value("${greeting.suffix:!}") + private String suffix; + + public GreeterBean(MessageProducer messageProducer) { + this.messageProducer = messageProducer; + } + + public String greet(String name) { + final String initialValue = messageProducer.getPrefix() + " " + name + suffix; + return noopStringFunction.andThen(capitalizerStringFunction).apply(initialValue); + } +} diff --git a/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResource.java b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResource.java new file mode 100644 index 0000000000000..d982edbe6b83e --- /dev/null +++ b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResource.java @@ -0,0 +1,36 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import javax.inject.Inject; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/") +public class InjectedSpringBeansResource { + + @Inject + private GreeterBean greeterBean; + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return greeterBean.greet("world"); + } +} diff --git a/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MessageProducer.java b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MessageProducer.java new file mode 100644 index 0000000000000..fd81e39ded3df --- /dev/null +++ b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MessageProducer.java @@ -0,0 +1,31 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +@Service +public class MessageProducer { + + @Value("${greeting.message}") + private String message; + + public String getPrefix() { + return message; + } +} diff --git a/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MultiplierStringFunction.java b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MultiplierStringFunction.java new file mode 100644 index 0000000000000..b0cdb6b6d31b8 --- /dev/null +++ b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MultiplierStringFunction.java @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import org.springframework.stereotype.Component; + +@Component("multiply") +public class MultiplierStringFunction implements StringFunction { + + @Override + public String apply(String input) { + return String.format("%s%s", input, input); + } +} diff --git a/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MyApplication.java b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MyApplication.java new file mode 100644 index 0000000000000..30be655c9d644 --- /dev/null +++ b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/MyApplication.java @@ -0,0 +1,25 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import javax.ws.rs.ApplicationPath; +import javax.ws.rs.core.Application; + +@ApplicationPath("/spring-test") +public class MyApplication extends Application { + +} \ No newline at end of file diff --git a/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/NoOpSingleStringFunction.java b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/NoOpSingleStringFunction.java new file mode 100644 index 0000000000000..3c7bbf5680b0a --- /dev/null +++ b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/NoOpSingleStringFunction.java @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import org.springframework.stereotype.Component; + +@Component("noop") +public class NoOpSingleStringFunction implements StringFunction { + + @Override + public String apply(String s) { + return s; + } +} diff --git a/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/OtherDummy.java b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/OtherDummy.java new file mode 100644 index 0000000000000..6abf2fd50614b --- /dev/null +++ b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/OtherDummy.java @@ -0,0 +1,30 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +@Component +public class OtherDummy { + + private final Dummy dummy; + + public OtherDummy(@Qualifier("dumb") Dummy dummy) { + this.dummy = dummy; + } +} diff --git a/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/StringFunction.java b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/StringFunction.java new file mode 100644 index 0000000000000..b38d7f93ad5ce --- /dev/null +++ b/integration-tests/spring-di/src/main/java/org/jboss/shamrock/spring/tests/StringFunction.java @@ -0,0 +1,23 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import java.util.function.Function; + +public interface StringFunction extends Function { + +} diff --git a/integration-tests/spring-di/src/main/resources/META-INF/microprofile-config.properties b/integration-tests/spring-di/src/main/resources/META-INF/microprofile-config.properties new file mode 100644 index 0000000000000..30cf8b632b4ca --- /dev/null +++ b/integration-tests/spring-di/src/main/resources/META-INF/microprofile-config.properties @@ -0,0 +1,2 @@ +# Your configuration properties +greeting.message = yolo diff --git a/integration-tests/spring-di/src/test/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResourceIT.java b/integration-tests/spring-di/src/test/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResourceIT.java new file mode 100644 index 0000000000000..3004e03555ecf --- /dev/null +++ b/integration-tests/spring-di/src/test/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResourceIT.java @@ -0,0 +1,24 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import org.jboss.shamrock.test.SubstrateTest; +import org.junit.runner.RunWith; + +@RunWith(SubstrateTest.class) +public class InjectedSpringBeansResourceIT extends InjectedSpringBeansResourceTest { +} diff --git a/integration-tests/spring-di/src/test/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResourceTest.java b/integration-tests/spring-di/src/test/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResourceTest.java new file mode 100644 index 0000000000000..03502644c5bd1 --- /dev/null +++ b/integration-tests/spring-di/src/test/java/org/jboss/shamrock/spring/tests/InjectedSpringBeansResourceTest.java @@ -0,0 +1,34 @@ +/* + * Copyright 2018 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jboss.shamrock.spring.tests; + +import io.restassured.RestAssured; +import org.jboss.shamrock.test.ShamrockTest; +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.hamcrest.Matchers.containsString; + +@RunWith(ShamrockTest.class) +public class InjectedSpringBeansResourceTest { + + @Test + public void testInjection() { + RestAssured.when().get("/spring-test").then() + .body(containsString("YOLO WORLD!")); + } +} From 9379f770f1cb67396023e8af80df2e6814726825 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Mon, 21 Jan 2019 07:44:34 +0200 Subject: [PATCH 2/2] Incorporate review comments --- bom/pom.xml | 7 +++++++ build-parent/pom.xml | 1 + .../shamrock/spring/deployment/SpringDIProcessor.java | 10 ++-------- integration-tests/spring-di/pom.xml | 2 +- 4 files changed, 11 insertions(+), 9 deletions(-) diff --git a/bom/pom.xml b/bom/pom.xml index e87436126ff49..dbf708891b4f8 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -172,6 +172,13 @@ provided + + org.jboss.shamrock + shamrock-spring-di-deployment + ${project.version} + provided + + org.jboss.shamrock shamrock-junit diff --git a/build-parent/pom.xml b/build-parent/pom.xml index c1035ae2d8348..05b8a16847fb9 100644 --- a/build-parent/pom.xml +++ b/build-parent/pom.xml @@ -102,6 +102,7 @@ 1.4.197 42.2.5 2.3.0 + 5.1.4.RELEASE 4.12 1.2.6 3.3.0 diff --git a/extensions/spring-di/deployment/src/main/java/org/jboss/shamrock/spring/deployment/SpringDIProcessor.java b/extensions/spring-di/deployment/src/main/java/org/jboss/shamrock/spring/deployment/SpringDIProcessor.java index 56863d4626d22..0036f9a16bb8c 100644 --- a/extensions/spring-di/deployment/src/main/java/org/jboss/shamrock/spring/deployment/SpringDIProcessor.java +++ b/extensions/spring-di/deployment/src/main/java/org/jboss/shamrock/spring/deployment/SpringDIProcessor.java @@ -26,12 +26,6 @@ import org.jboss.shamrock.annotations.BuildStep; import org.jboss.shamrock.arc.deployment.AnnotationsTransformerBuildItem; -import javax.enterprise.context.ApplicationScoped; -import javax.enterprise.context.Dependent; -import javax.enterprise.inject.Produces; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -261,9 +255,9 @@ private boolean addCDINamedAnnotation(TransformationContext context, private String determineName(AnnotationValue annotationValue) { final String className = annotationValue.getClass().getName(); - if (className.contains("ArrayValue")) { + if (annotationValue.kind() == AnnotationValue.Kind.ARRAY) { return annotationValue.asStringArray()[0]; - } else if (className.contains("StringValue")) { + } else if (annotationValue.kind() == AnnotationValue.Kind.STRING) { return annotationValue.asString(); } return null; diff --git a/integration-tests/spring-di/pom.xml b/integration-tests/spring-di/pom.xml index dc3420824b418..f31ee325ea34a 100644 --- a/integration-tests/spring-di/pom.xml +++ b/integration-tests/spring-di/pom.xml @@ -49,7 +49,7 @@ org.springframework spring-context - 5.1.4.RELEASE + ${spring.version}