VS Code + Docker + Gemini CLI で Java 開発(Maven 版)

に公開

はじめに

この記事は「VS Code + Docker + Gemini CLI で Java 開発(Gradle 版)」の続きです。

ここでは、前回用意した Gradle プロジェクトを Apache Maven プロジェクトへ移行したので、これについて説明します。

前回は、開発コンテナで Gemini CLI を使えるようにし、Gemini を使ってシンプルな Java プロジェクトを Gradle プロジェクトへ移行しました。今回は、VS Code と Docker を使った Maven プロジェクトの Java プログラム開発についての解説となります。

Gemini CLI は使える環境になっているだけで、そちらの解説はあまりしていません。あらかじめ、ご了承ください。

サンプルコード

GitHub にサンプルコードを用意したので、先に紹介しておきます。

java-app003-00 のタグをつけてあります。

タグ 説明
java-app003-00 今回、解説するもの
java-app002-00 前回のもの

利用するには開発コンテナの環境を用意するのが手軽です。リポジトリ内の dvc-java-gemini/README.md の説明にしたがって環境構築をしてください。

開発コンテナ用のファイルについては、前回の記事の「Gemini CLI 向け Dev Container のセットアップ」の解説を参照してください。

Apache Maven とは

最初に、今回利用する Apache Maven について、簡単に説明をします。

Maven は、Java プロジェクトで広く利用されているビルド自動化ツールであり、プロジェクト管理ツールでもあります。その主な目的は、開発者がプロジェクトのビルド、レポート作成、ドキュメント生成を簡単かつ標準的な方法で行えるようにすることです。

Maven は次の 3 つの主要な概念に基づいて構築されています。

  • プロジェクトオブジェクトモデル (POM)
  • 依存関係管理
  • ビルドライフサイクル

Maven プロジェクトでは、**プロジェクトオブジェクトモデル (POM)**により、プロジェクトの構成が一目でわかります。具体的には、POM を表現するための pom.xml というファイルがあり、これに、プロジェクトの依存関係、プラグイン、ゴール、ビルドプロファイルなど、すべての設定情報を集約します。

また、pom.xml にプロジェクトが必要とするライブラリを記述するだけで、依存関係管理が簡単にできるようになっています。この情報を使って、Maven がセントラルリポジトリから必要な JAR ファイルを自動的にダウンロードして管理します。手動で JAR ファイルを管理する手間を省き、バージョン競合の問題を解決しやすくします。

pom.xml の記述にあたっては、ビルドライフサイクルという重要な概念についての理解が不可欠です。これは、プロジェクトをビルドし、配布するための一連の標準化されたフェーズ(工程)を定義します。フェーズはあらかじめ決められているという点がポイントです。これにより、どんな Maven プロジェクトでも同じコマンドで一貫したビルドプロセスを実行できます。

ビルドライフサイクル

Maven のライフサイクルは、ビルドの各ステップを定義した「フェーズ (Phase)」の集まりです。特定のフェーズを実行すると、そのフェーズに至るまでのすべてのフェーズが順番に実行されます。

Maven には主に 3 つの組み込みライフサイクルがあります。

  • default: プロジェクトのビルドとデプロイ
  • clean: ビルドで生成されたファイル(target ディレクトリなど)を削除
  • site: プロジェクトのドキュメントサイトを生成

開発者が pom.xml を記述するときには、「どのライフサイクルの、どのフェーズで、どういった処理を実行するのか」を意識して設計するということになります。

default ライフサイクル

開発時に一番良く使用するのは、default ライフサイクルです。

このライフサイクルの主要なフェーズは次の順番で構成されています。ここでは、代表的なものを示しています。

  1. validate: プロジェクトが正しいか、必要な情報がすべて利用可能か検証
  2. compile: プロジェクトのソースコードをコンパイル
  3. test: コンパイルされたソースコードを、適切な単体テストフレームワーク(JUnit など)でテスト
  4. package: テスト済みのコードを、pom.xml で定義された形式(JAR, WAR など)にパッケージング
  5. verify: パッケージが有効であり、品質基準を満たしているかチェック
  6. install: パッケージをローカルリポジトリにインストール
  7. deploy: 完成したパッケージのデプロイ

例えば、./mvnw install というコマンドを実行すると、Maven は default ライフサイクルの validate から install までのすべてのフェーズを順番に実行します。つまり、コードの検証、コンパイル、テスト、パッケージング、そしてローカルリポジトリへのインストールが一度に行われるのです。

このように、ライフサイクルという概念があるおかげで、開発者は複雑なビルド手順を覚えることなく、標準化されたコマンドでプロジェクトを管理できます。

リポジトリ

Maven の強力な依存関係管理機能は、「リポジトリ (Repository)」という仕組みによって支えられています。リポジトリは、プロジェクトの成果物(JAR ファイルなど)やプラグインを保管し、共有するための場所です。

