Java
Maven

Mavenで依存関係などを含まないjarファイルを作る方法

はじめに

Mavenシリーズの第3弾です。
以前に、Mavenで実行可能jarをビルドする方法を書きました。
この方法を使えば、java -jar <実行対象のjarファイル名>のコマンドでjarファイルにアーカイブしたjavaプログラムを実行することができます。

しかしながら、この方法でビルドした実行可能jarファイルは、プログラムで使用する依存関係などをすべてjarファイルに同梱してしまうため、設定ファイルなどの内容を書き換えようとすると、ソースファイルを修正したうえでビルドしなおす必要があります。

それでは、例えばプログラム中に書きたくない設定値などを外に出したプロパティファイルなど、わざわざ外に出した意味が半分くらい失われてしまいます。

できれば設定ファイルなどはjarファイルに同梱せず、設定ファイルを
直接修正 > プログラムの再起動
で済ませたいものです。

そこで今回は、依存するjarや設定ファイルを同梱しないjarファイルをMavenでビルドする方法を紹介します。

今回紹介するビルド方法では、jarファイルのエントリポイントを指定しないため、前述のコマンドでjavaプログラムを実行することはできません。

筆者はその方法を知りませんが、もしこの記事をご覧いただいた方で、その方法をご存じの方がいらっしゃいましたら、ご教示いただければ幸いです。

すごく長くなってしまいましたが、今回この記事を書くに至ったいきさつと、これから記載する内容のあらすじでした。

ここからは、具体的な方法について記載していきます。

1. Mavenプロジェクトの構築

まずは、テストに使用するプロジェクトを構築します。

1.1. プロジェクトの作成

Mavenプロジェクトは、いつも通り作成します。
Mavenプロジェクトの作成方法がわからない方は、こちらをご覧ください。

1.2. テスト用の追加設定

今回のプロジェクトでは、コピーする依存関係やリソースが必要なので、それらを追加します。

1.2.1. 依存関係の追加

依存関係のコピーを確認するために、依存するjarファイルを追加します。
Mavenプロジェクトで依存するjarファイルは、pom.xmlに記載します。
そうすることで、Mavenがセントラルリポジトリというところから、自動で依存するjarファイルをダウンロードしてくれます。

■pom.xmlの記載内容

<dependencies>
    <dependency>
        <!-- 今回はロガーを依存関係として追加します -->
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.3</version>
    </dependency>
</dependencies>

1.3. リソースの追加

リソースのコピーを確認するためのリソースファイルを追加します。
今回は、ここまでに追加したロガー(logback)の設定ファイル(logback.xml)をリソースファイルとして追加します。
設定ファイルは、「src/main/resources」フォルダに追加します。

■リソース追加後のプロジェクトツリー
picuture1.JPG

1.4. ロガーを使用する設定に改造

hello-worldプロジェクトでは、標準出力を使用してHello Worldを出力していましたが、その部分をロガーを使用する設定に改造してしまいましょう。

package hello.main;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * MavenでHello World
 */
public class HelloWorld {
    /** ロガー */
    private static Logger logger = LoggerFactory.getLogger(HelloWorld.class);

    /**
     * main処理
     * 標準出力にHello Worldを表示する。
     * @param args コマンド引数
     */
    public static void main(String[] args) {
        // 標準出力による出力をロガーに変更
        logger.info("Hello Maven World!");
    }
}

1.5. logback.xmlの設定

ロガーの動きを制御する設定ファイルが「logback.xml」です。
logback自体は、それがなくてもデフォルト設定で動きますが、今回はコピーのテストもあるので、きっちり設定ファイルを書きましょう。
筆者がいつも忘れるlogback.xmlの書き方の備忘も兼ねて、コンソールに出力する設定と、ファイルに出力する設定を記載しています。

■logback.xmlの記載内容

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>logs/log%d{yyyy-MM-dd}.log</fileNamePattern>
            <maxHistory>3</maxHistory>
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd'T'HH:mm:ss'Z'} - %m%n</pattern>
        </encoder>
    </appender>

    <root level="DEBUG">
        <appender-ref ref="STDOUT" />
        <appender-ref ref="FILE" />
    </root>
</configuration>

2. 依存性のあるjarのコピー

まず、プログラム中で使用しているライブラリなどを含んだ、依存性のあるjarファイルのコピーを設定します。

2.1. maven-dependency-plugin

依存性のあるファイルをjarファイルとは別のディレクトリにコピーするには、maven-dependency-pluginというプラグインを使用します。
このプラグインを使用すれば、ビルド時に、依存するjarファイルを指定したディレクトリにコピーすることができます。

