ツールをみんなで共有したいときなど、各自にライブラリ Jar を用意してもらうのはなかなか難しいと思います。単純にダブルクリックやコマンドライン一行で使用できるよう、全てのライブラリを Jar ファイルに含めてしまう方法を紹介したいとおもいます。
このような Jar ファイルを「Fat Jar」と呼びます。
また、開発者が移動や退職したので、ツールのメンテナンスができなくなった、という状況を回避できるよう、Jar ファイルと同じフォルダに、ソースコードも 一緒に圧縮して置いてもらう設定も行います。
ツールの作成
本題とは余り関係ないですが、簡単なツールを作ります。
標準入力で入力された、カンマ区切りファイルをタブ区切りに編集して、標準出力に表示します。
オープンソースの open csv という Csv ファイルの操作が容易になるライブラリを使用します。
Main.java
package sample; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.InputStreamReader; import com.opencsv.CSVReader; public class Main { public static void main(String... args) throws Exception { final File file; // 標準入力から取得したパスを file に格納する。 try (BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) { file = new File(br.readLine()); } // 1行ずつ読み込んで、タブ区切りに変換して出力する try (CSVReader cr = new CSVReader(new FileReader(file))) { String[] arr; while ((arr = cr.readNext()) != null) { String s = ""; for (int i = 0; i < arr.length; i++) { s = i == 0 ? arr[i] : s + "\t" + arr[i]; } System.out.println(s); } } } }
これで、例えば以下のようなファイルを text.csv として C:\tmp フォルダ配下に格納します。
aaa,bbb,ccc ddd,eee,fff ggg,hhh,iii
実行したときのイメージです。
ファイルのパスを入力してください。: C:\tmp\text.csv ← これは手で入力した。 aaa bbb ccc ddd eee fff ggg hhh iii
カンマ区切りがタブ区切りに編集されていることが分かります。
通常の Jar ファイルを作成するときの pom.xml はこちら。
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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>org.yyama</groupId> <artifactId>sample</artifactId> <packaging>jar</packaging> <version>0.0.1-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>4.1</version> </dependency> </dependencies> </project>
依存ライブラリを含めた実行可能 Jar にする
今のままだと、作成した Jar を単独で実行できません。
例えば、作成された Jar ファイルを任意のフォルダにコピーし、実行すると次のようになります。
C:\tmp>java -jar sample-0.0.1-SNAPSHOT.jar sample-0.0.1-SNAPSHOT.jarにメイン・マニフェスト属性がありません
最初にどのメソッドを実行すればいいのか分からないからですね。
じゃあ次のように、main メソッドが含まれたクラスを指定した場合は、どうなるでしょうか?
C:\tmp>java -classpath ./sample-0.0.1-SNAPSHOT.jar org.yyama.Main
実行はできましたが、open csv のライブラリが見つからないのでエラーとなってしまいます。
ファイルのパスを入力してください。: C:\tmp\text.csv ← これは手入力 Exception in thread "main" java.lang.NoClassDefFoundError: com/opencsv/CSVReader at org.yyama.Main.main(Main.java:22) Caused by: java.lang.ClassNotFoundException: com.opencsv.CSVReader at java.net.URLClassLoader.findClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source) at java.lang.ClassLoader.loadClass(Unknown Source) ... 1 more
それでは、依存ライブラリを含む かつ 実行可能な Jar を作成します。
pom.xml ファイルに次の build タグ以下を追記します。 タグの下に追記します。
<build> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>3.1.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>org.yyama.Main</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>sample</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
maven-assembly-plugin を使用しています。
以下の部分で、依存ライブラリを全て含む指定をしています。
<descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs>
そして、以下の部分で実行可能 Jar の main メソッドを含むクラスの指定をします。
<archive> <manifest> <mainClass>org.yyama.Main</mainClass> </manifest> </archive>
ビルドすると、通常の Jar ともうひとつ「-jar-with-dependencies」が付加された Jar ファイルも作成されていると思います。これが「依存ライブラリを全て含んだ実行可能 Jar」です。
実行確認してみます。
c:\tmp>java -jar sample-0.0.1-SNAPSHOT-jar-with-dependencies.jar ファイルのパスを入力してください。: C:\tmp\text.csv aaa bbb ccc ddd eee fff ggg hhh iii
動くことが確認できました。
ソースコードも置いてもらう
次にビルド時に使用したソースコードも Jar ファイルと同じ場所に出力してもらいましょう。
この設定は驚くほど簡単でした。
先ほど設定した、descriptorRefs タグの中を次のように変えます。
変更前:
<descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs>
変更後:
<descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> <descriptorRef>src</descriptorRef> <!-- ← 追加 --> </descriptorRefs>
これだけで、ビルド時に Jar ファイルと同じフォルダに 3 種類の圧縮ファイルを置いてくれます。
ファイルの例:
- sample-0.0.1-SNAPSHOT-src.tar.bz2
- sample-0.0.1-SNAPSHOT-src.tar.gz
- sample-0.0.1-SNAPSHOT-src.zip
圧縮形式は異なれど、中身は同じなので、好みの1つを配布すればいいでしょう。
まとめ
Java でツールを作ったときなど、チームメンバーに配布するときは、このように依存ライブラリを全て含んだ Jar を ソース付きで配布するといいのではないでしょうか。
おしまい
スッキリわかる Java入門 実践編 第2版 (スッキリシリーズ)
- 作者: 中山清喬
- 出版社/メーカー: インプレス
- 発売日: 2014/09/22
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (7件) を見る
- 作者: 高橋麻奈
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2013/08/29
- メディア: 単行本
- この商品を含むブログ (5件) を見る
- 作者: 高橋麻奈
- 出版社/メーカー: SBクリエイティブ
- 発売日: 2012/02/29
- メディア: 単行本
- この商品を含むブログ (2件) を見る