Maven は主に次の役割の異なる 2 種類のリポジトリを連携させて利用します。

  • ローカルリポジトリ
  • リモートリポジトリ

依存関係を解決する際、Maven はまずローカルリポジトリを探し、そこに見つからなければリモートリポジトリに問い合わせに行きます。

ローカルリポジトリ

ローカルリポジトリは、開発者自身のコンピュータ上に作成される、ライブラリやプラグインの一時的な保管場所(キャッシュ)です。デフォルトでは、ユーザーのホームディレクトリ配下の .m2/repository に作られます。

一度リモートリポジトリからダウンロードされた依存ライブラリは、すべてこのローカルリポジトリに保存されます。次回以降、同じライブラリが必要になった場合は、インターネットにアクセスすることなく、ローカルリポジトリから即座に取得されます。これにより、ビルドの高速化とオフラインでの作業が可能になります。

また、./mvnw install コマンドを実行すると、ビルドしたプロジェクトの成果物(JAR ファイル)がこのローカルリポジトリにインストールされます。これにより、同じマシン上の他のプロジェクトから依存関係として参照できるようになりますが、チームの他のメンバーと共有するためにはリモートリポジトリへのデプロイが必要です。

リモートリポジトリ

リモートリポジトリは、ネットワーク経由でアクセスされるサーバー上のリポジトリです。チーム内での成果物の共有や、オープンソースライブラリの配布に利用されます。リモートリポジトリは、その公開範囲によっていくつかの種類に分けられます。

リポジトリ 説明
セントラルリポジトリ Maven コミュニティが公式に提供するデフォルトのリモートリポジトリ
その他のパブリックリポジトリ セントラルリポジトリ以外にも、特定の目的のために利用できる公開リポジトリ
プライベートリポジトリ 企業や組織内で独自に運用されるリポジトリ

これらのリポジトリが連携することで、Maven は効率的かつ安定した依存関係管理を実現しています。

セントラルリポジトリには、世界中のオープンソースライブラリが集約されています。pom.xml に依存関係を記述するだけで、Maven が自動的にここからライブラリをダウンロードします。

その他のパブリックリポジトリは、特定のベンダーが提供するライブラリでセントラルリポジトリには登録されていないライブラリを利用したい場合に使用します。別の公開リポジトリを指定するには、pom.xml<repositories> タグを追加します。代表的なものには、Spring、JBoss、Google のリポジトリなどがあります。

プライベートリポジトリには、企業や組織内で独自に運用される非公開のリポジトリです。主な目的は次の通りです。

  • 自社で開発したライブラリや成果物を、組織内で安全に共有すること
  • 外部のパブリックリポジトリのプロキシとして機能させ、ダウンロードしたライブラリをキャッシュすることで、ビルドの高速化と安定化を図ること
  • 利用するライブラリを組織内で承認されたものだけに限定し、セキュリティを管理すること

プライベートリポジトリは、GitLab のパッケージレジストリ機能 で提供することができます。Sonatype NexusJFrog Artifactory といった専用のソフトウェアで構築することもできます。関連する URL のリストを次に示します。

java-app003 の解説

java-app003 は、java-app002 の Gradle プロジェクトを Maven へ移行したものです。基本的なコンソールアプリケーションである点は同じですが、開発体験を向上させるための様々な機能が追加されています。

  • Maven によるビルド管理: pom.xml を中心に、依存関係の管理やビルドプロセスが定義されています。
  • 静的コード解析: Checkstyle を導入し、Google Java Style Guide に基づくコード規約を適用しています。
  • ドキュメント生成: Javadoc と Maven Site Plugin を活用し、API ドキュメントやプロジェクト情報をまとめた Web サイトを生成できます。
  • テストレポート: Maven Surefire Report Plugin により、JUnit のテスト結果を HTML で閲覧できます。
  • VS Code でのデバッグ: java-app003.code-workspace にデバッグ用の起動構成が定義されており、VS Code から直接デバッグ実行が可能です。

Maven プロジェクトのフォルダ構成

java-app003 のフォルダ構成は、標準的な Maven プロジェクトのレイアウトに従っています。これは、前回解説した Gradle プロジェクト (java-app002) と多くの点で共通していますが、ビルドツール固有の違いも存在します。

共通点:ソースコードの配置

まず、アプリケーションのソースコードやリソースファイルの配置場所は、Maven と Gradle で全く同じです。これは両ツールが「設定より規約」の思想に従い、同じディレクトリ構造を標準としているためです。

パス(配置場所) 説明
src/main/java アプリケーション本体の Java ソースコードを配置
src/main/resources logback.xml のような、ビルド時にクラスパスに含めたい設定ファイルなどを配置
src/test/java JUnit などで記述されたテストコードを配置
src/test/resources テスト実行時に利用する設定ファイルなどを配置

この規約のおかげで、ビルドツールを Maven から Gradle へ(あるいはその逆へ)移行する際に、ソースコードの移動が不要になります。

相違点:ビルド関連ファイルの比較

