I discovered this in trying to upgrade from Spring boot 1.4.1 to 2.0.0.M2

If I have a yaml file with the following: myProperties: name: 'Sam'

and I have a configuration class:

@Configuration
@ConfigurationProperties(prefix="myProperties")
public class MyConfig {
    private String name;

    public String getName(){
        return name;
    }

    public void setName(String name){
        this.name =  name;
    }

}

I will get a bunch of errors trying to create the MyConfig bean. Essentially the error boils down to:

Caused by: java.lang.IllegalArgumentException: Configuration property name 'myProperties' is not valid

I notice that if I change this line to: @ConfigurationProperties(prefix="myproperties")

the error goes away. Using a prefix with capital letters in it used to work in 1.4.1 and 1.5.4

Comment From: wilkinsona

Lots of things worked in 1.x that weren't expressly supported. We've tightened things up in 2.0 so that things are hopefully significantly easier to understand and to implement. As a result some things that used to work no longer do. This could well be one of them.

We may want to support this or, perhaps, to improve the error message to explain why the prefix is invalid. To that end, can you please share the full stack trace and message of the error that you saw?

Comment From: ctwoolsey

 :: Spring Boot ::             (v2.0.0.M2)

2017-06-17 14:50:25.957  INFO 14920 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication on LAPTOP-NCOQ07G9 with PID 14920 (started by clark in C:\Data\Programming\spring demos\demo)
2017-06-17 14:50:25.958  INFO 14920 --- [           main] com.example.demo.DemoApplication         : The following profiles are active: local
2017-06-17 14:50:25.958 DEBUG 14920 --- [           main] o.s.boot.SpringApplication               : Loading source class com.example.demo.DemoApplication
2017-06-17 14:50:26.019 DEBUG 14920 --- [           main] o.s.b.c.c.ConfigFileApplicationListener  : Activated profiles local
2017-06-17 14:50:26.019 DEBUG 14920 --- [           main] o.s.b.c.c.ConfigFileApplicationListener  : Loaded config file 'file:/C:/Data/Programming/spring%20demos/demo/target/classes/application.yaml' (classpath:/application.yaml)
2017-06-17 14:50:26.023  INFO 14920 --- [           main] ConfigServletWebServerApplicationContext : Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@49964d75: startup date [Sat Jun 17 14:50:26 CDT 2017]; root of context hierarchy
2017-06-17 14:50:26.026 DEBUG 14920 --- [           main] ConfigServletWebServerApplicationContext : Bean factory for org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@49964d75: org.springframework.beans.factory.support.DefaultListableBeanFactory@58ffcbd7: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.context.event.internalEventListenerProcessor,org.springframework.context.event.internalEventListenerFactory,demoApplication]; root of factory hierarchy
2017-06-17 14:50:27.011  INFO 14920 --- [           main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2017-06-17 14:50:27.189 DEBUG 14920 --- [           main] ConfigServletWebServerApplicationContext : Unable to locate MessageSource with name 'messageSource': using default [org.springframework.context.support.DelegatingMessageSource@bd1111a]
2017-06-17 14:50:27.189 DEBUG 14920 --- [           main] ConfigServletWebServerApplicationContext : Unable to locate ApplicationEventMulticaster with name 'applicationEventMulticaster': using default [org.springframework.context.event.SimpleApplicationEventMulticaster@7a8136b3]
2017-06-17 14:50:27.497 DEBUG 14920 --- [           main] .s.b.w.e.t.TomcatServletWebServerFactory : Code archive: C:\Users\clark\.m2\repository\org\springframework\boot\spring-boot\2.0.0.M2\spring-boot-2.0.0.M2.jar
2017-06-17 14:50:27.498 DEBUG 14920 --- [           main] .s.b.w.e.t.TomcatServletWebServerFactory : Code archive: C:\Users\clark\.m2\repository\org\springframework\boot\spring-boot\2.0.0.M2\spring-boot-2.0.0.M2.jar
2017-06-17 14:50:27.498 DEBUG 14920 --- [           main] .s.b.w.e.t.TomcatServletWebServerFactory : None of the document roots [src/main/webapp, public, static] point to a directory and will be ignored.
2017-06-17 14:50:27.553  INFO 14920 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2017-06-17 14:50:27.568  INFO 14920 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2017-06-17 14:50:27.569  INFO 14920 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.15
2017-06-17 14:50:27.736  INFO 14920 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-06-17 14:50:27.736  INFO 14920 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1716 ms
2017-06-17 14:50:27.853 DEBUG 14920 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Added existing Servlet initializer bean 'dispatcherServletRegistration'; order=2147483647, resource=class path resource [org/springframework/boot/autoconfigure/web/servlet/DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration.class]
2017-06-17 14:50:27.943 DEBUG 14920 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Created Filter initializer for bean 'characterEncodingFilter'; order=-2147483648, resource=class path resource [org/springframework/boot/autoconfigure/web/servlet/HttpEncodingAutoConfiguration.class]
2017-06-17 14:50:27.946 DEBUG 14920 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Created Filter initializer for bean 'hiddenHttpMethodFilter'; order=-10000, resource=class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class]
2017-06-17 14:50:27.947 DEBUG 14920 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Created Filter initializer for bean 'httpPutFormContentFilter'; order=-9900, resource=class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration.class]
2017-06-17 14:50:27.947 DEBUG 14920 --- [ost-startStop-1] o.s.b.w.s.ServletContextInitializerBeans : Created Filter initializer for bean 'requestContextFilter'; order=-105, resource=class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter.class]
2017-06-17 14:50:27.953  INFO 14920 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'dispatcherServlet' to [/]
2017-06-17 14:50:27.960  INFO 14920 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2017-06-17 14:50:27.962  INFO 14920 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2017-06-17 14:50:27.963  INFO 14920 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpPutFormContentFilter' to: [/*]
2017-06-17 14:50:27.963  INFO 14920 --- [ost-startStop-1] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2017-06-17 14:50:28.013 DEBUG 14920 --- [ost-startStop-1] o.s.b.w.s.f.OrderedRequestContextFilter  : Initializing filter 'requestContextFilter'
2017-06-17 14:50:28.013 DEBUG 14920 --- [ost-startStop-1] o.s.b.w.s.f.OrderedRequestContextFilter  : Filter 'requestContextFilter' configured successfully
2017-06-17 14:50:28.014 DEBUG 14920 --- [ost-startStop-1] .b.w.s.f.OrderedHttpPutFormContentFilter : Initializing filter 'httpPutFormContentFilter'
2017-06-17 14:50:28.015 DEBUG 14920 --- [ost-startStop-1] .b.w.s.f.OrderedHttpPutFormContentFilter : Filter 'httpPutFormContentFilter' configured successfully
2017-06-17 14:50:28.015 DEBUG 14920 --- [ost-startStop-1] .s.b.w.s.f.OrderedHiddenHttpMethodFilter : Initializing filter 'hiddenHttpMethodFilter'
2017-06-17 14:50:28.015 DEBUG 14920 --- [ost-startStop-1] .s.b.w.s.f.OrderedHiddenHttpMethodFilter : Filter 'hiddenHttpMethodFilter' configured successfully
2017-06-17 14:50:28.015 DEBUG 14920 --- [ost-startStop-1] s.b.w.s.f.OrderedCharacterEncodingFilter : Initializing filter 'characterEncodingFilter'
2017-06-17 14:50:28.016 DEBUG 14920 --- [ost-startStop-1] s.b.w.s.f.OrderedCharacterEncodingFilter : Filter 'characterEncodingFilter' configured successfully
2017-06-17 14:50:28.144  WARN 14920 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myConfig': Could not bind properties to MyConfig (prefix=myProperties, ignoreInvalidFields=false, ignoreUnknownFields=true); nested exception is java.lang.IllegalArgumentException: Configuration property name 'myProperties' is not valid
2017-06-17 14:50:28.148  INFO 14920 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
2017-06-17 14:50:28.163 DEBUG 14920 --- [           main] .c.l.ClasspathLoggingApplicationListener : Application failed to start with classpath: [file:/C:/Data/Programming/spring%20demos/demo/target/classes/, file:/C:/Users/clark/.m2/repository/org/springframework/boot/spring-boot-starter/2.0.0.M2/spring-boot-starter-2.0.0.M2.jar, file:/C:/Users/clark/.m2/repository/org/springframework/boot/spring-boot/2.0.0.M2/spring-boot-2.0.0.M2.jar, file:/C:/Users/clark/.m2/repository/org/springframework/spring-context/5.0.0.RC2/spring-context-5.0.0.RC2.jar, file:/C:/Users/clark/.m2/repository/org/springframework/boot/spring-boot-autoconfigure/2.0.0.M2/spring-boot-autoconfigure-2.0.0.M2.jar, file:/C:/Users/clark/.m2/repository/org/springframework/boot/spring-boot-starter-logging/2.0.0.M2/spring-boot-starter-logging-2.0.0.M2.jar, file:/C:/Users/clark/.m2/repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar, file:/C:/Users/clark/.m2/repository/ch/qos/logback/logback-core/1.2.3/logback-core-1.2.3.jar, file:/C:/Users/clark/.m2/repository/org/slf4j/jul-to-slf4j/1.7.25/jul-to-slf4j-1.7.25.jar, file:/C:/Users/clark/.m2/repository/org/slf4j/log4j-over-slf4j/1.7.25/log4j-over-slf4j-1.7.25.jar, file:/C:/Users/clark/.m2/repository/org/springframework/spring-core/5.0.0.RC2/spring-core-5.0.0.RC2.jar, file:/C:/Users/clark/.m2/repository/org/springframework/spring-jcl/5.0.0.RC2/spring-jcl-5.0.0.RC2.jar, file:/C:/Users/clark/.m2/repository/org/yaml/snakeyaml/1.18/snakeyaml-1.18.jar, file:/C:/Users/clark/.m2/repository/org/springframework/boot/spring-boot-starter-web/2.0.0.M2/spring-boot-starter-web-2.0.0.M2.jar, file:/C:/Users/clark/.m2/repository/org/springframework/boot/spring-boot-starter-json/2.0.0.M2/spring-boot-starter-json-2.0.0.M2.jar, file:/C:/Users/clark/.m2/repository/com/fasterxml/jackson/core/jackson-databind/2.9.0.pr3/jackson-databind-2.9.0.pr3.jar, file:/C:/Users/clark/.m2/repository/com/fasterxml/jackson/core/jackson-annotations/2.9.0.pr3/jackson-annotations-2.9.0.pr3.jar, file:/C:/Users/clark/.m2/repository/com/fasterxml/jackson/core/jackson-core/2.9.0.pr3/jackson-core-2.9.0.pr3.jar, file:/C:/Users/clark/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jdk8/2.9.0.pr3/jackson-datatype-jdk8-2.9.0.pr3.jar, file:/C:/Users/clark/.m2/repository/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/2.9.0.pr3/jackson-datatype-jsr310-2.9.0.pr3.jar, file:/C:/Users/clark/.m2/repository/com/fasterxml/jackson/module/jackson-module-parameter-names/2.9.0.pr3/jackson-module-parameter-names-2.9.0.pr3.jar, file:/C:/Users/clark/.m2/repository/org/springframework/boot/spring-boot-starter-tomcat/2.0.0.M2/spring-boot-starter-tomcat-2.0.0.M2.jar, file:/C:/Users/clark/.m2/repository/org/apache/tomcat/embed/tomcat-embed-core/8.5.15/tomcat-embed-core-8.5.15.jar, file:/C:/Users/clark/.m2/repository/org/apache/tomcat/embed/tomcat-embed-el/8.5.15/tomcat-embed-el-8.5.15.jar, file:/C:/Users/clark/.m2/repository/org/apache/tomcat/embed/tomcat-embed-websocket/8.5.15/tomcat-embed-websocket-8.5.15.jar, file:/C:/Users/clark/.m2/repository/org/hibernate/hibernate-validator/5.4.1.Final/hibernate-validator-5.4.1.Final.jar, file:/C:/Users/clark/.m2/repository/javax/validation/validation-api/1.1.0.Final/validation-api-1.1.0.Final.jar, file:/C:/Users/clark/.m2/repository/org/jboss/logging/jboss-logging/3.3.1.Final/jboss-logging-3.3.1.Final.jar, file:/C:/Users/clark/.m2/repository/com/fasterxml/classmate/1.3.3/classmate-1.3.3.jar, file:/C:/Users/clark/.m2/repository/org/springframework/spring-web/5.0.0.RC2/spring-web-5.0.0.RC2.jar, file:/C:/Users/clark/.m2/repository/org/springframework/spring-aop/5.0.0.RC2/spring-aop-5.0.0.RC2.jar, file:/C:/Users/clark/.m2/repository/org/springframework/spring-beans/5.0.0.RC2/spring-beans-5.0.0.RC2.jar, file:/C:/Users/clark/.m2/repository/org/springframework/spring-webmvc/5.0.0.RC2/spring-webmvc-5.0.0.RC2.jar, file:/C:/Users/clark/.m2/repository/org/springframework/spring-expression/5.0.0.RC2/spring-expression-5.0.0.RC2.jar, file:/C:/Users/clark/.m2/repository/org/slf4j/slf4j-api/1.7.25/slf4j-api-1.7.25.jar, file:/C:/Users/clark/.m2/repository/javax/inject/javax.inject/1/javax.inject-1.jar]
2017-06-17 14:50:28.178 DEBUG 14920 --- [           main] utoConfigurationReportLoggingInitializer : 

