views:

1347

answers:

5

My application needs to know the path to a directory where it can store its data. I tried to set a Java system property and use that variable as a placeholder in my Spring XML.

In Eclipse I added that property to the environment of my run configuration and it works just fine. Spring resolves ${dataDir} to the correct path.

But when I test the application using Maven2 (mvn test -DdataDir=c:/data), Spring complains that it can't resolve the placeholder.

My Spring XML looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"

 xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans.xsd
      http://www.springframework.org/schema/tx
      http://www.springframework.org/schema/tx/spring-tx.xsd"&gt;

 <!-- Allows me to use system properties in this file -->
 <bean id="propertyPlaceholderConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" />

 <bean id="xmlConfiguration" class="org.apache.commons.configuration.XMLConfiguration">
  <constructor-arg index="0">
   <value>${dataDir}/conf/config.xml</value>
  </constructor-arg>
 </bean>
</beans>

Why isn't that system property passed to Spring? What am I doing wrong? Thanks for any suggestions!

EDIT: Of course, you're right: ${baseDir} should be ${dataDir}. But that was just a typo in this question, not in the real code.

I tried *MAVEN_OPTS* before but it doesn't work either...

+1  A: 

Perhaps mvn test doesn't pass through the system properties that it is run with to the tests? Would it be possible to pass the properties using the test plugin (which itself may pull them from the System properties)?

See also: http://maven.apache.org/maven-1.x/plugins/test/properties.html

jsight
This is the best solution - embed any required properties in your POM file. This way they are stored with the project so that all team members have access to them (and don't have to set up their env separately), and so they are version-controlled.
John Stauffer
A: 

If you look at the mvn script, you can see that all arguments passed via the command line are passed as arguments to the launch class, not as arguments to the JVM. So -D won't work.

The quickest workaround is to define the MAVEN_OPTS environment variable, e.g.

set MAVEN_OPTS="-DdataDir=c:/data"

and then run mvn test

skaffman
A: 

May be you should use identical variable names? I mean that you pass dataDir, but expect baseDir. Am I wrong?

Andrew Dashin
+4  A: 

This is a known bug in the Surefire plugin 2.4.3. For details, see JIRA issue "System properties set on the command line get clobbered". Use the previous version, 2.4.2 instead:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-surefire-plugin</artifactId>
      <!-- Use 2.4.2 because 2.4.3 has bug with system properties
           see http://jira.codehaus.org/browse/SUREFIRE-121 -->
      <version>2.4.2</version>
    </plugin>
  </plugins>
</build>
flicken
A: 

I think that flicken's answer is the right answer to your question.

However, I'd suggest to move the config.xml file in src/test/resources. This seems to be a perfect location (in maven's world) and, this way, the file will be available on the classpath (so you won't have to use an absolute path). On top of that, the file will end up in the version control like any other resource of the project which is a good thing.

If really you want to keep it outside the project structure, I'd use resources filtering to filter your Spring configuration file and set ${dataDir} at build time.

Pascal Thivent
The file should be stored outside the project because it must not be overwritten when I want to update the application. But keeping it under Version Control is a good point. Have to think about that
Olvagor