Spring-boot: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'xxx.yyy' to com.example.demo.properties.ApplicationConfigurationProperties

Created on 18 Apr 2018  ·  3Comments  ·  Source: spring-projects/spring-boot

After upgrading to Spring Boot 2.0.1 release I get a BindingException with ConfigurationProperties.

This works well under Spring Boot 2.0.0

I have included a small sample application that reproduces the error.

This could be related to https://github.com/spring-projects/spring-boot/issues/12854

Output from starting the application:

2018-04-18 12:07:36.689 DEBUG 31652 --- [           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 'xxx.yyy' to com.example.demo.properties.ApplicationConfigurationProperties$$EnhancerBySpringCGLIB$$69ff6b88
    at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:250) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:226) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:210) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:192) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:82) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:106) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:93) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:422) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1694) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:579) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:501) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:760) ~[spring-beans-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:869) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550) ~[spring-context-5.0.5.RELEASE.jar:5.0.5.RELEASE]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:759) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:395) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1255) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1243) [spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at com.example.demo.ConfigurationpropertiesbugApplication.main(ConfigurationpropertiesbugApplication.java:10) [classes/:na]
Caused by: org.springframework.boot.context.properties.bind.UnboundConfigurationPropertiesException: The elements [xxx.yyy.zzzwww] were left unbound.
    at org.springframework.boot.context.properties.bind.handler.NoUnboundElementsBindHandler.checkNoUnboundElements(NoUnboundElementsBindHandler.java:88) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.context.properties.bind.handler.NoUnboundElementsBindHandler.onFinish(NoUnboundElementsBindHandler.java:73) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.context.properties.bind.Binder.handleBindResult(Binder.java:236) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:223) ~[spring-boot-2.0.1.RELEASE.jar:2.0.1.RELEASE]
    ... 23 common frames omitted

2018-04-18 12:07:36.689 ERROR 31652 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

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

Description:

Binding to target [Bindable@52fc5eb1 type = com.example.demo.properties.ApplicationConfigurationProperties$$EnhancerBySpringCGLIB$$69ff6b88, value = 'provided', annotations = array<Annotation>[@org.springframework.boot.context.properties.ConfigurationProperties(ignoreUnknownFields=false, ignoreInvalidFields=false, value=xxx.yyy, prefix=xxx.yyy)]] failed:

    Property: xxx.yyy.zzzwww
    Value: true
    Origin: class path resource [application.properties]:1:16
    Reason: The elements [xxx.yyy.zzzwww] were left unbound.

Action:

Update your application's configuration


Process finished with exit code 1

demo.zip

declined

Most helpful comment

@Configuration is a stereotype that declares the class as a configuration class, that is a class that is creating bean instances to be added to the context (via @Bean methods) and/or other top-level declarations that affect the context (such as @ComponentScan or @EnableXyz).

A @ConfigurationProperties annotated class ultimately becomes a bean, not a configuration class. I can understand the confusion with "configuration" and "configuration properties" but it's wrong to flag a @ConfigugraitonProperties class with @Configuration as it does not (and should not) implement the features that this stereotype implies.

It is unnecessary if you use it with @EnableConfigurationProperties(MyProperties.class) as this will make sure it's created as a bean. As for the documentation, adding a @Component or exposing a @Bean are two alternatives to the former. I haven't seen a @ConfigurationProperties flagged with @Configuration in the ref guide. If I am wrong, please open a separate issue and we'll fix it.

If you have more questions, please use StackOverflow or come chat with us on Gitter, we prefer to keep the tracker for bugs and enhancements only.

All 3 comments

@skufle two things. You are binding to a static property which we never intended to actually support. Your @ConfigurationProperties is flagged as @Configuration which is unnecessary and wrong (you're not and should not contributing additional @Bean in a @ConfigurationProperties object).

See #12390 - We need to document this properly and also add a note in the migration guide. The error you get is simply because no binding happens at all (and you've configured the binding to fail if properties are unbounded).

@snicoll You write that "@​ConfigurationProperties is flagged as @​Configuration which is unnecessary and wrong" but some of the examples given in the documentation, like under 24.7 and 24.7.1, use @​ConfigurationProperties with @​Bean or @​Component.
The API for ConfigurationProperties also mentions using @​ConfigurationProperties with @​​Configuration, and EnableConfigurationProperties mentions "ConfigurationProperties beans can be registered in the standard way".

Does the documentation need an update or am I misunderstanding something?

@Configuration is a stereotype that declares the class as a configuration class, that is a class that is creating bean instances to be added to the context (via @Bean methods) and/or other top-level declarations that affect the context (such as @ComponentScan or @EnableXyz).

A @ConfigurationProperties annotated class ultimately becomes a bean, not a configuration class. I can understand the confusion with "configuration" and "configuration properties" but it's wrong to flag a @ConfigugraitonProperties class with @Configuration as it does not (and should not) implement the features that this stereotype implies.

It is unnecessary if you use it with @EnableConfigurationProperties(MyProperties.class) as this will make sure it's created as a bean. As for the documentation, adding a @Component or exposing a @Bean are two alternatives to the former. I haven't seen a @ConfigurationProperties flagged with @Configuration in the ref guide. If I am wrong, please open a separate issue and we'll fix it.

If you have more questions, please use StackOverflow or come chat with us on Gitter, we prefer to keep the tracker for bugs and enhancements only.

Was this page helpful?
0 / 5 - 0 ratings