はじめに (対象読者・この記事でわかること)
この記事は、JavaプロジェクトでMavenを使ってビルドしているが、ビルドのタイミングでバッチファイル(bat)を自動実行したいと考えている開発者向けです。
特に、Windows環境で動作するCI/CDパイプラインを組んでいる方や、ビルド前後にレガシーツールを呼び出さなければならない方に最適です。
この記事を読むことで、以下のことがわかります。
- Mavenのライフサイクルにbatファイルを組み込む方法
- exec-maven-pluginの正しい設定とよくある落とし穴
- 相対パス・絶対パス、ワーキングディレクトリの扱い方
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。
- Mavenのpom.xmlの基本的な記述ルール
- Windowsバッチファイルの書き方と実行方法
- Javaプロジェクトのディレクトリ構成(src/main/java など)
Mavenでbatファイルを実行する意味と課題
Javaプロジェクトでは、ビルドの前後にレガシーシステムや外部ツールを呼び出す必要がよくあります。たとえば、古いVisual Basic製のレポートツールを起動したり、専用のビルドナンバーを記載したテキストを生成したり、といったケースです。
Mavenはポータブルなビルドツールですが、Windows固有のbatファイルを実行する場合、単純に<executable>batch.bat</executable>と書くだけではパス解決やワーキングディレクトリの違いでつまづきます。
また、CI環境(GitHub Actions、Jenkins、GitLab CIなど)でWindowsランナーを使っている場合、バッチの終了コードを正しくMavenに返さないと、ビルドが成功したように見えて実は失敗している、という事態になりかねません。
本記事では、これらの課題を回避しながら、Mavenのライフサイクルにシームレスにbatファイルを組み込む方法を解説します。
exec-maven-pluginでbatを実行する実践ガイド
ステップ1:最小構成で動かす
まずはシンプルなMavenプロジェクトを用意し、batファイルを実行するところまで持っていきます。
-
プロジェクトルートに
scriptsディレクトリを作成し、中にhello.batを配置
echo Hello from bat! exit 0 -
pom.xmlに
exec-maven-pluginを追加
xml <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>run-bat</id> <phase>compile</phase> <goals> <goal>exec</goal> </goals> <configuration> <!-- Windowsの場合、cmd.exe経由で実行する --> <executable>cmd</executable> <arguments> <argument>/c</argument> <argument>${project.basedir}/scripts/hello.bat</argument> </arguments> <!-- ワーキングディレクトリを明示 --> <workingDirectory>${project.basedir}</workingDirectory> </configuration> </execution> </executions> </plugin> -
ビルド実行
mvn compile
この時点で「Hello from bat!」と表示されれば成功です。
ステップ2:フェーズの指定と複数batの連鎖
実際のプロジェクトでは、以下のような要求が出ます。
- コード生成を
generate-sourcesフェーズで実行 - リソースコピーを
process-resourcesフェーズで実行 - テスト後にレポートを変換するbatを実行
複数のbatを連鎖させる場合、実行順序を制御するためにexecutionブロックを複数定義し、それぞれ異なるidとphaseを割り当てます。
Xml<execution> <id>generate-stubs</id> <phase>generate-sources</phase> ... </execution> <execution> <id>pack-extra</id> <phase>package</phase> ... </execution>
ハマった点やエラー解決
1. バッチの終了コードが0以外でもMavenが成功としてしまう
デフォルトでは、batがexit 1を返してもMavenは気にしません。
これを防ぐには、<successCode>を明示的に指定します。
Xml<configuration> ... <successCodes> <successCode>0</successCode> </successCodes> </configuration>
2. 相対パスが意図しない場所を指す
CI環境でmvn -f path/to/pom.xmlのように実行すると、カレントディレクトリがプロジェクトルートとは限りません。
そのため、バッチ内で../tool.exeと書いた場合、意図しない場所を指して「ファイルが見つからない」エラーになります。
解決策は次の2つです。
-
バッチ内で
%~dp0を使って「バッチ自身のディレクトリ」を基準にする
"%~dp0..\tool.exe" -
Maven側で
workingDirectoryをプロジェクトルートに固定する(前述の通り)
3. 文字化けや改行コード
batファイルをUTF-8で保存すると、日本語が文字化けする古いWindowsツールがあります。
その場合、バッチをShift-JISで保存し、Maven側で-Dfile.encoding=Shift_JISを付与すると回避できます。
Xml<environmentVariables> <file.encoding>Shift_JIS</file.encoding> </environmentVariables>
解決策
上記の対策をすべて盛り込んだ、実戦的なpom.xmlスニペットを以下に示します。
Xml<plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>3.1.0</version> <executions> <execution> <id>run-bat-with-check</id> <phase>compile</phase> <goals><goal>exec</goal></goals> <configuration> <executable>cmd</executable> <arguments> <argument>/c</argument> <argument>${project.basedir}/scripts/build-number.bat</argument> </arguments> <workingDirectory>${project.basedir}</workingDirectory> <successCodes><successCode>0</successCode></successCodes> <environmentVariables> <BUILD_NUMBER>${buildNumber}</BUILD_NUMBER> </environmentVariables> </configuration> </execution> </executions> </plugin>
これで、batが失敗したらビルドも失敗し、CIに正しく通知されます。
まとめ
本記事では、Mavenビルド時にWindowsバッチファイルを実行する方法を解説しました。
- exec-maven-pluginを使って
cmd /c経由でbatを起動する workingDirectoryとsuccessCodesを明示することで、CI環境でも安定動作- バッチ側では
%~dp0を使って相対パスを安定させる
この記事を通して、レガシーツールとの連携や独自ビルドステップをMavenに組み込む際の手間が減り、ビルドの信頼性が高まるはずです。
次回は、batファイルを跨いで環境変数を受け渡す方法や、PowerShellスクリプトを実行する場合の注意点について深掘りします。
参考資料
- exec-maven-plugin公式ドキュメント
- Maven 公式ガイド - プラグイン開発
- 高橋健太『Maven実践バイブル』技術評論社、2022年
