SB 2.5.1 breaks our project, since profile specific properties in combination with config-imports in a multi maven module are not properly resolved anymore. This worked for us with SB 2.5.0 and SB 2.4.5
My guess it's due to issues #26754 and #26755 fixed for SB 2.5.1/2.4.7, which imho are features, not bugs.
Consider following simplified project setup, maven multi module project, two SB applications and a shared common module:
module "application FOO"
- application.properties
- content: spring.config.import=classpath:common.properties
- application-local.properties
- application-yourname.properties
- application-prod.properties
module "application BAR"
- application.properties
- content: spring.config.import=classpath:common.properties
- application-local.properties
- application-yourname.properties
- application-prod.properties
module "COMMON"
- common.properties
- common-local.properties
- common-yourname.properties
- common-prod.properties
We have defined some common properties per profile in module "COMMON", so we don't have to copy&paste (DRY) all properties which are needed by application FOO and application BAR. (Actually we have way more modules/applications, so it was a real hassle to refactor this some weeks ago for SB 2.4.0). Common properties for all applications end up in "common.properties", common properties for all production environments end up in "common-prod.properties" etc.
Behavior in SB 2.5.0 (and working from 2.4.0 to SB 2.4.5): Running "application FOO" with spring.profiles.active="local,yourname" used properties in following order (the latter overwrites to former): COMMON/common.properties < COMMON/common-local.properties < COMMON/common-yourname.properties < FOO/application.properties < FOO/application-local.properties < FOO/application-yourname.properties
This does not work with SB 2.5.1 anymore. Application startup fails, because it cannot resolve some properties/placeholders we inject in a @Service
Please consider reverting the mentioned fixes, because SB 2.5.1 (and probably 2.4.7) is not backward compatible and break existing applications that relied on these features
See attached example project for demo, Run "DemoApplication" in demo-module with spring.profiles.active="prod". Modify SB version in parent pom.xml. SB 2.5.0 outputs "common-prod" SB 2.5.1 outputs "application-prod" demo.zip
Comment From: ghillert
I can confirm that some ConfigData API change breaks my app in 2.4.7
. 2.4.6
works. Still investigating whether it is related to the above issue.
Comment From: adgoudz
The changes for #26752 in 2.4.7 broke all of our applications this week. StandardConfigDateLocationResolver.resolveProfileSpecific
is returning early when resolving the ConfigDataResources for all of our imports, and I can see that this behavior was just added in d1b256a.
I really thought the import behavior in 2.4.0-2.4.6 was elegant... not surprising. We have dozens of applications that pull in common configuration from shared libraries, and sometimes those common configuration files pull in configuration from other shared libraries. We configure for 10+ profiles, so now we're needing to add imports to all of our profile-specific configuration. In some cases we don't have profile-specific configuration files, i.e. for the profiles that don't deviate from the defaults. Now we need to create files that contain only a sprint.config.import
for other profile-specific files.
The last example I'll share is that we can no longer activate a profile to manipulate the shared configuration that gets imported. The best alternative I can think of is to do something like this:
spring:
config:
import: file-for-the-${shared-env-name:default}-environment.yaml
It seems like #26752, #26753, #26754, #26755 were added to prevent problems that I don't understand. If they can't be reverted, could there be a way for developers to opt-in to one behavior over the other?
Comment From: pavankjadda
We have this issue as well. After upgrading to Spring Boot 2.5.1 the application failed to start. We load environment specific properties through yaml files.
Comment From: mtc3bmtc3b
I'll chime in with "me too". In our case, we are using Vault to store credentials, Consul for some runtime configuration, and also profile-based configuration for 'configuration as code'. We have application-common.properties but also application-
Consul/Vault appear to require the use of spring.config.import, but we also want to use profile-based configuration so we don't have the same configuration in 10+ places (all our microservices and our test infrastructure). On 2.4.5, we had the Consul/Vault config in application-common.properties along with the required spring.config.import=vault://,consul://. Everything just worked.
After upgrading to 2.5.1 (same with 2.4.7), it broke. Moving our Consul/Vault configuration (including the spring.config.import line to include it) to each application's application.properties appears to at least allow the application to start (not convinced it works fully yet). This works since our Consul/Vault config is the same across environments, except for our access tokens which are retrieved via the environment or k8s secrets. So, we don't need environment-specific Consul/Vault config. If we did, then that would also have to move outside of the app. Using this approach of spring.config.import residing in application.properties seems to import both ConsulVault and the environment-specific config files.
I'll second the notion that this change really does not belong in a patch release. It is a change in behavior that really belongs in a minor or major release - with explicit mention in the Release Notes.
Comment From: philwebb
Sorry for the inconvenience this change made. Importing profile specific files was somewhat accidental and we didn't anticipate that people would be using it. We'll look at reverting the change and adding some additional tests and docs.
Comment From: pavankjadda
@philwebb Unless I am missing something here, isn't that the reason different profiles exist? If not what's the recommended way to load environment specific properties through profiles(if possible please update the docs)?
Comment From: philwebb
@pavankjadda The spring.config.import
feature is new in 2.4 and we primarily expected it to be used in the form spring-config.import=some.properties
(without some-<profile>.properties
being considered). For profile-specific imports, we anticipated that they'd be referenced via profile-specific sections, E.g.:
application.properties
some.property=test
#---
spring.config.activate.on-profile=prod
spring.config.import=production.properties
We're going to restore the old behavior so some-<profile>.properties
will be considered again. We'll also try to clarify the documentation.
Comment From: pavankjadda
@philwebb Will place holders in production.properties file be replaced with values from Vault?
Here is an example based on 2.4 config. I have application.yml, dev.yml or prod.yml files. When the application starts, properties in dev.yml or prod.yml (based on active profile) should be replaced with actual values from Vault. But they are not
application.yml
server:
port: 8081
## Select profile
spring:
application:
name: "customers"
profiles:
group:
"dev": "dev"
"prod": "prod"
cloud:
vault:
authentication: APPROLE
app-role:
role-id: ${role-id}
secret-id: ${secret-id}
role: customers-read
app-role-path: approle
uri: https://VAULT_URL:8200
connection-timeout: 5000
read-timeout: 15000
kv:
enabled: true
backend: secret
application-name: app/customers
config:
import: vault://secret/app/customers/
---
spring:
config:
activate:
on-profile: "dev"
import: dev.yml
---
spring:
config:
activate:
on-profile: "prod"
import: prod.yml
dev.yml
spring:
datasource:
url: "jdbc:mysql://localhost/dev"
username: "dev"
password: "dev"
#### ELK Logging
elk:
logging:
rabbitmq:
hostname: ${customers.elk.logging.rabbitmq.hostname}
port: 5672
username: ${customers.elk.logging.rabbitmq.username}
password: ${customers.elk.logging.rabbitmq.password}
queueName: ${customers.elk.logging.rabbitmq.queueName}
prod.yml
spring:
datasource:
url: "jdbc:mysql://localhost/prod"
username: "prod"
password: "prod"
#### ELK Logging
elk:
logging:
rabbitmq:
hostname: ${customers.elk.logging.rabbitmq.hostname}
port: 5672
username: ${customers.elk.logging.rabbitmq.username}
password: ${customers.elk.logging.rabbitmq.password}
queueName: ${customers.elk.logging.rabbitmq.queueName}
Comment From: philwebb
@pavankjadda That doesn't appear to be related to this issue. I'm not sure if that's a problem with the vault support or something else. It's probably best to raise an issue at https://github.com/spring-cloud/spring-cloud-vault/issues to start with and provide a sample application that shows what you're trying to do.
Comment From: philwebb
I've pushed a fix that should hopefully restore the old behavior. CI should publish a new SNAPSHOT in the next hour or so. It would be helpful if someone watching this issue could give it a spin.
Comment From: kaliy
In my case it didn't work, because it's related to 0da0d2d4693779a91cd2e7c18ca4c3e567d4d633 commit.
I have profile groups for different environments specified like
spring:
profiles:
group:
prod:
- vault
- consul
So for prod
I have consul
profile set up and configuration inside the application-consul.yml
is following:
spring:
config:
import: "consul://"
# consul-specific properties are omitted
In spring cloud consul integration the method resolve()
returns empty list (the same is with spring cloud vault). resolveProfileSpecific()
is not called at all.
Comment From: kaliy
Ok, I guess my issue is related to #26950 rather than #26858