2.2. pom.xmlの編集

このような設定は、例のごとくpom.xmlに、jarファイルをビルドするための設定を書き足していきます。
ここでのポイントは、Mavenにはつきものの、テストで使用する資材を除いてコピーする設定をしておくことです。
正確には、dependencyプラグインの設定をするだけではだめで、依存するファイルのスコープをテストに限定しておいてください。

■pom.xmlの記載内容

<!-- スコープをテストに限定する -->
<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.11</version>
        <!-- ここでスコープを指定する -->
        <scope>test</scope>
    </dependency>
</dependencies>

<!-- 依存するjarのをコピーするためのプラグイン -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-dependency-plugin</artifactId>
    <!-- 記事執筆時点での最新はこちら -->
    <version>3.0.1</version>
    <executions>
        <execution>
            <id>copy-dependencies</id>
            <phase>package</phase>
            <goals>
                <goal>copy-dependencies</goal>
            </goals>
        </execution>
    </executions>
    <!-- compileスコープで使用する資材のみコピーする -->
    <configuration>
        <includeScope>compile</includeScope>
    </configuration>
</plugin>

3. リソースのコピー

一口にリソースと言っても、いろんな意味がありますが、ここでのリソースとは、javaプログラム内で使用する設定など記載したファイルのことを指します。

具体的には、Mavenプロジェクトの「src/main/resources/」ディレクトリに配置しているファイルのことです。
筆者のよく使用する環境だと、プロジェクトの構築でもそうしていますが、ロギングライブラリの設定ファイルなどをよく置いています。

余談ですが、筆者は「logback + slf4j」の環境を好んで使用します。

3.1. maven-resources-plugin

設定ファイルなどのリソースをコピーするには、maven-resources-pluginというプラグインを使用します。

3.2. pom.xmlの編集

それでは、こちらもpom.xmlにプラグインの設定を書き足していきます。
ここでのポイントは、ビルド時にjarファイルに、リソースを含まない設定を一緒に書き足しておくことです。
この設定をしておかないと、結局jarファイルにリソースを含んだ状態でビルドしてしまいます。

■pom.xmlの記載内容

<build>
    <!-- ここでビルド時にリソースを対象外にする設定を記載する。
    <resources>
        <resource>
            <directory>src/main/resources</directory>
            <!-- jarファイルに含まないリソースはexcludesタグで指定する -->
            <excludes>
                <exclude>*</exclude>
            </excludes>
        </resource>
    </resources>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-resources-plugin</artifactId>
            <version>3.0.2</version>
            <executions>
                <execution>
                    <id>copy-resources</id>
                    <phase>package</phase>
                    <goals>
                        <goal>copy-resources</goal>
                    </goals>
                    <configuration>
                        <outputDirectory>${basedir}/target/resources</outputDirectory>
                        <!-- おまけですが、リソースをコピーする先のディレクトリも指定します -->
                        <resources>
                            <resource>
                                <directory>src/main/resources</directory>
                                <filtering>true</filtering>
                            </resource>
                        </resources>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

最後に

ここまででjar依存性のあるファイルを除いたファイルをビルドする方法を紹介してきました。
筆者がここまでたどり着くまで、結構な時間ネットサーフィンしましたが、そのまま使える日本語のwebがなく、なかなか苦労しました。
そもそもMavenというものを深く理解しできていない、というところもその一因なのでしょうが、もし、同じような状況の方がいらっしゃり、そのような方のお役にたてれば幸いです。

また、もっとスマートにやる方法をご存知の方がいらっしゃれば、その旨ご指摘、ご教示いただけると幸いです。

ここ最近でMavenについて筆者が勉強したことは、今回の記事で大体出し切ったので、Mavenシリーズは、しばらくの間はこれで最後になると思います。
今まで3つの記事を書いてきましたが、Mavenはたかがビルドツールといえど、されどビルドツール。
いろいろな使い方があり、奥が深いものですので、またどこかで違う勉強をしたときには、紹介するかもしれません。

EX. 筆者が投稿したMavenシリーズ

参考までに、これまで筆者が書き記してきた記事をリンクとしてまとめておきます。
この記事をご覧いただいた皆様、よろしければ下記もご参考としてご利用ください。

■【超初心者向け】Maven超入門
http://qiita.com/ryota0001/items/e019ec4daaaf54684c53

■Mavenで実行可能jarをビルドする方法
http://qiita.com/ryota0001/items/e019ec4daaaf54684c53