Executable jar won't find the properties files
Solution 1
BalusC is right, you need to instruct Maven to generate a MANIFEST.MF
with the current directory (.
) in the Class-Path:
entry.
Assuming you're still using the Maven Assembly Plugin and the jar-with-dependencies
descriptor to build your executable JAR, you can tell the plugin to do so using the following:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>com.stackoverflow.App</mainClass>
</manifest>
<manifestEntries>
<Class-Path>.</Class-Path> <!-- HERE IS THE IMPORTANT BIT -->
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- append to the packaging phase. -->
<goals>
<goal>single</goal> <!-- goals == mojos -->
</goals>
</execution>
</executions>
</plugin>
Solution 2
There are two workarounds:
-
Don't use the JAR as executabele JAR, but as library.
java -cp .;filename.jar com.example.YourClassWithMain
-
Obtain the root location of the JAR file and get the properties file from it.
URL root = getClass().getProtectionDomain().getCodeSource().getLocation(); URL propertiesFile = new URL(root, "filename.properties"); Properties properties = new Properties(); properties.load(propertiesFile.openStream());
None of both are recommended approaches! The recommend approach is to have the following entry in JAR's /META-INF/MANIFEST.MF
file:
Class-Path: .
Then it'll be available as classpath resource the usual way. You'll really have to instruct Maven somehow to generate the MANIFEST.MF
file like that.
Solution 3
EDIT: this is to respond to your comment:
You need to make sure that the properties file is on the class path with the right root for the java invocation that stars up the jar file. if your path is
stuff/things.properties
and the runtime location is
/opt/myapp/etc/stuff/things.properties
and the jar file is in
/opt/myapp/bin/myjar
then you need to launch as
/path/to/java -cp "/opt/myapp/etc:/opt/myapp/bin/myjar.jar" my.pkg.KavaMain
working with this kind of config can be irksome in a dev environment, luckily, there's the maven exec plugin that will get you the right kind of launch scenario.
Original Answer:
You want to read about the maven resources plugin.
Basically you want to add something like this:
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*properties</include>
</includes>
</resource>
</resources>
</configuration>
<plugin>
to your pom.xml assuming that you're propertis file is with your java sources -- really it should be in src/main/resources.
Admin
Updated on February 03, 2020Comments
-
Admin over 4 years
I use this code in my program to load a properties file:
Properties properties = new Properties(); URL url = new App().getClass().getResource(PROPERTIES_FILE); properties.load(url.openStream());
The code runs fine in Eclipse. Then I package the program into a JAR named MyProgram.jar, and run it, I got a NullPointerException at the second line. The JAR doesn't contain the properties file, they both are in the same directory. I am using Maven to create the JAR. How can I fix this problem?
UPDATE: I don't want to add the properties file to the JAR, since it will be created at deployment time.
-
Admin over 13 yearsThanks, but I don't want to add the properties file to the JAR. It will be changed at deployment time.
-
BalusC over 13 yearsAs per your edit: the
-cp
argument is ignored when using-jar
argument. It has really to go inMANIFEST.MF
file :) -
Admin over 13 yearsOops I tried the first option before but I used . COMMA filename.jar. Maybe that's why it didn't work. Thanks for your help.
-
Devanshu Mevada over 13 yearsIf you're not using the maven assembly plugin, let me know and I'll update my answer.
-
Admin over 13 yearsWith the
executions
section, I don't have to runmvn assembly:assembly
separately right? By the way, thanks for answering all my questions on Maven. -
Devanshu Mevada over 13 years@HaiMinhNguyen: Indeed, the above
execution
binds thesingle
goal on thepackage
phase. As a result, runningmvn package
does create the assembly. Oh, and you're welcome. -
BalusC over 13 yearsYes, this is the approach you should take, Hai Minh Nguyen.
-
Bastien Jansen over 12 yearsHello, I tried using the above method to create a jar-with-depencies that could load a properties file located in the same directory but it does not work. I run my jar using "java -jar myjar.jar". I tried retrieving the properties file using both Class.getResource() Class.ClassLoader.getResource(), with and without a leading slash in the file name, but none of these work. If i println the content of java.class.path, I only get my jar file (no ".", though it is correctly set in the MANIFEST's Class-Path). Could someone help me please?
-
lscoughlin about 12 years@BalusC righto, fixed up. Can't go in the MANIFEST.MF if it could move at runtime.
-
matbrgz over 11 yearsThere's one reason for avoiding the Classpath - namely if the content changes between reads. The resource loader caches the first content
-
jgreen over 8 yearsThis thread was helpful to me. In my case (non-maven project), I also had to make the path of the resource I was requesting (which was buried in my src tree) absolute by prefacing it with a "/" (linux).