違いが表れるのは、プロジェクトのビルド設定や、ビルドツール自体を管理するためのファイルです。

目的 Maven (java-app003) Gradle (java-app002)
プロジェクト定義 pom.xml build.gradle / settings.gradle
ラッパー実行スクリプト mvnw, mvnw.cmd gradlew, gradlew.bat
ラッパー設定 .mvn/wrapper/ gradle/wrapper/

以下に java-app003 の構造を示します。Gradle プロジェクトの構造と見比べると、違いがより明確になるでしょう。

java-app003/
├── .mvn/
│   └── wrapper/
│       └── maven-wrapper.properties  # Maven Wrapper の設定ファイル
├── src/
│   ├── main/
│   │   ├── java/                     # アプリケーションのソースコード
│   │   │   └── internal/dev/App.java
│   │   └── resources/                # 設定ファイルなど
│   │       └── logback.xml
│   └── test/
│       └── java/                     # テストコード
│           └── internal/dev/AppTest.java
├── .gitignore                        # Git の無視ファイル設定
├── google_checks.xml                 # Checkstyle の設定ファイル
├── java-app003.code-workspace        # VS Code のワークスペース設定
├── mvnw                              # Maven Wrapper の実行スクリプト (Linux/macOS)
├── mvnw.cmd                          # Maven Wrapper の実行スクリプト (Windows)
├── pom.xml                           # Maven のプロジェクト設定ファイル
└── README.md                         # プロジェクトの説明書

プロジェクト定義ファイル:

Maven では pom.xml という XML ファイルに、プロジェクトの依存ライブラリ、ビルド設定、プラグインなど、すべての情報を集約して記述します。

一方、Gradle では build.gradle (または build.gradle.kts) という Groovy や Kotlin で書かれたスクリプトファイルにビルドロジックを記述し、settings.gradle でプロジェクトの基本的な設定を管理することが一般的です。

ラッパー (Wrapper) と JDK:

どちらのツールも、開発環境に特定のバージョンのビルドツールがインストールされていなくても、プロジェクトで定義されたバージョンを自動的にダウンロードして利用するための「ラッパー」機能を提供します。

Maven では、実行スクリプトが mvnwmvnw.cmd、設定ファイルが .mvn/wrapper/ ディレクトリに配置されます。

Gradle では、実行スクリプトが gradlewgradlew.bat、設定ファイルが gradle/wrapper/ ディレクトリに配置されます。

ここで、ビルドに必要な JDK の扱いには違いがあります。

Maven Wrapper は JDK を管理しませんmvnw を実行する前に、適切なバージョンの JDK があらかじめインストールされ、JAVA_HOME 環境変数が設定されている必要があります。

Gradle は Toolchains 機能により JDK を自動ダウンロードできますbuild.gradle に設定を記述することで、プロジェクトで指定されたバージョンの JDK を Gradle が自動的にダウンロードしてビルドに使用させることが可能です。これにより、開発者間で JDK のバージョンも統一できます。

このように、基本的なソースコードの管理方法は共通化しつつ、ビルドツールの設定や管理方法にそれぞれのツールの特徴が表れています。

プロジェクトのビルドと実行

プロジェクトのビルドは、cleaninstall を組み合わせるのが基本です。これにより、古いビルド成果物を削除し、コードのコンパイル、Checkstyle による静的解析、テストの実行、そして成果物(JAR ファイル)のローカル Maven リポジトリへのインストールが一度に行われます。

# プロジェクトのビルド
./mvnw clean install

初めて実行するときは、必要なパッケージのダウンロードも自動で実行されます。

ビルドが成功すれば、次のコマンドでアプリケーションを実行できます。

# アプリケーションの実行
./mvnw --quiet exec:java -Dexec.mainClass="internal.dev.App"

実行例は次のとおりです。

$ ./mvnw --quiet exec:java -Dexec.mainClass="internal.dev.App"
2025-09-21 23:49:36.480 [internal.dev.App.main()] INFO  internal.dev.App - This is an info message.
2025-09-21 23:49:36.487 [internal.dev.App.main()] WARN  internal.dev.App - This is a warning message.
2025-09-21 23:49:36.488 [internal.dev.App.main()] ERROR internal.dev.App - This is an error message.
Hello, World from VS Code!

なお、--quiet オプションは mvnw コマンド実行時のメッセージを抑制するためのものです。この指定をはずすと、mvnw の処理についての詳細が表示されます。

実行結果の例は次のようになります。

$ ./mvnw exec:java -Dexec.mainClass="internal.dev.App"
[INFO] Scanning for projects...
(略)
[INFO]
[INFO] --- exec:3.5.1:java (default-cli) @ java-app003 ---
2025-09-21 23:49:36.480 [internal.dev.App.main()] INFO  internal.dev.App - This is an info message.
2025-09-21 23:49:36.487 [internal.dev.App.main()] WARN  internal.dev.App - This is a warning message.
2025-09-21 23:49:36.488 [internal.dev.App.main()] ERROR internal.dev.App - This is an error message.
Hello, World from VS Code!
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.456 s
[INFO] Finished at: 2025-09-22T02:50:34Z
[INFO] ------------------------------------------------------------------------

