0

I'm trying to programmatically set the .properties file for my Spring MVC application based on the profile. For example, if the profile is dev I'd like to source the database-dev.properties file.

So inside my web.xml I have it call out to my custom class

<servlet>
  <servlet-name>spring-web</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
  <init-param>
    <param-name>contextInitializerClasses</param-name>
    <param-value>com.galapagos.context.CustomEnvironmentApplicationContextInitializer</param-value>
  </init-param>
</servlet>

The custom class just looks at the current profile and adds the correct .properties file to environment's property sources

public class CustomEnvironmentApplicationContextInitializer
        implements ApplicationContextInitializer<ConfigurableApplicationContext> {

    private static final Logger logger = LoggerFactory.getLogger(
        CustomEnvironmentApplicationContextInitializer.class);


    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) {
        // Get the environment
        ConfigurableEnvironment environment = applicationContext.getEnvironment();

        try {

            profile = environment.getActiveProfiles()[0];

            String fileName = String.format(
                "database-%s.properties",
                profile);

            ResourcePropertySource resource = 
                new ResourcePropertySource(new ClassPathResource(fileName));

            environment.getPropertySources().addFirst(resource);
            logger.info("Loaded: " + resource);

        } catch (IOException e) {
            logger.warn("Error loading: " + e);
        }

        // Print the list of property sources
        logger.info("ENVIRONMENT: " + environment.getPropertySources());

        // Refresh the context - is this even needed??
        applicationContext.refresh();
    }


}

I can tell the above is working because it prints out the property sources at the bottom

2017-01-29 21:43:25 INFO  CustomEnvironmentApplicationContextInitializer:66 - ENVIRONMENT: [class path resource [database-dev.properties],servletConfigInitParams,servletContextInitParams,jndiProperties,systemProperties,systemEnvironment]

All the database-%{xxx}.properties files for each profile are pretty straightforward. Just some JDBC connection properties

jdbc.driverClassName=org.postgresql.Driver
jdbc.url=jdbc:postgresql://localhost:5432/galapagos
jdbc.username=my_user
jdbc.password=

And finally inside my servlet definition I load the resources and create a dataSource

<beans:bean
  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
</beans:bean>

<!-- Database / JDBC -->

<beans:bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
  <beans:property name="driverClassName" value="${jdbc.driverClassName}" />
  <beans:property name="url" value="${jdbc.url}" />
  <beans:property name="username" value="${jdbc.username}" />
  <beans:property name="password" value="${jdbc.password}" />
</beans:bean>

However I'm getting a failure because it can't resolve the placeholder names

Could not resolve placeholder 'jdbc.driverClassName' in string value "${jdbc.driverClassName}"; nested exception is java.lang.IllegalArgumentException: Could not resolve placeholder 'jdbc.driverClassName' in string value "${jdbc.driverClassName}"

Looking around at various examples, they all seem to use this sort of set up (here's one). Any reason the placeholders aren't taking effect?

Thanks!

Community
  • 1
  • 1
user2490003
  • 10,706
  • 17
  • 79
  • 155

1 Answers1

0

Was able to self-diagnose the issue here.

My thought was that the PropertyPlaceholderConfigurer class would go through my environment sources and source each file I had in there.

Apparently that's been replaced since Spring 3.1 with a new class - PropertySourcesPlaceholderConfigurer.

From the docs for PropertySourcesPlaceholderConfigurer -

This class is designed as a general replacement for PropertyPlaceholderConfigurer in Spring 3.1 applications

So I updated my servlet XML file to be -

<beans:bean
  class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">

user2490003
  • 10,706
  • 17
  • 79
  • 155
  • 1
    Just use `` which does this for you and you shouldn't call `refresh` in your initializer class. That class is only for configuration the context before the container will refresh/start it. – M. Deinum Jan 30 '17 at 07:34