Thursday, June 18, 2009

Dude, where are my resources?

I was struggling with a stupid problem this week and it took me some time to realize what was going on, so I will post here the solution so nobody else needs to waste time on this matter again (and for future reference for myself as well ;)).

I wanted to read a .csv (comma separated value) text file that was inside one package in my application. Consider the simplified version of my code in the tree below.


src
|- main
|- java
|- com
|- App.java
|- resources
|- file.csv


The App.java had this (simplified) code:



public class App {

public static void main(String[] args) throws IOException {
URL url = App.class.getResource("com/resources/file.csv");
}
}



The value of the variable url was null. And there is one simple (and quite obvious once you find out) reason for this. The resource file was indeed in my src folder, but it was not in my destination folder where the classes were generated. As I am using maven, this would be the target folder.
And why is this obvious? Because the getResource method uses the ClassLoader of the calling class to find the resource you are looking for, and the realm of files the ClassLoader knows are in the classpath. As I was executing the code from my IDE, the classpath would be the compiled classes from sources. On top of that, the problem was that the text files not being copied to the destination folder.

Thanks to Maven the solution was quite simple. As it is based on convention over configuration, all I did was to move the resources folder to the root of the src/main folder like this:


src
|- main
|- java
|- com
|- App.java
|- resources
|- file.csv


The App.java had this (simplified) new version of the code:



public class App {

public static void main(String[] args) throws IOException {
URL url = App.class.getResource("file.csv");
}
}



In summary, just make the resource available somewhere in your classpath: in the target/classes folder or in the .jar you are generating.

Find this article also on definenull.com.

No comments: