diff --git a/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java b/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java index 12fa10e419b1f..d060d4157427e 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/recording/BytecodeRecorderImpl.java @@ -1197,21 +1197,30 @@ public void prepare(MethodContext context) { } } } else { - for (Constructor ctor : param.getClass().getConstructors()) { + Constructor[] ctors = param.getClass().getConstructors(); + Constructor selectedCtor = null; + if (ctors.length == 1) { + // if there is a single constructor we use it regardless of the presence of @RecordableConstructor annotation + selectedCtor = ctors[0]; + } + for (Constructor ctor : ctors) { if (RecordingAnnotationsUtil.isRecordableConstructor(ctor)) { - nonDefaultConstructorHolder = new NonDefaultConstructorHolder(ctor, null); - nonDefaultConstructorHandles = new DeferredParameter[ctor.getParameterCount()]; - - if (ctor.getParameterCount() > 0) { - Parameter[] ctorParameters = ctor.getParameters(); - for (int i = 0; i < ctor.getParameterCount(); ++i) { - String name = ctorParameters[i].getName(); - constructorParamNameMap.put(name, i); - } - } + selectedCtor = ctor; break; } } + if (selectedCtor != null) { + nonDefaultConstructorHolder = new NonDefaultConstructorHolder(selectedCtor, null); + nonDefaultConstructorHandles = new DeferredParameter[selectedCtor.getParameterCount()]; + + if (selectedCtor.getParameterCount() > 0) { + Parameter[] ctorParameters = selectedCtor.getParameters(); + for (int i = 0; i < selectedCtor.getParameterCount(); ++i) { + String name = ctorParameters[i].getName(); + constructorParamNameMap.put(name, i); + } + } + } } Set handledProperties = new HashSet<>(); diff --git a/core/deployment/src/test/java/io/quarkus/deployment/recording/BytecodeRecorderTestCase.java b/core/deployment/src/test/java/io/quarkus/deployment/recording/BytecodeRecorderTestCase.java index eff0271228d08..b4d5e01aac009 100644 --- a/core/deployment/src/test/java/io/quarkus/deployment/recording/BytecodeRecorderTestCase.java +++ b/core/deployment/src/test/java/io/quarkus/deployment/recording/BytecodeRecorderTestCase.java @@ -300,6 +300,12 @@ public void testRecordableConstructor() throws Exception { TestRecorder recorder = generator.getRecordingProxy(TestRecorder.class); recorder.bean(bean); }, new OtherTestConstructorBean("Jane", "Citizen").setAge(30)); + + runTest(generator -> { + TestSingleConstructorBean bean = new TestSingleConstructorBean("Jane", "Citizen", 30); + TestRecorder recorder = generator.getRecordingProxy(TestRecorder.class); + recorder.bean(bean); + }, new TestSingleConstructorBean("Jane", "Citizen", 30)); } @Test diff --git a/core/deployment/src/test/java/io/quarkus/deployment/recording/TestRecorder.java b/core/deployment/src/test/java/io/quarkus/deployment/recording/TestRecorder.java index 50345ca827c3f..a4238e45f4ebe 100644 --- a/core/deployment/src/test/java/io/quarkus/deployment/recording/TestRecorder.java +++ b/core/deployment/src/test/java/io/quarkus/deployment/recording/TestRecorder.java @@ -80,6 +80,10 @@ public void bean(OtherTestConstructorBean bean) { RESULT.add(bean); } + public void bean(TestSingleConstructorBean bean) { + RESULT.add(bean); + } + public void result(RuntimeValue bean) { RESULT.add(bean.getValue()); } diff --git a/core/deployment/src/test/java/io/quarkus/deployment/recording/TestSingleConstructorBean.java b/core/deployment/src/test/java/io/quarkus/deployment/recording/TestSingleConstructorBean.java new file mode 100644 index 0000000000000..03cad575420e9 --- /dev/null +++ b/core/deployment/src/test/java/io/quarkus/deployment/recording/TestSingleConstructorBean.java @@ -0,0 +1,45 @@ +package io.quarkus.deployment.recording; + +import java.util.Objects; + +public class TestSingleConstructorBean { + + private final String first; + private final String last; + private final int age; + + public TestSingleConstructorBean(String first, String last, int age) { + this.first = first; + this.last = last; + this.age = age; + } + + public String getFirst() { + return first; + } + + public String getLast() { + return last; + } + + public int getAge() { + return age; + } + + @Override + public boolean equals(Object o) { + if (this == o) + return true; + if (o == null || getClass() != o.getClass()) + return false; + TestSingleConstructorBean that = (TestSingleConstructorBean) o; + return age == that.age && + Objects.equals(first, that.first) && + Objects.equals(last, that.last); + } + + @Override + public int hashCode() { + return Objects.hash(first, last, age); + } +}