Maven で .env みたいなことをしたい

Maven を使っているプロジェクトで、環境変数を dotenv (.env) ファイルから読み込めないか考えてみました。

背景

開発環境において、ポート番号の衝突は避けられない問題です。プロジェクト A で 8080 は被りそうだから 8081 使ったけど、同じことを考えたプロジェクト B も 8081 を使っていたというような現象がどうしても発生します1どちらかというとデフォルト設定のままにしたことによって被るケースの方が多い気がする

そういった問題があるので、各個人の開発環境によってポート番号は自由に設定できるようにしたいですが、うっかり Git などに個人設定を上げてしまわないよう、開発環境ごとの設定はバージョン管理外のファイルに記載しておきたいです。

Java + Maven 環境の場合

そういったケースの場合、よく使われるのは .env ファイルを使って環境変数を指定する方法です。

  • .env に設定を書く(バージョン管理しない)
  • .env を環境変数として読み込み
PORT=8081

Maven でも似たようなことできないか調べましたが、あまり情報が出てきませんでした。

注: Java の場合、通常は application-[profile].properties を使いますが、一部設定のために application-dev.properties 全体をバージョン管理外にするのか?という疑問から調査しています。あとまれに application.properties を環境ごとに作れないケースもあります。

しばらく頭を抱えていたのですが、そういえば .env ファイルって .properties ファイルと書式ほぼ一緒じゃんということに気づき、

  • .env に設定を書く(バージョン管理しない)
  • .env を環境変数 properties ファイルとして読み込み、システムプロパティに設定する

これならできるんじゃないかという若干無理のある案を思いつきました。

properties-maven-plugin

properties ファイルを読み込むという検索条件で再び Maven プラグインを探してみると、 properties-maven-plugin というものが見つかりました。このプラグインの以下の機能を使います。

  • properties ファイルを Maven のプロジェクトプロパティ(pom.xml 内で使えるプロパティ)として読み込む
  • システムプロパティを pom.xml で定義する
<?xml version="1.0"?>

  <!-- ... -->

  <build>
    <plugins>

    <!-- ... -->

      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>properties-maven-plugin</artifactId>
        <version>1.0.0</version>
        <executions>
          <execution>
            <id>load-project-properties</id>
            <phase>initialize</phase>
            <goals>
              <goal>read-project-properties</goal>
            </goals>
            <configuration>
              <!-- ファイルがなくても無視する -->
              <quiet>true</quiet>
              <files>
                <!-- .env の場所 -->
                <file>.env</file>
              </files>
            </configuration>
          </execution>
          <execution>
            <id>set-properties</id>
            <goals>
              <goal>set-system-properties</goal>
            </goals>
            <configuration>
              <properties>
                <property>
                  <!-- プロジェクトプロパティとして読み込まれるので、システムプロパティとして再設定する -->
                  <name>PORT</name>
                  <value>${PORT}</value>
                </property>
              </properties>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

  <!-- ... -->

このように設定することで、 Maven の initialize フェーズで .env の読み込みとシステムプロパティの設定を行ってくれます。

ただ、いくつか制約があり

  • 読み込み順の関係で dependencies などの中では使えない
  • mvn quarkus:dev のようにゴールを指定した場合は initialize が実行されないので、 mvn initialize quarkus:dev のように initialize を付けてコマンドを打つ必要がある
  • .env は環境変数なので SCREAMING_CASE で書くが、 properties は dot.separated.property のような書式で書くので違和感がある

場所によっては使えそうといった感じです。

参考

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください