Skip to content

Consistent configuration property binding for nested classes on JVM and native-image #31708

@mhalbritter

Description

@mhalbritter

While working on the AOT smoke test configuration-properties I encountered a case where binding a nested class fails in native image. This works in JVM mode.

See the failing build here: https://ci.spring.io/teams/spring-aot-smoke-tests/pipelines/spring-aot-smoke-tests-1.0.x/jobs/configuration-properties

2022-07-13T15:35:51.578+02:00  WARN 44862 --- [           main] o.s.c.support.GenericApplicationContext  : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'CLR': Unsatisfied dependency expressed through constructor parameter 0: Error creating bean with name 'app-com.example.configprops.AppProperties': Could not bind properties to 'AppProperties' : prefix=app, ignoreInvalidFields=false, ignoreUnknownFields=true
2022-07-13T15:35:51.579+02:00 DEBUG 44862 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : Application failed to start due to an exception

org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'app.nested-list' to java.util.List<com.example.configprops.AppProperties$Nested>
        at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:387) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:347) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$4(Binder.java:472) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:95) ~[na:na]
        at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:83) ~[na:na]
        at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:59) ~[na:na]
        at org.springframework.boot.context.properties.bind.Binder.lambda$bindDataObject$5(Binder.java:476) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590) ~[na:na]
        at org.springframework.boot.context.properties.bind.Binder$Context.withDataObject(Binder.java:576) ~[na:na]
        at org.springframework.boot.context.properties.bind.Binder.bindDataObject(Binder.java:474) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:414) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:332) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:262) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:249) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:95) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:89) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:78) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:425) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1745) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:604) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:526) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1374) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1294) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.resolveArgument(AutowiredInstantiationArgumentsResolver.java:302) ~[na:na]
        at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.resolveArguments(AutowiredInstantiationArgumentsResolver.java:232) ~[na:na]
        at org.springframework.beans.factory.aot.AutowiredInstantiationArgumentsResolver.resolve(AutowiredInstantiationArgumentsResolver.java:154) ~[na:na]
        at com.example.configprops.CLR__BeanDefinitions.getCLRInstance(CLR__BeanDefinitions.java:30) ~[na:na]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainInstanceFromSupplier(AbstractAutowireCapableBeanFactory.java:1224) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.obtainFromSupplier(AbstractAutowireCapableBeanFactory.java:1209) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1156) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:566) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:526) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:326) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:324) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:930) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:926) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:592) ~[configuration-properties:6.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:729) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:428) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:310) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1301) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.SpringApplication.run(SpringApplication.java:1290) ~[configuration-properties:3.0.0-SNAPSHOT]
        at com.example.configprops.ConfigPropsApplication.main(ConfigPropsApplication.java:10) ~[configuration-properties:na]
Caused by: org.springframework.boot.context.properties.bind.UnboundConfigurationPropertiesException: The elements [app.nested-list[0].a-int,app.nested-list[1].a-int] were left unbound.
        at org.springframework.boot.context.properties.bind.IndexedElementsBinder.assertNoUnboundChildren(IndexedElementsBinder.java:136) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:113) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:86) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.IndexedElementsBinder.bindIndexed(IndexedElementsBinder.java:70) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.CollectionBinder.bindAggregate(CollectionBinder.java:49) ~[na:na]
        at org.springframework.boot.context.properties.bind.AggregateBinder.bind(AggregateBinder.java:56) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder.lambda$bindAggregate$3(Binder.java:438) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:590) ~[na:na]
        at org.springframework.boot.context.properties.bind.Binder.bindAggregate(Binder.java:438) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:399) ~[configuration-properties:3.0.0-SNAPSHOT]
        at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:343) ~[configuration-properties:3.0.0-SNAPSHOT]
        ... 49 common frames omitted

2022-07-13T15:35:51.579+02:00 ERROR 44862 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Binding to target [Bindable@270c5b7b type = java.util.List<com.example.configprops.AppProperties$Nested>, value = 'provided', annotations = array<Annotation>[[empty]]] failed:

    Property: app.nested-list[0].a-int
    Value: 1
    Origin: class path resource [application.yaml] - 6:14
    Reason: The elements [app.nested-list[0].a-int,app.nested-list[1].a-int] were left unbound.
    Property: app.nested-list[1].a-int
    Value: 2
    Origin: class path resource [application.yaml] - 7:14
    Reason: The elements [app.nested-list[0].a-int,app.nested-list[1].a-int] were left unbound.

Action:

Update your application's configuration

Metadata

Metadata

Assignees

Labels

theme: aotAn issue related to Ahead-of-time processingtype: bugA general bug

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions