Hubert Stasiuk
Hubert Stasiuk

Reputation: 23

Loading properties from custom files depending on active profile

I have an application with the newest SpringBoot v.2.1.9. The project contains a severals custom files with pattern as follow:

I want to reach the similiar behaviour to the Spring's application-{profile}.properties, I mean to load every custom props from file, which matches to active profile. Due to a huge number of properties I am not able to store them in application-{profile}.properties, because it causes a troubles with readability.

I'd like to find a strictly Java's solution, without any Maven's workarounds with physical replacing of files after the build. Could you please advise me how can I reach that approach?

My current assumption is to override an initialize method from ApplicationContextInitializer, then check the profile and execute the logic to select the files, however I am not sure if it's the most effecient approach.

Many thanks in advance for your help.

@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
    String profile = System.getProperty("spring.profiles.active");
    //selecting files according to active profile
    applicationContext.getEnvironment().getPropertySources().addLast(prop);
}

Upvotes: 1

Views: 985

Answers (2)

Phill Campbell
Phill Campbell

Reputation: 1305

At the time of this response I am using spring-boot-starter-web:2.7.8

I use a "WebConfig" file like so:

@Configuration
@PropertySource(value = "classpath:somecustom.properties")
@PropertySource(value = "classpath:somecustom-${spring.profiles.active}.properties",
                ignoreResourceNotFound = true)
public class WebConfig implements WebMvcConfigurer
{

    @Autowired
    protected Environment env;
...

This approach does not affect the built in behavior with property files named application.properties.

In the resources folder I have:

application.properties
application-l1.properties
application-l2.properties
application-l3.properties
application-loc.properties
somecustom.properties
somecustom-l1.properties
somecustom-l2.properties
somecustom-l3.properties
somecustom-loc.properties

By using @PropertySource I specify somecustom.properties to be the default and it must exist in the resources.

Then using the variable ${spring.profiles.active} will load, if found, properties for the specified environment.

Order matters, so put the default first.

Upvotes: 0

Hubert Stasiuk
Hubert Stasiuk

Reputation: 23

I have already solved my issue. If anyone would encounter the same troubles, please find my solution below:

1) Implement the EnvironmentPostProcessor and override the postProcessEnvironment method.

2) Get the files from resources -> I have used PathMatchingResourcePatternResolver class from org.springframework.core.io.support package. Once we pass the ClassLoader instance, we can execute the getResources(String path) method.

3) Iterate over Resource[] array and select those who fulfil your needs

4) Create a PropertiesPropertySourceLoader instance and load the properties from resource's path.

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
    Resource[] resources = getResources("classpath*:/properties/*.*");
    List<List<PropertySource<?>>> propertySources = getPropertySources(resources);
    for (int i = 0; i < propertySources.size(); i++) {
        propertySources.get(i).forEach(propertySource -> environment.getPropertySources().addLast(propertySource));
    }
    application.setEnvironment(environment);
}

private Resource[] getResources(String path) {
    ClassLoader classLoader = this.getClass().getClassLoader();
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(classLoader);
    try {
        return resolver.getResources(path);
    } catch (IOException ex) {
        throw new IllegalStateException("Failed to load props configuration " + ex);
    }
}

Upvotes: 1

Related Questions