ドキュメントとテストレポートの生成

pom.xml には、maven-javadoc-pluginmaven-surefire-report-plugin などのレポート生成用プラグインが設定されています。次のコマンドを実行すると、これらのレポートが target/site ディレクトリにまとめて生成されます。

# Javadoc, テストレポートなどを含むプロジェクトサイトを生成
./mvnw site

生成されたドキュメントをブラウザで確認するには、簡易的な Web サーバーを起動すると便利です。README.md にも記載されていますが、開発コンテナ内であれば次のように実行します。

# target/site をルートとして Web サーバーを起動
java -m jdk.httpserver -b 0.0.0.0 -p 8000 \
  -d /workspaces/dvc-java-gemini/java-app003/target/site

その後、ホストマシンのブラウザで http://localhost:8000 を開きます。プロジェクトの概要、依存関係、ライセンスといった情報に加え、Javadoc (apidocs/index.html) やテストレポート (surefire-report.html) へのリンクが設置されたトップページが表示されます。

/images/20250922_vscode_java_04/01.png
プロジェクトサイトの画面

VS Code の画面

java-app003.code-workspace ファイルを使って開いた VS Code のワークスペース画面は次のようになります。

/images/20250922_vscode_java_04/02.png
java-app003 ワークスペースの画面

VS Code のプライマリー サイド バーに表示されているエクスプローラーに JAVA PROJECTSMAVEN のビューが追加されている点に注目しましょう。

JAVA PROJECTS のビューは次のようになります。ビルドツールを指定しないプロジェクトにはない Maven Dependencies の表示が増えています。

/images/20250922_vscode_java_04/03.png
java-app003 ワークスペースの JAVA PROJECTS ビュー

MAVEN のビューは次のようになります。pom.xml の内容と大体の対応があることがわかります。

/images/20250922_vscode_java_04/04.png
java-app003 ワークスペースの MAVEN ビュー

VS Code でのデバッグ実行

java-app003.code-workspace ファイルには、VS Code の「実行とデバッグ」機能で利用できる複数の起動構成が定義されています。

/images/20250922_vscode_java_04/05.png
起動構成の一覧

最も手軽なのは Debug (Launch) - App です。これを選択してから、デバッグ実行を開始するために緑色の再生ボタン ▶ をクリックします。すると、preLaunchTask として定義された Build Maven Project タスク(./mvnw clean install を実行)が自動的に走り、ビルドが完了した後にデバッグセッションが開始されます。

ソースコードの任意の場所(例えば App.javamain メソッド内)にブレークポイントを設定し、このデバッグ構成を実行すれば、そこでプログラムが一時停止し、変数の内容を確認したり、ステップ実行したりできます。

/images/20250922_vscode_java_04/06.png
VS Code でのデバッグ実行の様子

デバッグプロファイルを利用したデバッグ実行

このプロジェクトでは、pom.xml に定義された debug プロファイルを利用して、アプリケーションをデバッグモードで起動し、そこに VS Code のデバッガを接続(アタッチ)する方法も用意されています。

java-app003.code-workspace では、このアタッチデバッグのプロセスを完全に自動化する起動構成 Attach to Maven Process with Task が定義されています。

Debug (Launch) - App の方は VS Code の機能を利用するものなので手軽に使えますが、カスタマイズする場合は Maven と組み合わせるようにした方が、開発の全体効率が上がります。Maven のプロファイルを利用するデバッグ実行の設定方法を知っておくと、VS Code でもテーミナルのコマンドでも、どちらでもデバッグ実行ができるようになります。

起動構成について実際のコードは java-app003.code-workspacelaunch にあります。ここでは処理の概要について説明することにして、コードについては後で説明します。

Attach to Maven Process with Task を実行するには、「実行とデバッグ」ビューでこれを選択し、デバッグを開始(緑色の再生ボタン ▶ をクリック)するだけです。

初めて実行したときは、problemMatcher についての警告画面が表示されますが、「このタスクの選択内容を保存」をチェックし、「このままデバッグ」をクリックして進めます。

なお、この起動構成では、以下の処理がすべて自動的に実行されます。

  1. preLaunchTask の実行
  2. デバッガのアタッチ
  3. デバッグセッションの開始
  4. postDebugTask の実行

最初に preLaunchTask に指定されたタスクが実行されます。ここでは、App.java の Java プログラムがデバッグ待機状態(ポート 5005 番)で起動します。

次に、デバッガのアタッチが実行になります。VS Code の Java デバッガが、起動したプロセスのポート 5005 番に自動的に接続します。

アタッチが成功すると、デバッグセッションが開始されます。デバッグセッション内で、ブレークポイントを追加設定したり、ステップ実行したりできるようになります。