2017-06-17 14:50:28.188 ERROR 14920 --- [           main] o.s.boot.SpringApplication               : Application startup failed

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myConfig': Could not bind properties to MyConfig (prefix=myProperties, ignoreInvalidFields=false, ignoreUnknownFields=true); nested exception is java.lang.IllegalArgumentException: Configuration property name 'myProperties' is not valid
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:340) ~[spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:305) ~[spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:421) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1708) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:581) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:305) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:233) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:303) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:747) ~[spring-beans-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861) ~[spring-context-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542) ~[spring-context-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:122) ~[spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:750) [spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:386) [spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:327) [spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1245) [spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1233) [spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at com.example.demo.DemoApplication.main(DemoApplication.java:10) [classes/:na]
Caused by: java.lang.IllegalArgumentException: Configuration property name 'myProperties' is not valid
    at org.springframework.util.Assert.isTrue(Assert.java:134) ~[spring-core-5.0.0.RC2.jar:5.0.0.RC2]
    at org.springframework.boot.context.properties.source.ConfigurationPropertyName.lambda$of$5(ConfigurationPropertyName.java:454) ~[spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.boot.context.properties.source.ConfigurationPropertyName.processElement(ConfigurationPropertyName.java:546) ~[spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.boot.context.properties.source.ConfigurationPropertyName.process(ConfigurationPropertyName.java:540) ~[spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.boot.context.properties.source.ConfigurationPropertyName.of(ConfigurationPropertyName.java:452) ~[spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:168) ~[spring-boot-2.0.0.M2.jar:2.0.0.M2]
    at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:335) ~[spring-boot-2.0.0.M2.jar:2.0.0.M2]
    ... 19 common frames omitted

Comment From: mbhave

It's because of this line, where we try to convert a String to a ConfigurationPropertyName which has restrictions on it (one of them being all characters must be lower-case). I think supporting prefix names with upper-case characters is reasonable but would like to get the rest of the team's opinion on this.

Comment From: snicoll

I think my preference would be to enforce the canonical format there. I think that's what's required for; e.g. @ConditionalOnProperty to work without a prefix right? I'd favour consistency now we have a chance to do so and requiring my-properties has my preference.

But we should change that error message to explain why it's invalid (describing a bit more what the canonical format is).

Comment From: snicoll

@mumukiller this issue is closed and that comment is not really telling us anything. If you think you've found a bug, please create a separate issue with a proper description of the problem. A sample that reproduces it would be ideal. Thank you.

Comment From: dpeger

In the documentation on canonical property names it is mentioned that non-canonical representations are implicitly normalized.

https://github.com/spring-projects/spring-boot/wiki/Canonical-properties#simple-types:

Simple properties are converted into the canonical by removing any special characters and converting to lowercase. For example, the following YAML properties all result in the mapping spring.jpa.databaseplatform=mysql:

spring.jpa.database-platform=mysql spring.jpa.databasePlatform=mysql spring.JPA.database_platform=mysql

If the goal was to make things consistent and easier to understand, I think it would be good to apply the same transformation for the @ConfigurationProperties prefix and for @ConditionalOnProperty. The note says, that kebap case is encouraged, but not that is the only supported notation for prefixes.

Actually to above documentation doesn't seem to be correct as dashes won't be removed from the properties key as far as I understood. Actually they might be required to match the bean property names which are camel case by spec.