Java/Maven

Maven Variables in Java context

Maven is a very convenient and powerful tool for managing large projects, their builds, testing, deployment, versions, etc. It is so great, that sometimes it would be nice to have access to Maven variables from Java or other source language.

For example when writing a test case with JUnit I would like to use some data in an XML file. The file is distributed with the project as part of testing routines.

However getting hold of it’s location in Java is not easy.

  1. One could use the current working directory and assume that it is always the project root (where the pom.xml file is located), but that is really really not flexible although really simple when there is just one project to build.
  2. One could try fiddling with the Class Loader and possibly find the location of a specific class and then from that deduce the location of the test file. Very tedious and somewhat not elegant.
  3. One could try getting hold of one of Mavens variable values. For example ${basedir} contains the project root. This would be flexible and quite general as the code will be run through Maven all the time anyway.

So let’s look at option 3 more closely. Maven variables can be used in the maven scripts. If you are writing Maven plugins there are ways of getting these values. But if you are running a separate application, which is not part of Maven – there is no easy solution.

One way is to use the filtering capabilities of Maven.

For example, one could have a myproject.properties file somewhere in the project, where you would specify some configuration options.


// src/test/resources/myproject.properties
// .............
project.root=${basedir}
// .............

Now we have to let Maven know that it should help us and nicely provide the values we are after.

<!-- pom.xml -->
<project>
  <build>
    <testResources>
       <testResource>
         <directory>src/test/resources</directory>
         <filtering>true</filtering>
       </testResource>
    </testResources>
 </build>
</project>
       

The testResources directive with the filtering turned on will ask Maven to go through all files in src/test/resources and replace the Maven variables within then with the values. After it has done that it will put the files on the classpath of your application so you can get hold of them really easy.If one were to replace testResources with resources it would affect the application execution rather than just the testing.In Java all you have to do is load the properties file and there you go:


java.util.Properties props = new java.util.Properties();

// Get hold of the path to the properties file
// (Maven will make sure it's on the class path)
java.net.URL url = Config.class.getClassLoader().getResource("sql.properties");

// Load the file
props.load(url.openStream());

// Accessing values
porps.getProperty( "project.root" ); // This will return the value of the ${basedir}

That is it, we are done. Now that we have the project root, it is trivial to reference any file within the source tree with no dependence on the class layout or the current directory.

Standard

5 thoughts on “Maven Variables in Java context

  1. Thanks for the post. Really helped me to understand in Java Context. By the way, if one wants to read in Spring MVC context (i.e., using Spring dependency injection)
    ” to your bean.

    -Chandan Benjaram

  2. Another option is to pass the variables in via system properties. In you maven pom…

    org.apache.maven.plugins
    maven-surefire-plugin
    2.7.2


    ${project.basedir}

    Then within your tests…

    System.getProperty(“project.basedir”);

  3. Another option is to pass the variables in via system properties. In you maven pom…

                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>2.7.2</version>
                    <configuration>
                        <systemPropertyVariables>
                            <!-- Expose the build directory as a system property to unit tests -->
                            <project.basedir>${project.basedir}/..</project.basedir>
                        </systemPropertyVariables>
                    </configuration>
                </plugin>
    

    Then within your tests…

    System.getProperty(“project.basedir”);

Leave a comment