3

We are using spring boot 2.0.0. We have three environments dev, staging, production. Our current config structure

dev

application-dev.yml
application-dev.properties

Likewise, we have a yml and properties file for each environment. After a year of development now the single yml file for a profile become a large monolithic config.

is it possible to have a multiple config files for a profile like below?

application-dev.yml
application-dev-sqs.yml
application-dev-redis.yml
kannanrbk
  • 6,964
  • 13
  • 53
  • 94
  • have you tried and better to tell the problem you are facing – Ryuzaki L May 13 '19 at 19:50
  • I placed configurations inside `src/main/resources` but only `application-{profile}.yml or application-{profile}.properties` is loaded. I read spring docs, there is no clear definition to load multiple profile yml files. – kannanrbk May 13 '19 at 19:55
  • so you want to load all profiles? or specific profile? – Ryuzaki L May 13 '19 at 19:55
  • Basically, i want to group profiles configuration based on category like (sqs, redis, elastic). In this case for a dev profile, it will be application-dev-sqs.yml, application-dev-redis.yml and ... – kannanrbk May 13 '19 at 19:57

4 Answers4

3

I think there are 2 ways you can achieve this requirement.

spring.profiles.active accepts a comma-separated list of active profiles, so you can always provide dev,dev-sqs,dev-redis as the value.

Another approach is by making use of @PropertySource and a custom PropertySourceFactory to achieve this requirement. You can find an implementation which takes the value from spring.profiles.active to load one corresponding YAML file in the article below. It should be super easy to adapt the implementation to load multiple files by looking for the profile id in the name of the YAML files.

[How-to] Read profile-based YAML configurations with @PropertySource

Mr.J4mes
  • 9,168
  • 9
  • 48
  • 90
3

I was dealing with a similar problem and I'd recommend using yaml configuration.

Let's describe .properties file:

Initital approach

One can use it like this:

@Component
@PropertySources({
    @PropertySource("classpath:application.properties"),
    @PropertySource("classpath:application-${spring.profiles.active}.properties")
})
public class AppProperties {
}

This is very easy to configure. Limitation is, that you cannot combine profiles. I mean, that when you want to use profile as dev,local where local just alters some config properties for dev profile, Spring will try to load application-dev,local.properties file, which is very likely not what you want.

Btw, this is what Spring will do for you automatically, this is useful for topics as you described.

There is no way to configure it per profile (and not for whole list). Other possibility would be, that one can specify the list in spring.config.name which is not the case at the moment.

Better approach

In short, use:

@Profile("dev")
@Configuration
@PropertySources({
        @PropertySource("classpath:topic1-dev.properties"),
        @PropertySource("classpath:topic2-dev.properties")
})
public class AppPropertiesDev {
}

Disadvantage is, you have to have several such config classes (dev, staging), but know you have the topics. Also you can use mutliple profiles, which are (as of my testing) loaded in order you specified. That way, your developer can easily use dev configuration and alter just what's needed for his/her testing.

Yaml approach

You can see the approach with yaml in question I asked earlier - Property resolving for multiple Spring profiles (yaml configuration), benefit is smaller amount of files - yaml has all the profiles in one file, which may or may not be what you want.

Betlista
  • 10,327
  • 13
  • 69
  • 110
1

Yes, it's possible. spring.config.location is used to externalize the config file location in Spring boot applications. This can be used to provide a location of the file in the filesystem or even in the classpath. Based on how you want to provide your application access to the files, you can choose the URI.

Doing it programmatically:

@SpringBootApplication
public class Application {

  public static void main(String[] args) {

    ConfigurableApplicationContext applicationContext = new SpringApplicationBuilder(Application.class)
        .properties("spring.config.location:classpath:/application-dev.yml,classpath:/application-dev-sqs.yml,classpath:/application-dev-redis.yml")
        .build()
        .run(args);
    }
}

Doing it via environment variables:

set SPRING_CONFIG_LOCATION=classpath:/application-dev.yml, \
  classpath:/application-dev-sqs.yml, \
  classpath:/application-dev-redis.yml 

So, you can provide your files as comma-separated values.

I've used classpath here, it can also be a location in the file system:

/home/springboot-app/properties/application-dev.yml,/home/springboot-app/properties/application-sqs.yml,/home/springboot-app/properties/application-redis.yml
priyank-sriv
  • 1,094
  • 6
  • 12
0

Have you tried including profiles yet ?

Example with profile default, you want to load additional properties for redis and db. Within application.properties file, add:

spring.profiles.include=redis, db

This will load files application-redis.properties and application-db.properties respectively

Minh Trần
  • 356
  • 4
  • 13