Home > Code Hints, HOW TO > Use a classpath resource or kill your application’s portability

Use a classpath resource or kill your application’s portability

Here is the secret way to kill your application’s portability — and by portable, I mean across different computers, let alone operating systems:  Hardcode all your paths.

That’s it.  That very quickly kills portability.  It’s easy to accomplish, too.  Simply refer to all your configuration files, for example, by fully qualified pathname, like this:

System.setProperty("com.yourcorp.refdata.config.filename",
    "C:\\Documents and Settings\\FOO\\Perforce_FOO\\PATHS_CHANGED_FOR_ANONYMITY\\RefDataConfig.xml");

The above snippet is something I’m battling with to get unit tests working in my project. Naturally it doesn’t work for me because “FOO” isn’t my username nor is my Perforce sandbox “Performance_FOO” because, again, “FOO” isn’t my username.

This unit test won’t work across machines using the same OS, and our brethren using Macs or Linux boxes are completely hosed.

Don’t hardcode any paths in your application!

In Java, use a classpath resource.   This gives you portability.  It also allows a Configuration Management team the ability to package all required resources into a single artifact for better version control.

The safest way to get a classpath resource would be to use your current classloader to find the resource.

// Well-behaved Java programs set the thread's current classloader when running in a
// multi-classloader environment.  You see this when you write containers of any type.
Thread.currentThread().getContextClassLoader().getResource("/some/path/RefDataConfig.xml");

// or another way... sufficient for most cases
this.getClass().getClassLoader().getResource("/some/path/RefDataConfig.xml");
Categories: Code Hints, HOW TO Tags:
  1. July 10th, 2009 at 15:48 | #1

    Even though they’re not as good as your solution, relative paths are still more portable than absolute ones. From a platform-portability standpoint (which I know wasn’t what you were covering), I’ve tried to encourage people to use forward-slashes everywhere, since Java is fine with forward-slash paths on Windows but not with backward-slash paths on Unix/Linux. You probably knew that already, but perhaps someone else reading this didn’t.

    –Matt

  2. July 10th, 2009 at 17:58 | #2

    That’s true, Matt. I also like the forward slash trick because it works really well on Windows. I used it when I wrote an example about Java bootstrapping where the example looks for “/usr/local/src.” This defaults to “C:/usr/local/src” on Windows.

  3. July 17th, 2009 at 01:02 | #3

    I recommend pulling from a config path set by a system property with a reasonable default.

    We have configuration set in resource bundles and it has been painful. Worse, somewhere along the way, multiple ’systems’ were added to pull from one resource bundle or another based on machine name or user name. As we struggle to figure out which configuration bundle is the one in effect, changing it is slowed by having to go through the compile phase first.

    Configuration should be external.

    It looks like the solution we are settling on is a relative path in a reasonable default root that can be adjusted via a system property. This makes it easy to change a CI build which may be running multiple branches (and configurations) on the same machine on the same user account.

    So..have you encountered collisions in the java.io.temp dir yet?

    -s

  1. No trackbacks yet.

Switch to our mobile site