Reputation: 17627
We are currently having one application.properties
and one application-staging.properties
, which is loaded based on the active Spring profile.
However, it's very bloated and we like to split it into multiple properties files based on the context.
For example:
teams.properties
and
teams-staging.properties
We load it using the class below
@Getter
@Configuration
@PropertySource("classpath:teams.properties")
public class TeamsProperties {
@Value("${teams.some-team-a}")
private String someTeamA;
@Value("${teams.some-team-b}")
private String someTeamB;
}
But it won't respect the profile and the teams-staging.properties
is ignored.
What would be needed to "clone" the default application.properties behaviour for custom properties files?
Upvotes: 2
Views: 1238
Reputation: 17627
I've decided to do it via inheritance as @xerx593 recommended in the comment.
@Getter
public abstract class TeamsProperties {
@Value("${teams.some-team-a}")
private String someTeamA;
@Value("${teams.some-team-b}")
private String someTeamB;
@Configuration
@Profile({"!staging"})
@PropertySource({"classpath:teams.properties"})
public static class TeamsPropertiesDefault extends TeamsProperties {
}
@Configuration
@Profile({"staging"})
@PropertySource({"classpath:teams-staging.properties"})
public static class TeamsPropertiesStaging extends TeamsProperties {
}
}
The reason is, I'd like to keep teams.properties as the default properties file and only then switch to staging if the profile is staging. I also don't want to have to create one additional .properties file for each profile, like "testing".
So with that way, each profile that is not covered with a specific properties file will always fall back to teams.properties ( but the @Profile annotation of the default must be enhanced of course)
Putting it all together with inner classes keeps it relatively clean and I can live with it.
Upvotes: 1
Reputation: 2486
@PropertySource accept an array as value. You can do this :
@Getter
@Configuration
@PropertySource({"classpath:teams.properties", "classpath:teams-${spring.profiles.active}.properties"})
public class TeamsProperties {
@Value("${teams.some-team-a}")
private String someTeamA;
@Value("${teams.some-team-b}")
private String someTeamB;
}
Then run the application with the active profile :
-Dspring.profiles.active=staging
The disadvantage of this solution is that you always have to pass only one active profile. It will not work for multiple profiles : -Dspring.profiles.active=foo,bar
Edit:
@MarianKlühspies Following your answer, you can have more flexibily using YAML instead of properties file to achieve this behavior.
spring:
config:
activate:
on-profile: staging
name: staging-profile
environment: staging
enabled: false
...
---
spring:
config:
activate:
on-profile: prod
name: production-profile
environment: production
enabled: true
...
Upvotes: 2