プログラムを終了すると、デバッグセッションが終了となります。このとき、postDebugTask が自動実行されます。ここでは、バックグラウンドで実行されていた Maven プロセスが自動的に終了し、ポートが解放されます。

この構成のおかげで、開発者はターミナルで手動でコマンドを実行したり、プロセスを停止したりする手間から解放され、VS Code の UI 操作だけでアタッチデバッグの開始から終了までを完結させることができます。

ただし、ここで採用している設定方法では、「デバッガの切断」と「デバッガの停止」が同じ動作となってしまいます。どちらも、デバッグモードで起動してあるプログラムを自動停止してしまいます。

使用技術の解説

ここでは、java-app003 で利用されている主要な技術や設定について、初心者向けに解説します。

Maven と pom.xml

Maven プロジェクトの中心となるのが、プロジェクトオブジェクトモデル (POM) を定義する pom.xml ファイルです。先に解説した Maven の概念(ライフサイクル、依存関係管理など)は、すべてこのファイル内の記述に基づいて機能します。

Maven は「設定より規約 (Convention over Configuration)」という設計思想を重視しており、「Java のソースコードは src/main/java に置く」といった規約に従うことで、pom.xml の記述を最小限に抑えられます。

このセクションでは、java-app003pom.xml を例に、その具体的な構造と設定内容を解説します。

pom.xml の主な要素

java-app003pom.xml を例に、主要な要素を見ていきましょう。これは、大きく次の要素から構成されています。

  • プロジェクト情報
  • プロパティ
  • 依存ライブラリ
  • ビルド設定
  • レポート設定
  • プロファイル

それぞれについて説明します。

プロジェクト情報としては、<groupId>, <artifactId>, <version>, <packaging> といったものがあります。これらは、プロジェクトを一意に識別するための情報です。groupId は組織やグループ、artifactId は成果物(ライブラリやアプリケーション)の名前、version はそのバージョン、packaging はパッケージのフォーマットを表します。パッケージのフォーマットには、アプリケーションやライブラリなら jar、Web アプリケーションなら war を指定します。

<groupId>internal.dev</groupId>
<artifactId>java-app003</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

プロパティは <properties> に指定します。これはプロジェクト全体で利用する設定値を定義します。例えば、Java のバージョンや、他の場所で参照する値をまとめておくのに便利です。

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

依存ライブラリは <dependencies> に指定します。ここにはプロジェクトが必要とする外部のライブラリを記述します。ここに記述されたライブラリは、Maven が自動的にダウンロードしてクラスパスに追加してくれます。

<!-- 略 -->
<!-- SLF4J API -->
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>2.0.13</version>
</dependency>
<!-- Logback -->
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.5.6</version>
</dependency>
<!-- 略 -->

ビルド設定は <build> に指定します。ここには、プロジェクトのビルド方法を定義します。特に重要なのが <plugins> で、コンパイル、テスト、パッケージングといった各工程で実行される Maven プラグインを設定します。

  • maven-compiler-plugin: Java ソースコードをコンパイル
  • maven-surefire-plugin: ユニットテストを実行
  • maven-checkstyle-plugin: コードスタイルをチェック
  • exec-maven-plugin: アプリケーションを実行

レポート設定は <reporting> に指定します。ここには、./mvnw site コマンドで生成されるプロジェクトサイトに含めるレポートの種類を設定します。maven-javadoc-pluginmaven-surefire-report-plugin をここに設定することで、Javadoc やテストレポートがサイトに含まれるようになります。

プロファイルは <profiles> に指定します。プロファイルというのは、特定の状況に応じてビルド設定を切り替えるための仕組みです。これについては後述します。

VS Code と Maven の連携

VS Code は、「Extension Pack for Java」に含まれる「Maven for Java」拡張機能によって、Maven プロジェクトを強力にサポートします。

Maven ビュー

VS Code のサイドバーには「MAVEN」という専用のビューが表示されます。ここには、現在のプロジェクト(java-app003)がツリー形式で表示され、GUI で操作を行うことができます。

  • Lifecycle
  • Plugins
  • Dependencies

Lifecycle には clean, validate, compile, install といった Maven の主要なビルドライフサイクル・フェーズが一覧表示されます。

Plugins には、プロジェクトで利用しているプラグインとそのゴール(プラグインが提供する個別の機能)が一覧表示されます。ここから特定のゴールだけを実行することも可能です。

Dependencies には、プロジェクトの依存ライブラリが一覧表示されます。ライブラリのバージョン競合などを確認するのに役立ちます。

MAVEN ビューの画面は一度見ていますが、改めて、ここでも示しておきます。Lifecycle にある各項目の横にある再生ボタン ▶ を押すと、そのフェーズのビルドが実行されます。

/images/20250922_vscode_java_04/04.png
MAVEN ビュー

