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:
- Initial name =
vcap.services.s3-mct-service.credentials
- Remove hyphens =
vcap.services.s3mctservice.credentials
- Convert dots to underscores =
vcap_services_s3mctservice_credentials
- 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