Maven が取得するライブラリの確認環境を作る

# 1. はじめに

Maven プロジェクトを新規に作成する際や、既存の Maven プロジェクトのライブラリをバージョンアップする際に、「取得されるライブラリのファイル(JAR ファイル)を事前に確認したい」ということはないでしょうか（私はあります）。
pom.xml の依存関係定義(dependency)のバージョン値や並び順を変更しただけで予想外の JAR ファイルも更新されてしまうことは珍しくないですが、その調査や対処を実際の開発プロジェクトの中で行うのはなかなか骨が折れる作業です（ビルドに時間がかかるとか、余計な確認対象が多すぎるとか、面倒なことが多いです）。

そこで私の場合は、Maven が取得するライブラリのファイルを確認するためだけのシンプルな Maven プロジェクトを使っています。そして、その環境で確認がとれた依存関係定義を開発プロジェクトに反映しています [^1]。

# 2. 環境

Windows 10 Home
Java 17.0.7
Maven 3.8.8

# 3. プロジェクト構成

![mvntest-app-tree3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2512108/1d78fb2f-022f-966f-5a64-66834826b2fd.png)

上記は、Maven を `package` 実行すると、pom.xml に依存関係定義されたライブラリのファイルをダウンロードし、
**(プロジェクトディレクトリ※)/out/lib**
に保存するプロジェクトの構成図です（※構成図では「mvntest-app」がプロジェクトディレクトリになります）。

## 3.1 Main.java

```java:Main.java
package com.mvntest.app;

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello world!");
    }
}
```
Maven でビルドを行うために Java ファイルが必要となるため、ダミーのJavaファイルを準備しました。ビルドが通れば何でもよいため、とりあえずは Hello world。

## 3.2 pom.xml

```xml: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>com.mvntest</groupId>
	<artifactId>mvntest-app</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>mvntest-app</name>

	<repositories>
		<repository>
			<id>central</id>
			<url>https://repo1.maven.org/maven2</url>
		</repository>
	</repositories>
	<pluginRepositories>
		<pluginRepository>
			<id>central</id>
			<url>https://repo1.maven.org/maven2</url>
			<releases>
				<enabled>true</enabled>
			</releases>
		</pluginRepository>
	</pluginRepositories>

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

	<dependencies>
		<!-- ここに取得対象のライブラリを定義する -->
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-dependency-plugin</artifactId>
				<executions>
					<execution>
						<id>copy-dependencies</id>
						<phase>package</phase>
						<goals>
							<goal>copy-dependencies</goal>
						</goals>
						<configuration>
							<outputDirectory>${project.basedir}/out/lib</outputDirectory>
						</configuration>
					</execution>
				</executions>
			</plugin>
		</plugins>
	</build>
</project>
```
上記は pom.xml の雛形です [^2]。
`<!-- ここに取得対象のライブラリを定義する -->`
の下に取得対象のライブラリを定義して使用します。

ポイントは「maven-dependency-plugin」の定義です。
Maven の「package」フェーズで、このプラグインの「copy-dependencies」を呼び出しています。
JAR ファイルの保存先の定義は
`<outputDirectory>${project.basedir}/out/lib</outputDirectory>`
の箇所です。
なお、`${project.basedir}` を構成図のディレクトリで表すと「mvntest-app」になります。

:::note info
**[参考] outputDirectory の設定について**
保存先の定義を省略した場合は、
${project.basedir}/target/dependency
にファイルが出力されます。
この場合、Maven のクリーンコマンド(```mvn clean```)で target フォルダが削除されるため、取得された JAR ファイルも削除の対象になります。こちらの方が利用状況に適している場合は、```<outputDirectory>``` の定義を削除してください。
:::

# 4. 試運転

試しに Google カレンダーを扱うためのライブラリをダウンロードしてみましょう。以下のように定義します。
ちなみに、依存関係の定義は様々なサイトで確認できますが、私は [Sonatype](https://central.sonatype.com) を主に利用しています。

```xml:pom.xml の抜粋
	<dependencies>
		<!-- ここに取得対象のライブラリを定義する -->
		<dependency>
			<groupId>com.google.apis</groupId>
			<artifactId>google-api-services-calendar</artifactId>
			<version>v3-rev20240111-2.0.0</version>
		</dependency>
	</dependencies>
```

続けてプロジェクトディレクトリの場所で Maven を実行します。
実行は clean → package がお約束ということで、
具体的には
`mvn clean`
`mvn package`
のように順次コマンドを実行するか、若しくは
`mvn clean package`
のようにまとめて実行します。
※Maven 対応の IDE を使っている場合は、その機能を使うと楽ちんです。

out/lib の下を見ると、以下のファイルが保存されています。

|No.|ファイル名|
|-:|:-|
|1|checker-qual-3.12.0.jar|
|2|commons-codec-1.15.jar|
|3|commons-logging-1.2.jar|
|4|error_prone_annotations-2.11.0.jar|
|5|failureaccess-1.0.1.jar|
|6|google-api-client-2.2.0.jar|
|7|google-api-services-calendar-v3-rev20240111-2.0.0.jar|
|8|google-http-client-1.42.3.jar|
|9|google-http-client-apache-v2-1.42.3.jar|
|10|google-http-client-gson-1.42.3.jar|
|11|google-oauth-client-1.34.1.jar|
|12|grpc-context-1.27.2.jar|
|13|gson-2.10.jar|
|14|guava-31.1-jre.jar|
|15|httpclient-4.5.14.jar|
|16|httpcore-4.4.16.jar|
|17|j2objc-annotations-1.3.jar|
|18|jsr305-3.0.2.jar|
|19|listenablefuture-9999.0-empty-to-avoid-conflict-with-guava.jar|
|20|opencensus-api-0.31.1.jar|
|21|opencensus-contrib-http-util-0.31.1.jar|

依存関係に設定したライブラリの定義は 1 つですが、取得された JAR ファイルは **21** 個(！)もありました。
このレベルになると、手作業で JAR ファイルを全て収集するのはかなり困難ですね。

# 5. おわりに

この確認環境は、開発プロジェクトに Maven を導入しておらず、毎回手作業でライブラリのアップデートを行っているような場合にも、ライブラリ取得ツールとして使えます。本来であれば、開発プロジェクトを Maven に対応させるべきかもしれませんが、その手段をとれない場合に使用するとよいでしょう。

# 6. 参考にさせていただいた情報

Apache Maven Dependency Plugin &#x2013; Introduction
https://maven.apache.org/plugins/maven-dependency-plugin/

Maven Central Repository - Sonatype
https://central.sonatype.com

[^1]: 「開発プロジェクトに新しい依存関係の定義を取り込んだらビルドが通らなくなった」ということもありますが、ライブラリの取得とビルドは別の話なので、それぞれ分けて対処すべきと思っています。

[^2]: `<repositories>`, `<pluginRepositories>` の定義は不要なら削除、不足があれば逐次追加してください。また、`<properties>` 配下の `<maven.compiler.source>`, `<maven.compiler.target>` の値は、実行環境の Java のバージョンを設定してください。