MAVEN ビューではプロファイルの有効化もできます。有効化したいプロファイルにマウスを合わせると、右側に + マークが表示されるので、クリックします。すると、+ マークが - マークに変わり、プロファイルの先頭にチェックマーク(✔)がつきます。

/images/20250922_vscode_java_04/07.png
MAVEN ビューでの debug プロファイル有効化

プロファイルの無効化をするには、無効化したいプロファイルにマウスを合わせると、右側に表示される- マークをクリックします。

ワークスペース設定 (java-app003.code-workspace)

java-app003.code-workspace ファイルは、このプロジェクトを VS Code で開いたときに適用される設定をまとめたものです。これにより、開発者ごとに環境設定がバラバラになるのを防ぎます。

Maven 関連の設定:

settings の中には、Maven 開発を快適にするための設定が含まれています。

"settings": {
    // ...
    "maven.terminal.useJavaHome": true,
    "java.jdt.ls.java.home": "/usr/local/sdkman/candidates/java/21.0.7-tem",
    // ...
    "maven.view": "hierarchical",
    "java.configuration.updateBuildConfiguration": "interactive",
    "java.debug.settings.jdwp.requestTimeout": 15000
}
設定項目 説明
java.jdt.ls.java.home VS Code 用の Java Language Server が使用する JDK を設定します。
maven.terminal.useJavaHome Maven 用のターミナルが使用する JDK を設定します。
maven.view Maven ビューの表示形式を hierarchical(階層表示)に設定します。
java.configuration.updateBuildConfiguration ビルド構成ファイル(pom.xml など)が変更された際のプロジェクト構成の更新方法を制御します。
java.debug.settings.jdwp.requestTimeout デバッガがターゲット JVM と通信する際の JDWP リクエストのタイムアウト時間(ms)を設定します。

java.configuration.updateBuildConfiguration については、interactive を指定すると、変更を検知した際に更新するかどうかをユーザーに問い合わせるプロンプトが表示されます。"automatic" を指定すると、ユーザーの許可なしに自動で更新されるようになります。

java.debug.settings.jdwp.requestTimeout については、短いと後で説明するタスクの Attach to Maven Process with Task を利用する時に問題が起きることがあります。

launchtasks の詳細

VS Code のデバッグ機能を最大限に活用するため、launch(起動構成)と tasks(タスク定義)を連携させています。tasks にビルドや外部コマンドの実行といった具体的な処理を定義し、launch からそれらを呼び出すことで、複雑なデバッグフローを自動化できます。

java-app003.code-workspace に定義されている主要な launchtasks の設定を、コードと共に見ていきましょう。

tasks の設定

tasks セクションには、デバッグの前後やビルドで実行したいシェルコマンドなどを定義します。ここでは次のタスクについて説明します。

  • Build Maven Project
  • Run Maven with Debug
  • Stop Maven Debug Process

Build Maven Project:

Build Maven Project は、プロジェクトをビルドするためのタスクです。Debug (Launch) - App 起動構成の preLaunchTask から呼び出されます。

{
  "label": "Build Maven Project",
  "type": "shell",
  "command": "./mvnw clean install",
  "problemMatcher": ["$msCompile"],
  "group": {
    "kind": "build",
    "isDefault": true
  }
}

各設定項目の説明を表にしました。

設定項目 説明
label タスクを識別するための名前。
type タスクの種類。
command 実行するコマンド。
problemMatcher コマンドの出力からエラーや警告を検出し、VS Code の「問題」パネルに表示するためのパターン。
group タスクをグループ化するための設定。

label に指定したラベル文字列を使って、launch 構成からタスクを参照することができます。

typeshell を指定すると、シェルコマンドを実行できます。

ここでは command に Maven Wrapper を指定して、ビルドを実行しています。

problemMatcher の指定にある $msCompile は、一般的なコンパイラの出力形式に対応する定義済みパターンです。

ここでは groupkind: "build"isDefault: true を設定し、このタスクがデフォルトのビルドタスクとなるようにしています。

Run Maven with Debug:

次に用意してある Run Maven with Debug は、アタッチデバッグ用に、アプリケーションをデバッグモードで起動するタスクです。isBackground: true になっているため、このタスクはバックグラウンドで実行され続け、他の処理をブロックしません。

{
  "label": "Run Maven with Debug",
  "type": "shell",
  "command": "./mvnw",
  "args": ["exec:exec", "-Pdebug"],
  "problemMatcher": [],
  "isBackground": true
}

まだ説明していない設定項目のみ表にしました。

設定項目 説明
args コマンドに渡す引数の配列。
isBackground バックグランド実行をするときに指定

ここでは argsexec:exec ゴールと debug プロファイルを指定しています。

isBackgroundtrue に設定すると、このタスクはバックグラウンドで実行され、終了を待ちません。デバッグサーバーのように、長時間実行されるプロセスを起動する場合に利用します。

Stop Maven Debug Process:

Stop Maven Debug Process は、アタッチデバッグ終了後に、起動していたデバッグプロセスを停止するための後処理タスクです。ポート 5005 を使用しているプロセスを探して終了させます。

