Search code examples
springproperties-filespring-environment

Load different properties for development and deployment


I have a very common use case -- connect to different databases when my program is in development mode, in test mode, or in deployment mode.

The way I am doing it now, is I configure a data source, and pass it ${...} properties via bean:property tag.

However to get the ${...}, i am doing

<context:property-placeholder properties-ref="myProperties" />

and in the bottom of the xml config, I have

<beans profile=test>
   <util:properties id=myProperties>
   </util>
</beans>
<beans profile=dev,default>
   <util:properties id=myProperties>
</beans>
<beans profile=prod>
  <util:properties id="myProperties>
</beans>

This seems inefficient, overly verbose, and prone to error. All spring properties tutorials tell me that context:property-placeholder is Environment aware, and Environment is responsible for profiles so how do I simplify this? It is intuitive to me that there is a simpler way, I just can't figure it out.

Really, what I am looking for is to specify profile on context:properties-placeholder, or something like that.


Solution

  • I solved that problem once (a long time before Spring supports profiles): spring property substitution for test and production

    nowadays a would still use property files but, but I would select them by profiles. There are a lot of ways to do this:

    The simplest one is:

    <context:property-placeholder
             location="classpath*:META-INF/spring/config-${spring.profiles.active}.properties" />
    

    an other is:

    <beans profile="normal">
        <context:property-placeholder 
                 location="classpath*:META-INF/spring/config-normal.properties"/>
    </beans>
    <beans profile="test">    
          <context:property-placeholder
                 location="classpath*:META-INF/spring/config-test.properties"/>
    </beans>
    

    The first approach has the drawback, that when more than one profile is activated then only the properties for the first profile gets loaded. I am not sure what will happen with the second approach when having more than one profiles.

    For the first approach I found this solution, but I have not tested it:

    <bean id="propertyConfigurer"
          class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
          <property name="locations">
            <list>
                <value>classpath*:META-INF/spring/*_${spring.profiles.active}.properties</value>
            </list>
          </property>
    </bean>