diff --git a/extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/ClassConfigurationPropertiesUtil.java b/extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/ClassConfigurationPropertiesUtil.java index c40ba364959aa..a9082db669ce8 100644 --- a/extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/ClassConfigurationPropertiesUtil.java +++ b/extensions/spring-boot-properties/deployment/src/main/java/io/quarkus/spring/boot/properties/deployment/ClassConfigurationPropertiesUtil.java @@ -309,13 +309,7 @@ private ResultHandle populateConfigObject(ClassLoader classLoader, ClassInfo con break; } } - } else { - if (!fieldTypeClassInfo.hasNoArgsConstructor()) { - throw new IllegalArgumentException( - "Nested configuration class '" + fieldTypeClassInfo - + "' must contain a no-args constructor "); - } - + } else if (fieldTypeClassInfo.hasNoArgsConstructor()) { if (!Modifier.isPublic(fieldTypeClassInfo.flags())) { throw new IllegalArgumentException( "Nested configuration class '" + fieldTypeClassInfo + "' must be public "); @@ -325,6 +319,10 @@ private ResultHandle populateConfigObject(ClassLoader classLoader, ClassInfo con getFullConfigName(prefixStr, namingStrategy, field), namingStrategy, failOnMismatchingMember, null, methodCreator); createWriteValue(methodCreator, configObject, field, setter, useFieldAccess, nestedConfigObject); + } else { + LOGGER.warn("Nested configuration class '" + fieldTypeClassInfo + + "' declared in '" + currentClassInHierarchy.name() + "." + field.name() + "' is either an " + + "interface or does not have a non-args constructor, so this field will not be initialized"); } } else { String fullConfigName = getFullConfigName(prefixStr, namingStrategy, field); diff --git a/integration-tests/spring-boot-properties/src/main/java/io/quarkus/it/spring/boot/ClassProperties.java b/integration-tests/spring-boot-properties/src/main/java/io/quarkus/it/spring/boot/ClassProperties.java index 2ebf71240ef5e..1802d08864f5f 100644 --- a/integration-tests/spring-boot-properties/src/main/java/io/quarkus/it/spring/boot/ClassProperties.java +++ b/integration-tests/spring-boot-properties/src/main/java/io/quarkus/it/spring/boot/ClassProperties.java @@ -9,6 +9,8 @@ public final class ClassProperties { private AnotherClass anotherClass; + private Interface anInterface; + public String getValue() { return value; } @@ -24,4 +26,12 @@ public AnotherClass getAnotherClass() { public void setAnotherClass(AnotherClass anotherClass) { this.anotherClass = anotherClass; } + + public Interface getAnInterface() { + return anInterface; + } + + public void setAnInterface(Interface anInterface) { + this.anInterface = anInterface; + } } diff --git a/integration-tests/spring-boot-properties/src/main/java/io/quarkus/it/spring/boot/ClassPropertiesResource.java b/integration-tests/spring-boot-properties/src/main/java/io/quarkus/it/spring/boot/ClassPropertiesResource.java index 409d8ca39c7db..c49fa6d8ba4f3 100644 --- a/integration-tests/spring-boot-properties/src/main/java/io/quarkus/it/spring/boot/ClassPropertiesResource.java +++ b/integration-tests/spring-boot-properties/src/main/java/io/quarkus/it/spring/boot/ClassPropertiesResource.java @@ -21,4 +21,10 @@ public String getValue() { public boolean isAnotherClassValue() { return properties.getAnotherClass().isValue(); } + + @Path("/interface") + @GET + public boolean getUrlFromClassWithInterface() { + return properties.getAnInterface() == null; + } } diff --git a/integration-tests/spring-boot-properties/src/main/java/io/quarkus/it/spring/boot/Interface.java b/integration-tests/spring-boot-properties/src/main/java/io/quarkus/it/spring/boot/Interface.java new file mode 100644 index 0000000000000..12aee2584ed58 --- /dev/null +++ b/integration-tests/spring-boot-properties/src/main/java/io/quarkus/it/spring/boot/Interface.java @@ -0,0 +1,5 @@ +package io.quarkus.it.spring.boot; + +public interface Interface { + String getUrl(); +} diff --git a/integration-tests/spring-boot-properties/src/main/resources/application.properties b/integration-tests/spring-boot-properties/src/main/resources/application.properties index 4842f056edd12..a5b57052bbfe1 100644 --- a/integration-tests/spring-boot-properties/src/main/resources/application.properties +++ b/integration-tests/spring-boot-properties/src/main/resources/application.properties @@ -2,4 +2,4 @@ cl.value=class-value cl.another-class.value=true bean.value=1 bean.inner-class.value=inner-class-value -interface.value=interface-value +interface.value=interface-value \ No newline at end of file diff --git a/integration-tests/spring-boot-properties/src/test/java/io/quarkus/it/spring/boot/ClassPropertiesTest.java b/integration-tests/spring-boot-properties/src/test/java/io/quarkus/it/spring/boot/ClassPropertiesTest.java index b3418599c71b1..dbc95936980a3 100644 --- a/integration-tests/spring-boot-properties/src/test/java/io/quarkus/it/spring/boot/ClassPropertiesTest.java +++ b/integration-tests/spring-boot-properties/src/test/java/io/quarkus/it/spring/boot/ClassPropertiesTest.java @@ -24,4 +24,11 @@ void shouldHaveAnotherClassValue() { .then() .body(is(equalTo("true"))); } + + @Test + void shouldInterfaceNotBePopulated() { + when().get("/class/interface") + .then() + .body(is(equalTo("true"))); + } }