{
  "label": "Stop Maven Debug Process",
  "type": "shell",
  "command": "ss -tln | grep :5005 > /dev/null && fuser -k 5005/tcp || true",
  "problemMatcher": []
}

ここの command の指定にあるコマンドは、ポート 5005 を使用しているプロセスを検索して終了させます。ポートが未使用の場合でもエラーにならないように、最後に || true を付けています。

なお、ここではタスクのコマンド実行時の出力を解析する必要がないため、problemMatcher の指定を空の配列 [] としていす。

launch の設定

launch セクションでは、デバッグのシナリオごとに異なる起動構成を定義します。ここでは、このプロジェクトでよく使う次の 2 つについて説明します。

  • Debug (Launch) - App
  • Attach to Maven Process with Task

Debug (Launch) - App:

Debug (Launch) - App は、アプリケーションを直接起動してデバッグする、最もシンプルな構成です。

{
  "type": "java",
  "name": "Debug (Launch) - App",
  "request": "launch",
  "mainClass": "internal.dev.App",
  "projectName": "java-app003",
  "preLaunchTask": "Build Maven Project"
}

各設定項目の説明は次の表にあるとおりです。

設定項目 説明
type デバッガの種類
name 起動構成の名前
request デバッグセッションの種類
mainClass 実行するメインクラスの完全修飾名
projectName 対象となる Java プロジェクトの名前
preLaunchTask デバッグセッションを開始する前に実行するタスク

Java のデバッガを使用するため、type には java と指定します。

name に指定した値は、「実行とデバッグ」ビューに表示されます。

requestlaunch を指定すると、新しいプロセスを起動してデバッグすることになります。

mainClass には、今回使用するメインクラスの internal.dev.App を指定します。

projectName には、プロジェクト名 java-app003 を指定します。

preLaunchTask には tasks で用意したタスクをラベル(label)で指定します。ここでは、tasks で定義した Build Maven Project を指定し、デバッグ開始前に必ずビルドが実行されるようにしています。

Attach to Maven Process with Task:

Attach to Maven Process with Task は、アタッチデバッグの全工程を自動化する構成です。

この設定で、デバッグプロセスの起動から、デバッガをアタッチし、デバッグプロセスを停止するまでの一連の流れをワンクリックで実行できるようになります。

{
  "type": "java",
  "name": "Attach to Maven Process with Task",
  "request": "attach",
  "hostName": "localhost",
  "port": 5005,
  "preLaunchTask": "Run Maven with Debug",
  "postDebugTask": "Stop Maven Debug Process",
  "projectName": "java-app003"
}

まだ説明していない設定項目についてのみ表にしました。

設定項目 説明
hostName アタッチするプロセスが実行されているホスト名
port アタッチするプロセスがデバッグ接続を待ち受けているポート番号
preLaunchTask デバッグセッションを開始する前に実行するタスク
postDebugTask デバッグセッションが終了した後に実行するタスク

requestattach を指定すると、すでに実行中のプロセスにデバッガを接続(アタッチ)することになります。

ここでは hostName には、localhost を指定して、同じマシン上で実行されているプロセスにアタッチするようにしています。

また、preLaunchTask には、デバッグモードで Maven プロセスを起動する Run Maven with Debug を指定します。

postDebugTask には、バックグラウンドで実行されている Maven プロセスを停止する Stop Maven Debug Process を指定しています。

このように launchtasks を連携させることで、VS Code のデバッグ実行ボタン一つで、ビルドからデバッグ、後処理までを完結させることができます。

Javadoc とは

Javadoc とは、Java のソースコード内に特定の形式で記述されたコメントから、API 仕様書を HTML 形式で生成するためのツールです。/** ... */ という形式のコメントブロック内に、@param (引数) や @return (戻り値) といったタグを使ってクラスやメソッドの仕様を記述します。詳しくは、Oracle が提供する公式ドキュメントを参照してください。

この仕組みに従ってコードにドキュメントを埋め込んでおくことで、コードそのものがドキュメントとして機能し、いつでも最新の API 仕様書を生成できるようになります。

次に Javadoc 用のコメントを書いたプログラムの例を示します。

package internal.dev;

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

/**
 * The main application class.
 */
public class App {

  /**
   * Prevents instantiation of this utility class.
   */
  private App() {
  }

  /** The logger. */
  private static final Logger logger = LoggerFactory.getLogger(App.class);

  /**
   * Returns a greeting message and logs some messages.
   *
   * @return The greeting "Hello, World from VS Code!"
   */
  public static String getGreeting() {
    logger.info("This is an info message.");
    logger.warn("This is a warning message.");
    logger.error("This is an error message.");
    return "Hello, World from VS Code!";
  }

  /**
   * The main entry point of the program.
   *
   * @param args The command line arguments (not used).
   * @throws Exception If an exception occurs.
   */
  public static void main(String[] args) throws Exception {
    System.out.println(getGreeting());
  }
}

