Spring “spring.profiles.include” overrides

百般思念 提交于 2020-11-30 04:37:07

问题


My intention is to have two profiles in a spring boot application - development and production one. Development profile is meant just to override some variables of production profile (like in-memory database instead of database in the cloud). As I expect some changes to be done to production profile in the future, duplicating variables in development profile doesn't seem to be a solution.

So, in Spring Reference I read that spring.profiles.include is supposed to only add properties from referenced profile, but from what I've checked it rather overrides it. So, when having two profiles foo and bar, in separate yaml files:

application-foo.yaml:

myproperty: 44

application-bar.yaml:

spring:
  profiles:
    include: foo
    active: bar,foo
myproperty: 55

And setting -Dspring.profiles.active=bar variable in IDE, the runtime value of myproperty is 44. That means that bar, is overriden with foo which was supposed to only add properties, but not to override them. When starting the application, I get:

The following profiles are active: foo,bar

I added spring.profiles.active=bar to application-bar.yaml as suggested by this answer, in another question, but it has no effect - there is no difference when property is there or not (I also tried using dash listing instead of comma separated values).

My question is, is it how it is supposed to work (then Spring Reference is misleading)? If so, are there any solutions for that?

Adding a link to the application source code on a github.


回答1:


We implemented the Spring active profiles in a slightly different way. Let's say the default properties file, application.yml, contains all default values which is same in both production and development environments.

Create separate properties for production and development files named application-prd.yml and application-dev.yml respectively. These files may contain extra properties or override some of the default properties.

During application startup, we pass the spring.profiles.active as an environment variable. For example,

-Dspring.profiles.active=prd

will pick up application-prd.yml along with application.yml

or

-Dspring.profiles.active=dev

will pick up application-dev.yml along with application.yml




回答2:


According to the spring boot documentation here, spring.profiles.include is used to add the properties from other profiles. It will add the property from other profiles if the property is not present in active one. But if it is present, then it will overwrite and the last one to be applied wins




回答3:


You could add a new profile in the application-bar.yaml:

spring.profiles.include: foo,foo-override
myproperty: 33

---
spring.profiles: foo-override
myproperty: 55

The order is: 33 in bar overridden by 44 in foo overridden by 55 in foo-override.




回答4:


There are two parts to the problems here:

First is present in the answer refered in original question (here). I.e. how to inherit properties from profile. The answer is to include original profile. However for the situation we have it might be not needed.

Second problem is activating profiles done differently. I believe (but might turn out wrong) that in referred question the OP does not activate profile with this:

-Dspring.profiles.active=bar

This line overrides whatever is provided in the profile. So for this case the simplest solution to inherit properties would be to change the line in IDE to:

-Dspring.profiles.active=bar,foo

you can then omit properties in foo the are present in bar and also omit spring.profiles.include, however in that case foo will not be standalone profile. If that's ok - it will work this way.




回答5:


Given:

  • The files: application-default.yml, application-foo.yml, application-bar.yml
  • myproperty: default in application-default.yml
  • myproperty: foo in application-foo.yml
  • myproperty: bar in application-bar.yml

I think these 2 use cases of using profiles are a little bit opposite in the meaning:

  1. In the most common case (-Dspring.profiles.active but no spring.profiles.include):

    1. When profile foo or boo are activated the properties from application-foo.yml (or application-bar.yml) will add/override the ones from application-default.yml.
    2. When profiles foo,bar are activated then properties from bar will add/override those from application-foo.yml and then those from application-default.yml.

    E.g: -Dspring.profiles.active=foo,bar the property from application-bar.yml wins (overrides) -> myproperty: bar

  2. In the second case (spring.profiles.include is used)

    1. The properties from the include statement add/overrides the properties from the application-*.yml files which uses spring.profiles.include

    I.e.: If application-boo.yml contains the spring.profiles.include=foo then properties from application-foo.bar adds/override properties from from application-bar.yml which add/override those from application-default.yml.

    On the other hand (I suppose) if application-boo.yml includes the spring.profiles.include=default,foo then properties from application-foo.yml will add/override those from application-default.yml which add/overrides those from application-bar.yml. So myproperty: bar. I wouldn't recommend the usage of default in combination with spring.profiles.include because this way it mixes the two cases and the override strategy is counterintuitive considering application-default.yml has a special treatment in springboot.

I also admit I am not at all a fan of the spring.profiles.active usage in application-*.yml files. I prefer to activate the profiles with system properties (maven included) or env variables. IMO it makes the whole profiles thing clearer to me.

If with my (herein above)reasoning I am on the wrong path please let me know.



来源:https://stackoverflow.com/questions/47368086/spring-spring-profiles-include-overrides

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!