Accessing bundled resources in Java packages
This is sort of a continuation of a previous post about how to integrate your own Java classes into the Maven build lifecycle. This entry described how to generate files for inclusion in the final project artifact (ie. .jar
, .war
etc.). It took me some time to figure out how to access these files using Java’s resource mechanism so this post will summarize my findings.
Resource locations
If you follow the Maven convention your source code is located in src/main/java/
and the source code for your tests in src/main/test/
. Resource files will be in src/main/resources/
and src/test/resources/
respectively. In the final artifact the resouce files will be located in target/classes/
or target/test-classes/
. Sub-directories will be preserved.
If you want to be able to access a file during runtime drop them in either of these resource folders depending on whether you want to access them during tests or in your actual application.
Packaging
Copying resources to target/
will be done automatically by Maven. After packaging to .jar
etc. the contents of target/test-classes/
will not be included while the contents of target/classes/
will be found in the root directory of the artifact (for jar
packaging) or in WEB-INF/classes/
(for war
packaging)
Accessing resources
During runtime of the artifact you can access resources with
InputStream resource = SomeClass.class.getResourceAsStream("<file or directory name"))
or
URL resource = SomeClass.class.getResource("<file or directory name"))
where SomeClass
is a class in the artifact. The first way will give you an InputStream
that you can use to read the contents of the file, the second way will return a URL
that you can use to find out the path of the file or directory or move along the directory tree.
Accessing a resource will be delegated to the classloader of the class you use to load the resource. So when SomeClass
is a class in a dependency of your project the resource will be loaded from that dependency’s artifact.
Resource paths
Resources have a notion of absolute and relative paths. The resource /filename
will be resolved to target/classes/filename
whereas filename
will be resolved using the package of the class ie. with org.example.SomeClass
it will be resolved to target/classes/org/example/filename
. Again, for test classes the base resource directory will be target/test-classes/
.
Note that you do not have to give a file name at all. /
for example will be resolved to just target/classes/
.
Comments are closed.