上記のようなコメントを書いておくと、Javadoc はクラスやメソッドの説明、引数(@param)、戻り値(@return)といった情報を解析し、見やすいドキュメントを生成してくれます。

Maven では、maven-javadoc-plugin を使えば Javadoc のドキュメント生成に対応できます。java-app003 では、このプラグインを設定し、./mvnw site コマンドで Javadoc を生成できるようにしています。

Javadoc と mvnw site の連携の仕組み

./mvnw site コマンドを実行したときに Javadoc が生成されるのは、pom.xml<reporting> セクションに maven-javadoc-plugin が設定されているためです。

Maven には、compiletest, package といったビルドの各工程を定義した「ライフサイクル」という概念があります。site もそのライフサイクルの一つで、プロジェクトに関する情報やレポートをまとめた Web サイトを生成する役割を担います。

./mvnw site コマンドを実行すると、Maven は site ライフサイクルを実行します。その際、pom.xml<reporting> セクションに記述されたプラグインを呼び出し、レポートを生成させます。

java-app003pom.xml では、<reporting> セクションに maven-javadoc-pluginmaven-surefire-report-plugin が含まれているため、./mvnw site を実行するだけで、Javadoc やテストレポートが自動的に生成され、プロジェクトサイトに統合されるのです。

Maven Surefire Report Plugin とは

Maven Surefire Report Plugin は、ユニットテストの結果をまとめたレポートを HTML 形式で生成するためのプラグインです。

Maven でテストを実行する際、実際には maven-surefire-plugin という別のプラグインが使われます。このプラグインが JUnit などのテストフレームワークを呼び出してテストを実行し、結果を XML ファイルに出力します。

Surefire Report Plugin は、その XML ファイルを読み込んで、人間が見やすい形の HTML レポートを生成する役割を担います。./mvnw site を実行すると、このプラグインが動作し、target/site/surefire-report.html というファイルが作成されます。このレポートを見れば、どのテストが成功し、どれが失敗したのかが一目でわかります。

Maven プロファイル とは

Maven プロファイルは、特定の状況に応じてビルド設定を切り替えるための仕組みです。例えば、「開発中はこの設定、本番環境向けにビルドするときは別の設定」といった使い分けができます。

プロファイルは pom.xml 内の <profiles> タグで定義し、それぞれに ID を付けます。そして、コマンドラインで -P オプションを使って有効にするプロファイルを指定します。

java-app003pom.xml には debug という ID のプロファイルが定義されています。

<profiles>
    <profile>
        <id>debug</id>
        <properties>
            <exec.jvmargs>-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005</exec.jvmargs>
        </properties>
        <build>
            <plugins>
                <plugin>
                    <groupId>org.codehaus.mojo</groupId>
                    <artifactId>exec-maven-plugin</artifactId>
                    <version>3.1.0</version>
                    <configuration>
                        <executable>java</executable>
                        <arguments>
                            <argument>-classpath</argument>
                            <classpath />
                            <argument>${exec.jvmargs}</argument>
                            <argument>internal.dev.App</argument>
                        </arguments>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </profile>
</profiles>

このプロファイルは、有効になったときに特定のビルド設定を適用します。

  • <properties>: exec.jvmargs というプロパティを定義し、JVM をデバッグモードで起動するための引数を設定します。
  • <build>: exec-maven-plugin を設定し、アプリケーションを起動できるようにします。

ここで設定したゴールを利用するには、mvnw 実行時に debug プロファイルを有効にする必要があります。

./mvnw exec:exec -Pdebug のように -Pdebug を付けて実行すると debug プロファイルが有効になります。これにより、<build> 内の exec-maven-plugin が利用可能になり、かつ <properties> で定義されたデバッグ用の JVM 引数 (-agentlib:jdwp=...) が ${exec.jvmargs} に渡されます。結果として、アプリケーションがデバッグモードで起動する、という仕組みです。

まとめ

本記事では、開発コンテナ環境で Apache Maven プロジェクトを開発する方法について、具体的なサンプル java-app003 を通して解説しました。

Maven の中心的な概念である POM (pom.xml)、ビルドライフサイクル、依存関係管理の仕組みを理解することで、プロジェクトのビルド、テスト、ドキュメント生成といった一連のプロセスを自動化し、効率化できることを示しました。

また、VS Code の拡張機能やワークスペース設定を活用することで、Maven プロジェクトのデバッグ実行が容易になることも確認しました。特に、launchtasks を連携させたデバッグ構成や、デバッグ用のプロファイルを使ったアタッチデバッグは、実践的な開発で役立つでしょう。

この記事で紹介した pom.xml の設定や各種プラグイン(Checkstyle, Javadoc, Surefire Report など)は、多くの Java プロジェクトで応用できるものです。本記事が、皆さんの Maven を使った Java 開発の一助となれば幸いです。

Discussion