From 0b5ccac830d5efe3b1892d029ba6edbe7e08c606 Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Tue, 27 Jun 2023 13:21:22 +0200 Subject: [PATCH] ArC: fix constructor injection for abstract decorators --- .../arc/processor/DecoratorGenerator.java | 8 +- ...DecoratorWithConstructorInjectionTest.java | 66 +++++++++++++++++ .../DecoratorWithFieldInjectionTest.java | 62 ++++++++++++++++ .../DecoratorWithSetterInjectionTest.java | 66 +++++++++++++++++ ...DecoratorWithConstructorInjectionTest.java | 73 +++++++++++++++++++ ...stractDecoratorWithFieldInjectionTest.java | 69 ++++++++++++++++++ ...tractDecoratorWithSetterInjectionTest.java | 73 +++++++++++++++++++ 7 files changed, 415 insertions(+), 2 deletions(-) create mode 100644 independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithConstructorInjectionTest.java create mode 100644 independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithFieldInjectionTest.java create mode 100644 independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithSetterInjectionTest.java create mode 100644 independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithConstructorInjectionTest.java create mode 100644 independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithFieldInjectionTest.java create mode 100644 independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithSetterInjectionTest.java diff --git a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/DecoratorGenerator.java b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/DecoratorGenerator.java index 1f19752bede5b..2b3183d63d645 100644 --- a/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/DecoratorGenerator.java +++ b/independent-projects/arc/processor/src/main/java/io/quarkus/arc/processor/DecoratorGenerator.java @@ -167,9 +167,13 @@ private String generateDecoratorImplementation(String baseName, String targetPac // Constructor MethodInfo decoratorConstructor = decoratorClass.firstMethod(Methods.INIT); MethodCreator constructor = decoratorImplCreator.getMethodCreator(Methods.INIT, "V", - decoratorConstructor.parameterTypes().toArray()); + decoratorConstructor.parameterTypes().stream().map(it -> it.name().toString()).toArray()); + ResultHandle[] constructorArgs = new ResultHandle[decoratorConstructor.parametersCount()]; + for (int i = 0; i < decoratorConstructor.parametersCount(); i++) { + constructorArgs[i] = constructor.getMethodParam(i); + } // Invoke super() - constructor.invokeSpecialMethod(decoratorConstructor, constructor.getThis()); + constructor.invokeSpecialMethod(decoratorConstructor, constructor.getThis(), constructorArgs); // Set the delegate field constructor.writeInstanceField(delegateField.getFieldDescriptor(), constructor.getThis(), constructor.invokeStaticMethod(MethodDescriptors.DECORATOR_DELEGATE_PROVIDER_GET)); diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithConstructorInjectionTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithConstructorInjectionTest.java new file mode 100644 index 0000000000000..68d6bd9eb823a --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithConstructorInjectionTest.java @@ -0,0 +1,66 @@ +package io.quarkus.arc.test.decorators; + +import io.quarkus.arc.Arc; +import io.quarkus.arc.test.ArcTestContainer; +import jakarta.annotation.Priority; +import jakarta.decorator.Decorator; +import jakarta.decorator.Delegate; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DecoratorWithConstructorInjectionTest { + @RegisterExtension + public ArcTestContainer container = new ArcTestContainer(Converter.class, ToUpperCaseConverter.class, + TrimConverterDecorator.class, Trimmer.class); + + @Test + public void testDecoration() { + ToUpperCaseConverter converter = Arc.container().instance(ToUpperCaseConverter.class).get(); + assertEquals("HOLA!", converter.convert(" holA! ")); + } + + interface Converter { + T convert(T value); + } + + @ApplicationScoped + static class ToUpperCaseConverter implements Converter { + @Override + public String convert(String value) { + return value.toUpperCase(); + } + } + + @Dependent + @Priority(1) + @Decorator + static class TrimConverterDecorator implements Converter { + @Inject + @Delegate + Converter delegate; + + private final Trimmer trimmer; + + @Inject + TrimConverterDecorator(Trimmer trimmer) { + this.trimmer = trimmer; + } + + @Override + public String convert(String value) { + return delegate.convert(trimmer.trim(value)); + } + } + + @Dependent + static class Trimmer { + public String trim(String str) { + return str.trim(); + } + } +} diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithFieldInjectionTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithFieldInjectionTest.java new file mode 100644 index 0000000000000..59707fca07b9a --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithFieldInjectionTest.java @@ -0,0 +1,62 @@ +package io.quarkus.arc.test.decorators; + +import io.quarkus.arc.Arc; +import io.quarkus.arc.test.ArcTestContainer; +import jakarta.annotation.Priority; +import jakarta.decorator.Decorator; +import jakarta.decorator.Delegate; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DecoratorWithFieldInjectionTest { + @RegisterExtension + public ArcTestContainer container = new ArcTestContainer(Converter.class, ToUpperCaseConverter.class, + TrimConverterDecorator.class, Trimmer.class); + + @Test + public void testDecoration() { + ToUpperCaseConverter converter = Arc.container().instance(ToUpperCaseConverter.class).get(); + assertEquals("HOLA!", converter.convert(" holA! ")); + } + + interface Converter { + T convert(T value); + } + + @ApplicationScoped + static class ToUpperCaseConverter implements Converter { + @Override + public String convert(String value) { + return value.toUpperCase(); + } + } + + @Dependent + @Priority(1) + @Decorator + static class TrimConverterDecorator implements Converter { + @Inject + @Delegate + Converter delegate; + + @Inject + Trimmer trimmer; + + @Override + public String convert(String value) { + return delegate.convert(trimmer.trim(value)); + } + } + + @Dependent + static class Trimmer { + public String trim(String str) { + return str.trim(); + } + } +} diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithSetterInjectionTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithSetterInjectionTest.java new file mode 100644 index 0000000000000..f10e28cbbd3e1 --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/DecoratorWithSetterInjectionTest.java @@ -0,0 +1,66 @@ +package io.quarkus.arc.test.decorators; + +import io.quarkus.arc.Arc; +import io.quarkus.arc.test.ArcTestContainer; +import jakarta.annotation.Priority; +import jakarta.decorator.Decorator; +import jakarta.decorator.Delegate; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class DecoratorWithSetterInjectionTest { + @RegisterExtension + public ArcTestContainer container = new ArcTestContainer(Converter.class, ToUpperCaseConverter.class, + TrimConverterDecorator.class, Trimmer.class); + + @Test + public void testDecoration() { + ToUpperCaseConverter converter = Arc.container().instance(ToUpperCaseConverter.class).get(); + assertEquals("HOLA!", converter.convert(" holA! ")); + } + + interface Converter { + T convert(T value); + } + + @ApplicationScoped + static class ToUpperCaseConverter implements Converter { + @Override + public String convert(String value) { + return value.toUpperCase(); + } + } + + @Dependent + @Priority(1) + @Decorator + static class TrimConverterDecorator implements Converter { + @Inject + @Delegate + Converter delegate; + + private Trimmer trimmer; + + @Inject + void init(Trimmer trimmer) { + this.trimmer = trimmer; + } + + @Override + public String convert(String value) { + return delegate.convert(trimmer.trim(value)); + } + } + + @Dependent + static class Trimmer { + public String trim(String str) { + return str.trim(); + } + } +} diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithConstructorInjectionTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithConstructorInjectionTest.java new file mode 100644 index 0000000000000..9730feb533ed1 --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithConstructorInjectionTest.java @@ -0,0 +1,73 @@ +package io.quarkus.arc.test.decorators.abstractimpl; + +import io.quarkus.arc.Arc; +import io.quarkus.arc.test.ArcTestContainer; +import jakarta.annotation.Priority; +import jakarta.decorator.Decorator; +import jakarta.decorator.Delegate; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class AbstractDecoratorWithConstructorInjectionTest { + @RegisterExtension + public ArcTestContainer container = new ArcTestContainer(Converter.class, ToUpperCaseConverter.class, + TrimConverterDecorator.class, Trimmer.class); + + @Test + public void testDecoration() { + ToUpperCaseConverter converter = Arc.container().instance(ToUpperCaseConverter.class).get(); + assertEquals("HELLO", converter.convert(" hello ")); + assertEquals(ToUpperCaseConverter.class.getName(), converter.getId()); + } + + interface Converter { + T convert(T value); + + U getId(); + } + + @ApplicationScoped + static class ToUpperCaseConverter implements Converter { + @Override + public String convert(String value) { + return value.toUpperCase(); + } + + @Override + public String getId() { + return ToUpperCaseConverter.class.getName(); + } + } + + @Priority(1) + @Decorator + static abstract class TrimConverterDecorator implements Converter { + @Inject + @Delegate + Converter delegate; + + private final Trimmer trimmer; + + @Inject + TrimConverterDecorator(Trimmer trimmer) { + this.trimmer = trimmer; + } + + @Override + public String convert(String value) { + return delegate.convert(trimmer.trim(value)); + } + } + + @Dependent + static class Trimmer { + public String trim(String value) { + return value.trim(); + } + } +} diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithFieldInjectionTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithFieldInjectionTest.java new file mode 100644 index 0000000000000..e84a0ede01940 --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithFieldInjectionTest.java @@ -0,0 +1,69 @@ +package io.quarkus.arc.test.decorators.abstractimpl; + +import io.quarkus.arc.Arc; +import io.quarkus.arc.test.ArcTestContainer; +import jakarta.annotation.Priority; +import jakarta.decorator.Decorator; +import jakarta.decorator.Delegate; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class AbstractDecoratorWithFieldInjectionTest { + @RegisterExtension + public ArcTestContainer container = new ArcTestContainer(Converter.class, ToUpperCaseConverter.class, + TrimConverterDecorator.class, Trimmer.class); + + @Test + public void testDecoration() { + ToUpperCaseConverter converter = Arc.container().instance(ToUpperCaseConverter.class).get(); + assertEquals("HELLO", converter.convert(" hello ")); + assertEquals(ToUpperCaseConverter.class.getName(), converter.getId()); + } + + interface Converter { + T convert(T value); + + U getId(); + } + + @ApplicationScoped + static class ToUpperCaseConverter implements Converter { + @Override + public String convert(String value) { + return value.toUpperCase(); + } + + @Override + public String getId() { + return ToUpperCaseConverter.class.getName(); + } + } + + @Priority(1) + @Decorator + static abstract class TrimConverterDecorator implements Converter { + @Inject + @Delegate + Converter delegate; + + @Inject + Trimmer trimmer; + + @Override + public String convert(String value) { + return delegate.convert(trimmer.trim(value)); + } + } + + @Dependent + static class Trimmer { + public String trim(String value) { + return value.trim(); + } + } +} diff --git a/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithSetterInjectionTest.java b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithSetterInjectionTest.java new file mode 100644 index 0000000000000..c6c6057ff48dd --- /dev/null +++ b/independent-projects/arc/tests/src/test/java/io/quarkus/arc/test/decorators/abstractimpl/AbstractDecoratorWithSetterInjectionTest.java @@ -0,0 +1,73 @@ +package io.quarkus.arc.test.decorators.abstractimpl; + +import io.quarkus.arc.Arc; +import io.quarkus.arc.test.ArcTestContainer; +import jakarta.annotation.Priority; +import jakarta.decorator.Decorator; +import jakarta.decorator.Delegate; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.context.Dependent; +import jakarta.inject.Inject; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.RegisterExtension; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class AbstractDecoratorWithSetterInjectionTest { + @RegisterExtension + public ArcTestContainer container = new ArcTestContainer(Converter.class, ToUpperCaseConverter.class, + TrimConverterDecorator.class, Trimmer.class); + + @Test + public void testDecoration() { + ToUpperCaseConverter converter = Arc.container().instance(ToUpperCaseConverter.class).get(); + assertEquals("HELLO", converter.convert(" hello ")); + assertEquals(ToUpperCaseConverter.class.getName(), converter.getId()); + } + + interface Converter { + T convert(T value); + + U getId(); + } + + @ApplicationScoped + static class ToUpperCaseConverter implements Converter { + @Override + public String convert(String value) { + return value.toUpperCase(); + } + + @Override + public String getId() { + return ToUpperCaseConverter.class.getName(); + } + } + + @Priority(1) + @Decorator + static abstract class TrimConverterDecorator implements Converter { + @Inject + @Delegate + Converter delegate; + + private Trimmer trimmer; + + @Inject + void init(Trimmer trimmer) { + this.trimmer = trimmer; + } + + @Override + public String convert(String value) { + return delegate.convert(trimmer.trim(value)); + } + } + + @Dependent + static class Trimmer { + public String trim(String value) { + return value.trim(); + } + } +}