1

I want to control loading of a property file using Spring's property-placeholder and setting a system property. This works like it should:

  <context:property-placeholder
location="classpath:jdbc/jdbc.${TARGET_ENV}.properties" />

When I run my application in different environment, I set system property TARGET_ENV and correct property file is picked up.

Now I have my integration tests, and I want to force configuration to load a specific property file (jdbc.INTEGRATION_TESTS.properties) always.

I have

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
    "classpath:/META-INF/spring/set-system-property.xml", 
    "classpath:/META-INF/spring/applicationContext.xml"}) 
public class AbstractIntegrationTest extends AbstractTransactionalJUnit4SpringContextTests {

and set-system-property.xml (using advice from Set System Property With Spring Configuration File):

<beans>
<bean id="systemPrereqs"
    class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
    <property name="targetObject" value="#{@systemProperties}" />
    <property name="targetMethod" value="putAll" />
    <property name="arguments">
        <util:properties>
            <prop key="TARGET_ENV">INTEGRATION_TESTS</prop>
        </util:properties>
    </property>
</bean>

but the property is not picked up by Spring:

Caused by: java.io.FileNotFoundException: class path resource [jdbc/jdbc.${TARGET_ENV}.properties] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.java:157)

Why does this not work? Is there something about bean instantiation, factory beans etc, that I am not getting?

Community
  • 1
  • 1
Janne Mattila
  • 598
  • 7
  • 20

1 Answers1

0

I'm not sure but isn't setting the system property from a Spring context file not already too late? We use a similar setup but instead of changing the system property for tests we use a test-context.xml which uses a fixed path for loading the properties

eg in the test:

    <bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:be/xxx/broker/standalone-test.properties</value>
        </list>
    </property>   
</bean>       

vs

    <bean id="bridgePropertyPlaceholder" class="org.apache.camel.spring.spi.BridgePropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>${BROKER_CONF}</value>
        </list>
    </property>   
</bean>

in the real context.

Just ignore here that I'm using a Camel propertyplaceholder, we also do this with a regular Spring Propertyplaceholder, but couldn't find an example right now.

Nicolas Mommaerts
  • 3,207
  • 4
  • 35
  • 55
  • Yeah, I ended up using a similar solution. I would still like to know WHY to original solution does not work. How come setting system property is too late? So I am not marking this answered yet. – Janne Mattila Jan 18 '13 at 06:45
  • I would guess that before Spring starts parsing its context files, it takes all the environment variables that are declared at that time. The context:placeholder bean will be processed before the bean that changes the environment property, or the order is not deterministic. – Nicolas Mommaerts Jan 18 '13 at 15:24