くらげになりたい。

くらげのようにふわふわ生きたい日曜プログラマなブログ。趣味の備忘録です。

Mavenでよくする設定とFatJarとFatJarのクラスパス設定でハマる

javaでライブラリとかをまとめるFatJar(実行可能jar)は、Javaを知らない人に渡すときに便利。
でも、いろいろとはまったので、その備忘録。

ハマりまくって、学んだことは、2つ。

  1. 実行可能jarのクラスパスは、実行時に指定できない
    • jar内のMETA-INF/MANIFEST.MFに設定があるため。
  2. 実行可能jarを直接実行すると、標準出力が表示されない
    • $ ./xxxx.jarを実行すると、$ javaw -jar xxxx.jarとして実行されるため。

コンパイラJavaバージョンを指定

<project>

    <properties>
        <!-- 文字コードの指定 --> 
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

        <!-- コンパイルするJavaのバージョンを指定。デフォルトだと1.5になるのでハマる -->
        <java.version>1.8</java.version>
        <maven.compiler.target>${java.version}</maven.compiler.target>
        <maven.compiler.source>${java.version}</maven.compiler.source>
    </properties>

</project>

clean時にローカルのjarをインストールする設定

そんなときは、Apache Maven Install Pluginを使う。

<project>
  <build>
    <plugins>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-install-plugin</artifactId>
        <executions>
          <execution>
            <id>install-external</id>
            <phase>clean</phase>
            <configuration>
              <file>${project.basedir}/src/main/resources/mylib-1.0.0.jar</file>
              <repositoryLayout>default</repositoryLayout>
              <groupId>jp.my.libs</groupId>
              <artifactId>mylib</artifactId>
              <version>1.0.0</version>
              <packaging>jar</packaging>
              <generatePom>true</generatePom>
            </configuration>
            <goals>
              <goal>install-file</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

    </plugins>
  </build>
</project>

package時にFatJarを作る設定

<project>
  <build>
    <plugins>

      <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.2</version>
        <executions>
          <execution>
            <id>make-assembly</id>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>MyMain</mainClass>
            </manifest>
            <manifestEntries>
              <!-- クラスパスの設定はここでする!!。 起動オプションでは有効にならない。 -->
              <Class-Path>./</Class-Path>
            </manifestEntries>
          </archive>
        </configuration>
      </plugin>

    </plugins>
  </build>
</project>

ここが最大のハマリポイントだった。。

プロパティファイルをローカルに配置して読み込むが、読み込まれず。。。
クラスパスを見ても、カレントディレクトリが含まれておらず。。。

jarの中に同梱されるMETA-INF/MANIFEST.MFを変更しないといけないらしい。。

ちなみに、実行しているjarの、クラスパスの確認方法は以下な感じ。(つさんの記事から引用)

System.out.println("classpath : " + System.getProperty("java.class.path"));

とりあえず、<manifestEntries><Class-Path>./</Class-Path></manifestEntries>を追加して、読み込めるようになったが、
実行してみると別の問題が。。。

jarを直接実行すると、標準出力が表示されない

$ java -jar xxxx.jarで実行すると表示されるが、$ ./xxxx.jarとすると表示されないよう。。
この記事をみると以下のように書いてある。

ただし これは「javaw -jar hello.jar」が裏で実行されているだけ。
すなわち(javaでなくjavawだから)ウィンドウが開かないので、System.out.println()等でコンソール入出力をしているプログラムは何も表示されない。

おぉぉ。とりあえず、jreをインストールしてもらう or 同梱して配布するか。。。

以上!!

参考にしたサイト様