First of all, due to using docker, I have no application.yml or application.properties in my resource, I am setting properties by environment variable only.

Here are my properties and config define.

@ConditionalOnProperty(prefix = "my-service", name = ["endpoint"])
@ConfigurationProperties(prefix = "my-service")
@EnableConfigurationProperties(MyServiceConfig::class)
class MyServiceConfig {
    lateinit var endpoint: String

    @Bean
    override fun someBean(): Any {
        // Create bean here by endpoint.
    }
}

Because of Linux not support dash('-') for the environment variable, I am using MY_SERVICE_ENDPOINT to define these properties.

> env
MY_SERVICE_ENDPOINT=http://my-service:8080

But windows support it, and I am using MY-SERVICE_ENDPOINT to defined these properties in Windows.

> env
MY-SERVICE_ENDPOINT=http://my-service:8080

This config works fine with Windows, but not Linux. It tells me endpoint is not initialized. You can see, I defined a ConditionalOnProperty in my config, if spring can't resolve this property, this config should not import.

So, I have more test for it. It works fine both in Windows and Linux with Value annotation.

@Value("\${my-service.endpoint}")
lateinit var endpoint: String    // Work fine.

If I changed my config to this

@ConditionalOnProperty(prefix = "my-service", name = ["endpoint"])
@ConfigurationProperties(prefix = "my")
@EnableConfigurationProperties(MyServiceConfig::class)
class MyServiceConfig {
    lateinit var serviceEndpoint: String

    @Bean
    override fun someBean(): Any {
        // Create bean here by endpoint.
    }
}

You can see, I changed my prefix to my and change the property to serviceEndpoint, it can work fine with Linux...

Comment From: mbhave

@higankanshi As you mentioned, Linux does not support - for environment variables so I don't quite follow why you'd expect MY-SERVICE_ENDPOINT to work on Linux.

I'm going to close this issue as _ should be used as a delimiter for environment variables as stated in the wiki and not -. If you have any more questions, please ask on StackOverflow or Gitter.

Comment From: devkanro

Have you read my description carefully?

My question is why Value and ConditionalOnProperty can resolve my-service.endpoint to MY_SERVICE_ENDPOINT, but ConfigurationProperties not?

Comment From: devkanro

@mbhave

Comment From: snicoll

Have you read my description carefully?

Yes, I did and asked for help because I didn't understand what you were reporting. I still don't so if you want some help, share a sample (Github repo or zip) that we can run ourselves with instructions.

Comment From: devkanro

@snicoll My question is why Value and ConditionalOnProperty can resolve my-service.endpoint to MY_SERVICE_ENDPOINT, but ConfigurationProperties not?

Comment From: snicoll

Copy pasting your question is not what we’re asking. The condition and the binder work off the same environment so that shouldn’t happen. That’s why a sample we can run is what we need.

Comment From: devkanro

OK, I am not good at English, my wording may be offensive, forget me, please.

I don't know you can't recurrent this problem, I will give you a sample later.

Comment From: devkanro

@snicoll

Comment From: bakoontz

To @devkanro's credit, he has a point: Hyphens and underscores are handled inconsistently, even within the same environment.

I can confirm the following works in Linux:

application.yml:

vcap:
     services:
        s3-mct-service:
            credentials:
                 <stuff>

Some spring class:

@ConfigurationProperties(prefix="vcap.services.s3-mct-service.credentials")

Now, if I want to run this app locally, in Cygwin, I can't use the application properties as they are due to the hyphens (not supported as environment vars). But if I modify them:

export VCAP_SERVICES_S3_MCT_SERVICE_CREDENTIALS_ACCESSKEY=<some key>

then the @ConfigurationProperties prefix is unrecognized.

Instead of dismissing the OP, think about the issue: Inconsistent conversion of periods, hyphens, and underscores lead to different behaviors in different environments. Why not make them consistent? There is no reason why a hyphen cannot be interpreted as an underscore.

Comment From: philwebb

There is no reason why a hyphen cannot be interpreted as an underscore.

Unfortunately there is a reason why we can't just treat a hyphen as an underscore (in fact we used to have a much more flexible binding mechanism in Spring Boot 1.5 but we changed it because it caused a lot of subtle issues). Depending on the environment, not all property sources may be iterable. With some PropertySource implementation we can only ask "what's the value of the property named 'X'", we can't ask "what are all property names that you know about".

In order to support those non-iterable sources, we need an algorithm that can take a configuration key and convert it into a name. In the example above we'd do this:

1) Initial name = vcap.services.s3-mct-service.credentials 2) Remove hyphens = vcap.services.s3mctservice.credentials 3) Convert dots to underscores = vcap_services_s3mctservice_credentials 4) Uppercase = VCAP_SERVICES_S3MCTSERVICE_CREDENTIALS

If we allow hyphens we can't make unique mappings. I.e. vcap.services.s3-mct-service.credentials, vcap.services.s3.mct-service.credentials, vcap.services.s3-mct.service.credentials, vcap.services.s3-mct-service-credentials all end up as VCAP_SERVICES_S3_MCT_SERVICE_CREDENTIALS.

Although the restriction can cause some confusion (as OP pointed out), we've generally found these strict rules to be much less error-prone overall.

Comment From: davidljuba15031979

... ... In order to support those non-iterable sources, we need an algorithm that can take a configuration key and convert it into a name. In the example above we'd do this:

  1. Initial name = vcap.services.s3-mct-service.credentials
  2. Remove hyphens = vcap.services.s3mctservice.credentials
  3. Convert dots to underscores = vcap_services_s3mctservice_credentials
  4. Uppercase = VCAP_SERVICES_S3MCTSERVICE_CREDENTIALS

...

Also documented here: https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config.typesafe-configuration-properties.relaxed-binding.environment-variables