1

I am working in Spring, Java, Ant web application. I am using Spring profiling to load properties based on the enironment. Below is the sample

@Profile("dev")
@Component
@PropertySource("classpath:dev.properties")
public class DevPropertiesConfig{

}
@Profile("qa")
@Component
@PropertySource("classpath:qa.properties")
public class TestPropertiesConfig {

}

@Profile("live")
@Component
@PropertySource("classpath:live.properties")
public class LivePropertiesConfig{

}

In web.xml, we can give the profile

    <context-param>
        <param-name>spring.profiles.active</param-name>
        <param-value>dev</param-value>
    </context-param>

Now, my query is for every environment i need to create a separate Java class.

Question: Is it possible to have only one class like providing profile name as some binding parameter like @Profile({profile}).

Also, let me know if there is other better option available to achieve the same.

Naman Gala
  • 4,670
  • 1
  • 21
  • 55
Anand
  • 20,708
  • 48
  • 131
  • 198
  • Yes it is possible, and you have done it right. – Naman Gala Aug 28 '15 at 09:15
  • 3
    Instead of this use an `ApplicationContextInitializer` which based on the active profiles add a `ResourcePropertySource` pointing to the file for that profile. That is also what Spring Boot (more or less) does. – M. Deinum Aug 28 '15 at 09:19
  • For detailed example of @M.Deinum answer, refer this [SO answer](http://stackoverflow.com/a/8601353/3898076). – Naman Gala Aug 28 '15 at 09:23
  • I have deleted my solution, as it was hard coding profile names. You can refer solution in above SO answer link. – Naman Gala Aug 28 '15 at 10:04
  • @M.Deinum, is it possible to create single bean for loading the properties files. As OP has to use 3 separate classes. – Naman Gala Aug 28 '15 at 10:07

1 Answers1

2

There can be multiple profiles active at one time, so there is no single property to obtain the active profile. A general solution is to create an ApplicationContextInitializer which based on the active profiles loads additional configuration files.

public class ProfileConfigurationInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    public void initialize(final ConfigurableApplicationContext ctx) {
        ConfigurableEnvironment env = ctg.getEnvironment();
        String[] profiles = env.getActiveProfiles();
        if (!ArrayUtils.isEmpty(profiles)) {
            MutablePropertySources mps = env.getPropertySources();
            for (String profile : profiles) {
               Resource resource = new ClassPathResource(profile+".properties");
               if (resource.exists() ) {
                   mps.addLast(profile + "-properties", new ResourcePropertySource(resource);
               }
            }
        }
    }
}

Something like that should do the trick (might contain errors as I typed it from the top of my head).

Now in your web.xml include a context parameter named contextInitializerClasses and give it the name of your initializer.

<context-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>your.package.ProfileConfigurationInitializer</param-value>
</context-param>
M. Deinum
  • 115,695
  • 22
  • 220
  • 224