はじめに (対象読者・この記事でわかること)

この記事は、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ファイルを実行するところまで持っていきます。

  1. プロジェクトルートにscriptsディレクトリを作成し、中にhello.batを配置
    echo Hello from bat! exit 0

  2. 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>

  3. ビルド実行
    mvn compile

この時点で「Hello from bat!」と表示されれば成功です。

ステップ2:フェーズの指定と複数batの連鎖

実際のプロジェクトでは、以下のような要求が出ます。

  • コード生成をgenerate-sourcesフェーズで実行
  • リソースコピーをprocess-resourcesフェーズで実行
  • テスト後にレポートを変換するbatを実行

複数のbatを連鎖させる場合、実行順序を制御するためにexecutionブロックを複数定義し、それぞれ異なるidphaseを割り当てます。

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を起動する
  • workingDirectorysuccessCodesを明示することで、CI環境でも安定動作
  • バッチ側では%~dp0を使って相対パスを安定させる

この記事を通して、レガシーツールとの連携や独自ビルドステップをMavenに組み込む際の手間が減り、ビルドの信頼性が高まるはずです。

次回は、batファイルを跨いで環境変数を受け渡す方法や、PowerShellスクリプトを実行する場合の注意点について深掘りします。

参考資料