Maven Dependency Plugin で system スコープの jar ファイルもひとつにまとめる

## 概要

- 依存する JAR ファイルをローカルに置いて pom.xml で \<scope\>system\</scope\> を指定している状況を想定
- mvn package コマンドで作成する JAR ファイルに、依存 JAR ファイル内のすべてのクラスファイルが入るように設定する
- 今回の環境: Apache Maven 3.6.2

## 方法

Maven Dependency Plugin で以下にように設定する。

- phase: prepare-package
- goal: unpack-dependencies
- outputDirectory: コンパイルしたクラスファイルが置かれるディレクトリを指定
- includeArtifactIds: JAR ファイルに含めたいライブラリの artifactId をカンマ区切りで指定

```xml
<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-dependency-plugin</artifactId>
  <executions>
    <execution>
      <phase>prepare-package</phase>
      <goals>
        <goal>unpack-dependencies</goal>
      </goals>
      <configuration>
        <outputDirectory>${project.build.directory}/classes</outputDirectory>
        <includeArtifactIds>ajd4jp,jdom</includeArtifactIds>
      </configuration>
    </execution>
  </executions>
</plugin>
```

この設定で mvn package を実行すると、JAR ファイルを作成する前に、ライブラリなどの依存 JAR ファイルからクラスファイル等が展開され、outputDirectory で指定したディレクトリにコピーされる。
JAR ファイルを作成する際には、依存 JAR ファイルの中にあったクラスファイルもひとつの JAR ファイルにまとめられる。

## 実例

pom.xml ファイルを用意。

```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/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>sample</artifactId>
  <packaging>jar</packaging>
  <version>1.0.0</version>
  <name>sample</name>

  <build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
      <!-- Apache Maven Dependency Plugin -->
      <!-- https://maven.apache.org/plugins/maven-dependency-plugin/ -->
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-dependency-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <phase>prepare-package</phase>
            <goals>
              <goal>unpack-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}/classes</outputDirectory>
              <includeArtifactIds>ajd4jp,jdom</includeArtifactIds>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

  <dependencies>

    <dependency>
      <groupId>ajd4jp</groupId>
      <artifactId>ajd4jp</artifactId>
      <version>1.4.6.2019</version>
      <scope>system</scope>
      <systemPath>${project.basedir}/lib/ajd4jp-1.4.6.2019.jar</systemPath>
    </dependency>

    <dependency>
      <groupId>jdom</groupId>
      <artifactId>jdom</artifactId>
      <version>1.1.3</version>
      <scope>system</scope>
      <systemPath>${project.basedir}/lib/jdom-1.1.3.jar</systemPath>
    </dependency>

  </dependencies>

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

</project>
```

mvn package コマンドで JAR ファイルを作成する。

```
$ mvn package
```

作成した target/sample.jar を展開すると、指定したライブラリの jar ファイルに含まれていたクラスファイルが入っていることがわかる。

```
$ unzip target/sample.jar
Archive:  target/sample.jar
   creating: META-INF/
  inflating: META-INF/MANIFEST.MF    
   creating: orrery/
   creating: iso/
   creating: org/
   creating: org/jdom/
   creating: org/jdom/xpath/
   creating: org/jdom/input/
   creating: org/jdom/output/
   creating: org/jdom/adapters/
   creating: org/jdom/filter/
   creating: org/jdom/transform/
   creating: ajd4jp/
   creating: ajd4jp/orrery/
   creating: ajd4jp/orrery/tool/
   creating: ajd4jp/iso/
   creating: ajd4jp/util/
   creating: ajd4jp/format/
   creating: format/
   creating: com/
   creating: com/example/
  inflating: orrery/package-info.class  
  inflating: Copyright.txt           
  inflating: iso/package-info.class  
  inflating: org/jdom/IllegalAddException.class  
  inflating: org/jdom/DefaultJDOMFactory.class  
  inflating: org/jdom/EntityRef.class  
(後略)
```

## Maven Assembly Plugin と組み合わせる

Maven Assembly Plugin も導入することで system スコープを指定した JAR ファイルだけでなく、リポジトリにある依存 JAR ファイルも一緒にまとめることができる。

pom.xml ファイルを用意。

