1

I have the bean definitions below. If I change the placeholderPrefix for the "exposeSystemProperties" bean to "${" and use that in the properties path of the second bean, it works. If I change it to anything but "%{" it doesn't work. I can't use any other string (e.g. "$sys{", "#[", etc.). I'm currently on 3.0.5.RELEASE.

Any thoughts as to why this is? To compound it all, I have a 3rd PropertyPlaceHolderConfigure, so only having two prefixes does not work.

  <bean id="exposeSystemProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreUnresolvablePlaceholders" value="true" />
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
    <property name="placeholderPrefix"><value>$sys{</value></property>
    <property name="order" value="10" />
  </bean>

  <bean id="localFileProperties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreUnresolvablePlaceholders" value="true" />
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_NEVER" />
    <property name="placeholderPrefix" value="%{" />
    <property name="placeholderSuffix" value="}" />
    <property name="order" value="20" />
    <property name="locations">
      <array>
        <bean class="java.lang.String">
            <constructor-arg><value>classpath:properties/$sys{deploy.env}/client.properties</value></constructor-arg>
        </bean>
      </array>
    </property>
  </bean>
Spencer Kormos
  • 8,381
  • 3
  • 28
  • 45

1 Answers1

2

Since what you need the prefix for is to control environment specific properties, this can be done by using system variables ( instead of a deploy.env property in your example ):

 <value>classpath:properties/${ENV_SYSTEM:dev}/client.properties</value>

In this case it will always look under:

 <value>classpath:properties/dev/client.properties</value>

by default, unless a ENV_SYSTEM system variable is set. If it is set to "qa", for example, it will automatically look under:

 <value>classpath:properties/qa/client.properties</value>

Another approach, in case you are open to "look into the future" a bit, is to use Spring 3.1's PROFILE feature, where beans can be profile specific. For example:

<beans profile="dev">
    <jdbc:embedded-database id="dataSource">
        <jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
        <jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
    </jdbc:embedded-database>
</beans>

This dataSource will only be loaded in case a profile is set to dev:

GenericXmlApplicationContext ctx = new GenericXmlApplicationContext();
ctx.getEnvironment().setActiveProfiles( "dev" );
ctx.load( "classpath:/org/boom/bang/config/xml/*-config.xml" );
ctx.refresh();
tolitius
  • 22,149
  • 6
  • 70
  • 81
  • So you're saying Spring loads up the System variables to the context? I thought you needed to expose that another way. – Spencer Kormos Oct 03 '11 at 05:55
  • @Spencer, yes: `System`/`Environment` variables _are_ available to Spring at application context creation, so you can rely on them to drive the environment. These variables can be set in multiple ways, for example: `System.setProperty( "ENV_SYSTEM", "qa" )` or you can simply pass it through `-D` JVM arguments: `-DENV_SYSTEM=qa` – tolitius Oct 03 '11 at 13:12
  • This certainly works around my problem, though still doesn't necessarily fix the issue of why the configurers aren't resolving properly. I haven't had the time to actually debug this inline, but when I do, it's the first thing on my list. Thanks for the different viewpoint. – Spencer Kormos Oct 03 '11 at 15:33
  • sure. once you try it, and it _will_ work, you won't go back :) as ENV variables and/or PROFILEs are cleaner and a bit more intuitive way to switch between different environments – tolitius Oct 03 '11 at 15:48