From cac6bf3644716290179ddcc3a34e90bd824c1b4a Mon Sep 17 00:00:00 2001 From: Graeme Rocher Date: Thu, 2 Jan 2025 09:39:44 -0400 Subject: [PATCH] if a class has a constructor default to it in introspection instead of builder --- .../beans/visitor/BeanIntrospectionWriter.java | 6 +++++- .../visitor/IntrospectedTypeElementVisitor.java | 2 +- .../AbstractInitializableBeanIntrospection.java | 15 ++++++++++++++- test-suite/build.gradle | 2 ++ .../java/io/micronaut/test/lombok/Book.java | 17 +++++++++++++++++ .../lombok/LombokIntrospectedBuilderTest.java | 8 ++++++++ 6 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 test-suite/src/test/java/io/micronaut/test/lombok/Book.java diff --git a/core-processor/src/main/java/io/micronaut/inject/beans/visitor/BeanIntrospectionWriter.java b/core-processor/src/main/java/io/micronaut/inject/beans/visitor/BeanIntrospectionWriter.java index 6dedd1354a..9b669e9a21 100644 --- a/core-processor/src/main/java/io/micronaut/inject/beans/visitor/BeanIntrospectionWriter.java +++ b/core-processor/src/main/java/io/micronaut/inject/beans/visitor/BeanIntrospectionWriter.java @@ -724,7 +724,11 @@ private void writeIntrospectionClass(ClassWriterOutputVisitor classWriterOutputV buildGetIndexedProperties(classWriter); boolean hasBuilder = annotationMetadata != null && (annotationMetadata.isPresent(Introspected.class, "builder") || annotationMetadata.hasDeclaredAnnotation("lombok.Builder")); + if (defaultConstructor != null || constructor != null) { + writeBooleanMethod(classWriter, "hasConstructor", true); + } if (defaultConstructor != null) { + writeInstantiateMethod(classWriter, defaultConstructor, "instantiate"); // in case invoked directly or via instantiateUnsafe if (constructor == null) { @@ -766,7 +770,7 @@ private void writeIntrospectionClass(ClassWriterOutputVisitor classWriterOutputV } private void writeBooleanMethod(ClassWriter classWriter, String methodName, boolean state) { - GeneratorAdapter booleanMethod = startPublicMethodZeroArgs(classWriter, boolean.class, methodName); + GeneratorAdapter booleanMethod = startPublicFinalMethodZeroArgs(classWriter, boolean.class, methodName); booleanMethod.push(state); booleanMethod.returnValue(); booleanMethod.visitMaxs(2, 1); diff --git a/core-processor/src/main/java/io/micronaut/inject/beans/visitor/IntrospectedTypeElementVisitor.java b/core-processor/src/main/java/io/micronaut/inject/beans/visitor/IntrospectedTypeElementVisitor.java index 090ef931b1..6c7a52cf2f 100644 --- a/core-processor/src/main/java/io/micronaut/inject/beans/visitor/IntrospectedTypeElementVisitor.java +++ b/core-processor/src/main/java/io/micronaut/inject/beans/visitor/IntrospectedTypeElementVisitor.java @@ -241,7 +241,7 @@ private void processBuilderDefinition(ClassElement element, VisitorContext conte creatorMethod, writePrefixes, methodElement, - null, + element.getDefaultConstructor().orElse(null), returnType, methodMetadata, index, diff --git a/inject/src/main/java/io/micronaut/inject/beans/AbstractInitializableBeanIntrospection.java b/inject/src/main/java/io/micronaut/inject/beans/AbstractInitializableBeanIntrospection.java index cab98699d4..27a81192fb 100644 --- a/inject/src/main/java/io/micronaut/inject/beans/AbstractInitializableBeanIntrospection.java +++ b/inject/src/main/java/io/micronaut/inject/beans/AbstractInitializableBeanIntrospection.java @@ -166,6 +166,15 @@ public Builder builder() { } } + /** + * Whether an accessible constructor exists. + * @return True if a default constructor exists + * @since 4.7.11 + */ + protected boolean hasConstructor() { + return false; + } + /** * Reflection free bean instantiation implementation for the given arguments. * @@ -393,7 +402,11 @@ public AnnotationMetadata getAnnotationMetadata() { @Override public Argument[] getConstructorArguments() { - return hasBuilder() ? getBuilderData().constructorArguments : constructorArguments; + if (hasConstructor()) { + return constructorArguments; + } else { + return hasBuilder() ? getBuilderData().constructorArguments : constructorArguments; + } } @NonNull diff --git a/test-suite/build.gradle b/test-suite/build.gradle index 690bf5429b..3b8b533f68 100644 --- a/test-suite/build.gradle +++ b/test-suite/build.gradle @@ -119,3 +119,5 @@ test { exclude '**/classnotfound/**' } +//compileTestJava.options.fork = true +//compileTestJava.options.forkOptions.jvmArgs = ['-Xdebug', '-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005'] diff --git a/test-suite/src/test/java/io/micronaut/test/lombok/Book.java b/test-suite/src/test/java/io/micronaut/test/lombok/Book.java new file mode 100644 index 0000000000..d762bbf95a --- /dev/null +++ b/test-suite/src/test/java/io/micronaut/test/lombok/Book.java @@ -0,0 +1,17 @@ +package io.micronaut.test.lombok; + +import io.micronaut.core.annotation.Introspected; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Introspected +@Data +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Book { + private Integer id; + private String title; +} diff --git a/test-suite/src/test/java/io/micronaut/test/lombok/LombokIntrospectedBuilderTest.java b/test-suite/src/test/java/io/micronaut/test/lombok/LombokIntrospectedBuilderTest.java index 89f737e19e..572133d622 100644 --- a/test-suite/src/test/java/io/micronaut/test/lombok/LombokIntrospectedBuilderTest.java +++ b/test-suite/src/test/java/io/micronaut/test/lombok/LombokIntrospectedBuilderTest.java @@ -15,6 +15,14 @@ public class LombokIntrospectedBuilderTest { + @Test + void testLombokNoArgsConstructor() { + BeanIntrospection introspection = BeanIntrospection.getIntrospection(Book.class); + assertEquals(0, introspection.getConstructorArguments().length); + Book book = introspection.instantiate(); + assertNotNull(book); + } + @Test void testLombokRecordBuilder() { BeanIntrospection introspection = BeanIntrospection.getIntrospection(RobotRecord.class);