Take the 2-minute tour ×

I am currently working on a JUnit test that checks functionality responsible for loading/saving a process configuration from/to some file. Given that a particular configuration file is present in resources, the functionality loads parameters from the file. Otherwise the functionality attempts to create new configuration file and persist a default configuration coded in the class. Right now I am using .class.getResource() method to check if configuration file exists, and to retrieve the necessary information. This approach is proven to be working fine from both maven's "test-class" and "class" directories. However, I am having problems while attempting to save default configuration when the file does not exist, namely the .class.getResource() method returns null, as the resource does not yet exist. This stops me from building the target resource directory (context-dependent) where the file should be saved.

Is there a way to code my functionality to evaluate whether particular object is being executed as a test or in production? More precisely, how can I build a relative path to my resource files to point to either production resources (../classes/...) or test resources (../test-classes/..) depending on the execution mode in which the project currently is?

My question is somewhat similar to the following How should I discover test-resource files in a Maven-managed Java project? but I think it is different enough to warrant new thread.

share|improve this question

2 Answers 2

If I understand you right, essentially your issue is that you have a Maven project, which reads a particular file (normally, and during unit tests), that determines the application's behaviour. If that file doesn't exist, your application creates it.

The problem with ClassLoader.getSystemResource(...), is that it's not actually scanning a single directory. Instead it's looking at Java's classpath to determine the location of that particular resource. If there's multiple directories on the classpath, it'll have a number of areas that the file could potentially be located in.

In a sense then, .getSystemResource(...) is one way. You're able to look-up the location of a file, but not get the appropriate location to place it.

*So what about when you need to put the file in the correct location?*

You have two options essentially:

  1. Hard-code the location of the file: Noone likes doing that.
  2. The locations that are scanned on the classpath are passed into the classloader. You could use, for example, the first one and create the file there.

The second option isn't actually a bad one; have a look at this sample code.

    final Enumeration<URL> urls = ClassLoader.getSystemClassLoader().getResources("");
    if(! urls.hasMoreElements()) {
        LOG.error("No entries exist on the class path!");
    final File configFile = new File(urls.nextElement().getFile(), "config.xml");
    LOG.info("Create a new configuration file: " + configFile.getPath());

This resolved the configuration file to be within my target folder: ..\target\classes\config.xml

Up to you what you do; happy to provide more tips & advice if you feel more is required.

share|improve this answer
If you feel that answer resolves your issue, please mark it accordingly. :) –  Teh Hippo Aug 13 '12 at 23:28

It sounds like you want to do the following:

When your code runs, it tries to load the configuration file. When the configuration file is not found you want to create the configuration file. The twist is that

  • if you are executing the code in "production mode" (I presume using something like the exec-maven-plugin or jetty-maven-plugin depending on the nature of your code) you want the configuration file to be placed in ${project.build.outputDirectory}

  • if you are executing the code in "test mode" (e.g. via surefire or failsafe) you want the configuration file to be placed in ${project.build.testOutputDirectory}

What I would do is use the ServiceLoader pattern.

You create a ConfigFileStore interface that is responsible for storing your configuration.

The ConfigFileStoreFactory enumerates all the services implementing that interface (using the ServiceLoader API by getting all the /META-INF/services/com.yourpackage.ConfigFileStore resources and extracting the class names from those. If there are no implementations registered then it will instantiate a default implementation that stores the file in the path based on getClass() (i.e. working backwards to get to the ${project.build.outputDirectory} note that it should handle the case where the classes get bundled up into a JAR, and I would presume in such a case the config file might get stored adjacent to the JAR)

Note: The default implementation will not be registered in /META-INF/services

Then in src/test/java you extend the default implementation and register that extended implementation in src/test/resources/META-INF/services/com.yourpackage.ConfigFileStore

Now when running code that has the test code on the classpath, the test version will be found, that will pick up the getClass() for a class from ${project.build.testOutputDirectory} because it is from the test classpath's /META-INF/services.

When running code that does not have the test code on the classpath, the default implementation will pick up the getClass() for a class from ${project.build.outputDirectory}

Should do what you want.

share|improve this answer

Your Answer


