Datei innerhalb einer JAR Datei lesen

Kurzer Code-Schnippsel, um eine properties-Datei, die in einem Paket aus einer JAR-Datei steckt, einzulesen:

1
2
3
4
5
6
7
8
9
10
    Properties properties = new Properties();
    try
    {
      InputStream is = this.getClass().getClassLoader().getResourceAsStream("com/oberprima/upload/client/configuration/config.properties");
      properties.load(is);
    }
    catch (IOException ex)
    {
      System.out.println(ex.getLocalizedMessage());
    }

Eigene JAR-Bibliothek in Maven-Projekt verwenden

Apache Maven ist wundervoll. Aber wie bekommt man die eigene JAR-Bibliothek als Maven-Abhängigkeit in sein Projekt? Das geht einfacher als gedacht. Man muss dazu nur folgendes in die Konsole eingeben:

mvn install:install-file -Dfile=C:\path\to\my-lib-0.1.jar -DgroupId=com.mycompany.mylib -DartifactId=MyLibrary -Dversion=0.1 -Dpackaging=jar

Danach kann man in der pom.xml von seinem Maven-Projekt die eigene Bibliothek über folgenden Eintrag einhängen:

1
2
3
4
5
6
7
...
    <dependency>
      <groupId>com.mycompany.mylib</groupId>
      <artifactId>MyLibrary</artifactId>
      <version>0.1</version>
    </dependency>
...

Vielen Dank an How to include library manually into maven local repository?.

Mehrere externe JARs in eine JAR einbinden

Das Einbinden von externen JAR-Bibliotheken in der eigenen JAR ist mit einem Apache Ant Build-Task recht einfach. Für mein Beispiel verweise ich auf dieses [post id=2583]Ant Build Skript[/post]. Mit nur einer weiteren Zeile (Zeile Nummer 6) kann man die build.xml so erweitern, dass alle externen Bibliotheken aus dem /lib-Verzeichnis in die eigene JAR gepackt werden:

1
2
3
4
5
6
7
<jar destfile="${jar.dir}/${ant.project.name}-${app.version}.jar" basedir="${classes.dir}">
	<manifest>
		<attribute name="Main-Class" value="${main.class}" />
		<attribute name="Class-Path" value="${manifest.class.path}" />
	</manifest>
	<zipgroupfileset dir="${lib.dir}/."/>
</jar>

Das zipgroupfileset unterstützt alle Attribute des <fileset>, wodurch über folgenden Befehl einzelne Dateien ausgeschlossen werden können:

1
<zipgroupfileset dir="${lib.dir}/." excludes="junit-4.8.2.jar" />

Für weitere Infos verweise ich auf den Beitrag „NetBeans – deploying all in one jar“ von stackoverflow.

Aktuellen Pfad einer Java-Anwendung ermitteln

Wenn man mit Java eine JAR-Datei ausführt, dann wird nicht die JAR-Datei ausgeführt, sondern der Java-Bytecode dieser JAR-Datei. Der Java-Bytecode liegt aber nicht im Speicherort der JAR-Datei und somit können Referenzen wie bsp. new File("serverlog.txt"); nicht richtig gefunden werden, wenn man davon ausgegangen ist, dass in diesem Fall die Datei serverlog.txt im selben Ordner wie die ausgeführte JAR-Datei zu finden ist.

Man muss sich deshalb den zur Laufzeit gültigen Pfad der JAR-Datei holen. Für dieses Vorhaben habe ich mir eine eigene Methode geschrieben:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  /**
   * Returns the path where the currently running JAR-file is located.
   * Example value: C:\MyProject\build\jar\
   * @return Path of the JAR-file
   */
  public static String getJarExecutionDirectory()
  {
    String jarFile = null;
    String jarDirectory = null;
    int cutFileSeperator = 0;
    int cutSemicolon = -1;
 
    jarFile = System.getProperty("java.class.path");
    // Cut seperators
    cutFileSeperator = jarFile.lastIndexOf(System.getProperty("file.separator"));
    jarDirectory = jarFile.substring(0, cutFileSeperator);
    // Cut semicolons
    cutSemicolon = jarDirectory.lastIndexOf(';');
    jarDirectory = jarDirectory.substring(cutSemicolon+1, jarDirectory.length());
 
    return jarDirectory+System.getProperty("file.separator");
  }

Diese Methode liefert aber nur den richtigen Ort, wenn man die JAR Datei über die Konsole (java -jar meinprojekt.jar) ausführt. Deswegen möchte ich anhand eines Beispiels noch einen zweiten, zuverlässigeren Weg aufzeigen:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    String propertiesFilePath = "client.properties";
    File propertiesFile = new File(propertiesFilePath);
 
    if (!propertiesFile.exists())
    {
      try
      {
        CodeSource codeSource = MainView.class.getProtectionDomain().getCodeSource();
        File jarFile = new File(codeSource.getLocation().toURI().getPath());
        String jarDir = jarFile.getParentFile().getPath();
        propertiesFile = new File(jarDir + System.getProperty("file.separator") + propertiesFilePath);
      }
      catch (Exception ex)
      {
      }
    }
 
    System.out.println(propertiesFile.getAbsolutePath());