Search code examples
javamavenpropertiesmaven-assembly-plugin

Java properties file in jar not found when running jar


When I run main() from IntelliJ I got as, expected peter,johnson as result in standard out. But when I run mvn clean package and try to execute java -jar target/example-1.0.0-SNAPSHOT-jar-with-dependencies.jar I get following error message. Why and how can I make sure that .properties file is read?

java -jar target/example-1.0.0-SNAPSHOT-jar-with-dependencies.jar
Exception in thread "main" java.io.FileNotFoundException:      file:/Users/ismar.slomic/src/ADOP/example/target/example-1.0.0-SNAPSHOT-  jar-with-dependencies.jar!/my-example.properties (No such file or   directory)
at java.io.FileInputStream.open0(Native Method)
at java.io.FileInputStream.open(FileInputStream.java:195)
at java.io.FileInputStream.<init>(FileInputStream.java:138)
at java.io.FileInputStream.<init>(FileInputStream.java:93)
at com.example.MyPropertiesClass.getFullName(MyPropertiesClass.java:18)
at com.example.MyMainClass.main(MyMainClass.java:9)

MyMainClass

package com.example;

import java.io.IOException;

public class MyMainClass {

   public static void main(String[] args) throws IOException {
       MyPropertiesClass mpc = new MyPropertiesClass();
       System.out.println(mpc.getFullName());
   }
}

MyPropertiesClass

package com.example;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

public class MyPropertiesClass {

  public String getFullName() throws IOException {
    Properties properties = new Properties();
    ClassLoader cl = this.getClass().getClassLoader();
    String filePath = cl.getResource("my-example.properties").getFile();

    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
    properties.load(bis);

    String name = properties.getProperty("name");
    String lastname = properties.getProperty("lastname");
    return name + "," + lastname;
  }
}

my-example.properties

name=peter
lastname=johnson

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="http://maven.apache.org/POM/4.0.0"
     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>example</artifactId>
<version>1.0.0-SNAPSHOT</version>

<name>${project.artifactId}</name>
<description>My Example</description>

<properties>
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<build>
    <plugins>
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.0.0</version>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                        <classpathPrefix>lib/</classpathPrefix>
                        <mainClass>com.example.MyMainClass</mainClass>
                    </manifest>
                </archive>
            </configuration>
            <executions>
                <execution>
                    <id>make-assembly</id>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>


Solution

  • If your property file is inside your jar, then you'd better to use getResourceAsStream instead of getResource and getFile.

    Something like:

      ClassLoader cl = this.getClass().getClassLoader();
      try (InputStream stream = cl.getResourceAsStream("my-example.properties")) {
         properties.load(bis);
      }
    

    The method getResource(String)returns an URL that points to a file inside a jar. In your case, something like: file:/Users/ismar.slomic/src/ADOP/example/target/example-1.0.0-SNAPSHOT-jar-with-dependencies.jar!/my-example.properties. When you call getFile on that URL, it returns the file (i.e. the jar) which and not the pointer to the properties file inside.

    What could also work is to open a connection on the URL and use the returned JarURLConnection. But it is easier with getResourceAsStream.