```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/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>sample</artifactId>
  <packaging>jar</packaging>
  <version>1.0.0</version>
  <name>sample</name>

  <build>
    <finalName>${project.artifactId}</finalName>
    <plugins>
      <!-- Apache Maven Dependency Plugin -->
      <!-- https://maven.apache.org/plugins/maven-dependency-plugin/ -->
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-dependency-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <executions>
          <execution>
            <phase>prepare-package</phase>
            <goals>
              <goal>unpack-dependencies</goal>
            </goals>
            <configuration>
              <outputDirectory>${project.build.directory}/classes</outputDirectory>
              <includeArtifactIds>ajd4jp,jdom</includeArtifactIds>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <!-- Apache Maven Assembly Plugin -->
      <!-- http://maven.apache.org/plugins/maven-assembly-plugin/ -->
      <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-assembly-plugin -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>3.1.1</version>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>single</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <descriptorRefs>
            <descriptorRef>jar-with-dependencies</descriptorRef>
          </descriptorRefs>
          <archive>
            <manifest>
              <mainClass>com.example.App</mainClass>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
  </build>

  <dependencies>

    <dependency>
      <groupId>ajd4jp</groupId>
      <artifactId>ajd4jp</artifactId>
      <version>1.4.6.2019</version>
      <scope>system</scope>
      <systemPath>${project.basedir}/lib/ajd4jp-1.4.6.2019.jar</systemPath>
    </dependency>

    <dependency>
      <groupId>jdom</groupId>
      <artifactId>jdom</artifactId>
      <version>1.1.3</version>
      <scope>system</scope>
      <systemPath>${project.basedir}/lib/jdom-1.1.3.jar</systemPath>
    </dependency>

    <dependency>
      <groupId>org.twitter4j</groupId>
      <artifactId>twitter4j-core</artifactId>
      <version>4.0.7</version>
      <scope>compile</scope>
    </dependency>

  </dependencies>

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

</project>
```

mvn package コマンドで JAR ファイルを作成する。

```
$ mvn package
```

作成した target/sample-jar-with-dependencies.jar を展開すると、system スコープと compile スコープで指定したライブラリの jar ファイルに含まれるクラスファイルが入っていることがわかる。

```
$ unzip target/sample-jar-with-dependencies.jar 
Archive:  target/sample-jar-with-dependencies.jar
  inflating: META-INF/MANIFEST.MF    
   creating: twitter4j/
   creating: twitter4j/util/
   creating: twitter4j/util/function/
   creating: twitter4j/auth/
   creating: twitter4j/management/
   creating: twitter4j/json/
   creating: twitter4j/api/
   creating: twitter4j/conf/
   creating: META-INF/maven/
   creating: META-INF/maven/org.twitter4j/
   creating: META-INF/maven/org.twitter4j/twitter4j-core/
   creating: orrery/
   creating: iso/
   creating: org/
   creating: org/jdom/
   creating: org/jdom/xpath/
   creating: org/jdom/input/
   creating: org/jdom/output/
   creating: org/jdom/adapters/
   creating: org/jdom/filter/
   creating: org/jdom/transform/
   creating: ajd4jp/
   creating: ajd4jp/orrery/
   creating: ajd4jp/orrery/tool/
   creating: ajd4jp/iso/
   creating: ajd4jp/util/
   creating: ajd4jp/format/
   creating: format/
   creating: com/
   creating: com/example/
   creating: META-INF/maven/com.example/
   creating: META-INF/maven/com.example/sample/
  inflating: META-INF/LICENSE.txt    
  inflating: twitter4j/JULLoggerFactory.class  
  inflating: twitter4j/SymbolEntity.class  
  inflating: twitter4j/MediaEntity.class  
  inflating: twitter4j/TwitterBase.class  
  inflating: twitter4j/Dispatcher.class  
  inflating: twitter4j/HttpClientBase.class  
(後略)
```

## 参考資料
- [Apache Maven Dependency Plugin – dependency:unpack\-dependencies](https://maven.apache.org/plugins/maven-dependency-plugin/unpack-dependencies-mojo.html)
- [Mavenでwarファイルを作成する直前に別のライブラリを含めたい \- Qiita](https://qiita.com/fukasawah/items/2230149387df8ea9866e)