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

この記事は、Heroku上でJavaアプリケーションを開発・デプロイしているプログラマー、特にWARファイルをHeroku CLIでデプロイする際に、特定のJavaバージョンを使用したいと考えている方を対象としています。

この記事を読むことで、Heroku CLIを用いてWARファイルをデプロイする際に、デフォルトのJavaバージョンではなく、任意のJavaバージョン(例えばJava 11やJava 17など)を指定してアプリケーションを動作させる具体的な方法がわかります。これにより、既存のアプリケーションの互換性維持や、最新のJavaバージョンでの検証作業がスムーズに行えるようになります。

Herokuは非常に便利なPaaSですが、Javaアプリケーションの実行環境について、バージョン指定の際に少しだけコツが必要です。本記事では、その「コツ」を具体的な手順とともにご紹介します。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。 * Java/JVMの基本的な知識 * MavenまたはGradleを使ったJavaプロジェクトのビルド(WARファイルの生成) * Heroku CLIの基本的なコマンド操作(heroku loginheroku createなど)

HerokuにおけるJavaデプロイの基本とバージョン指定の必要性

Herokuでは、アプリケーションをデプロイする際に「Buildpack」と呼ばれる仕組みを利用して、プロジェクトの言語やフレームワークを自動的に検出し、適切な実行環境を構築します。Javaアプリケーションの場合、HerokuのJava Buildpackが適用され、MavenやGradleでビルドされたWARファイルやJARファイルを検出し、JVM上で実行可能な状態にセットアップしてくれます。

HerokuのJava Buildpackは通常、最新のLTS(Long Term Support)版Java(現時点ではJava 17が主流、以前はJava 11)をデフォルトで提供します。しかし、開発しているアプリケーションが特定のJavaバージョンに依存している場合や、新しいJavaバージョンへの移行テストを行いたい場合など、Herokuのデフォルトとは異なるJavaバージョンでアプリケーションを実行したい状況が発生します。このような場合、明示的にJavaバージョンを指定する必要があります。指定しない場合、アプリケーションが期待通りに動作しない、あるいはビルドすらできないといった問題に直面する可能性があります。

例えば、Java 8で開発された古いアプリケーションをそのままデプロイしたい場合や、最新のJava 21の新機能を試したいがまだデフォルトではない場合などが挙げられます。このように、開発者が任意のJavaバージョンを選択できることは、HerokuのようなPaaSを活用する上で非常に重要な要素となります。

Heroku CLIでWARデプロイ時にJavaバージョンを指定する具体的な方法

HerokuでJavaアプリケーションをWARファイルとしてデプロイし、その際に特定のJavaバージョンを指定する方法は、プロジェクトのルートディレクトリにsystem.propertiesという設定ファイルを配置することが鍵となります。HerokuのJava Buildpackはこのファイルを読み込み、指定されたJavaバージョンでJVMをセットアップします。

ステップ1: system.propertiesファイルの作成

まず、Javaプロジェクトのルートディレクトリ(pom.xmlbuild.gradleがある場所)にsystem.propertiesという名前のファイルを作成します。このファイルに、使用したいJavaのランタイムバージョンを記述します。

例えば、Java 11を使用したい場合は、以下のように記述します。

Properties
java.runtime.version=11

Java 17を使用したい場合は、以下のように記述します。

Properties
java.runtime.version=17

ポイント: * java.runtime.versionは、HerokuがサポートしているJavaのLTSバージョン(例: 8, 11, 17, 21など)を指定するのが一般的です。Heroku Dev Centerで最新のサポート状況を確認することをおすすめします。 * 正確なバージョン(例: 11.0.12)を指定することも可能ですが、一般的にはメジャーバージョンのみの指定で十分です。Herokuが自動的にそのバージョンの最新パッチを適用してくれます。 * このファイルは、Git管理下に含めるようにしましょう。

ステップ2: WARファイルのビルド

次に、通常通りプロジェクトをビルドし、WARファイルを生成します。これはMavenやGradleといったビルドツールを用いて行います。

Mavenを使用する場合:

Bash
mvn clean package

このコマンドは、プロジェクトのターゲットディレクトリ(通常はtarget/)にWARファイルを生成します(例: target/your-app-name.war)。

Gradleを使用する場合:

Bash
./gradlew clean war

このコマンドは、プロジェクトのビルドディレクトリ(通常はbuild/libs/)にWARファイルを生成します(例: build/libs/your-app-name.war)。

ステップ3: Herokuへのデプロイ

WARファイルが準備できたら、Heroku CLIを使ってデプロイします。heroku deploy:warコマンドに、--appオプションでHerokuアプリ名を指定し、生成されたWARファイルのパスを渡します。

Bash
heroku deploy:war --app your-heroku-app-name target/your-app-name.war

またはGradleの場合:

Bash
heroku deploy:war --app your-heroku-app-name build/libs/your-app-name.war

デプロイ時のHerokuの挙動: heroku deploy:warコマンドを実行すると、Heroku CLIは指定されたWARファイルと、そのWARファイルが存在するディレクトリ(通常はプロジェクトのルートディレクトリ)にあるsystem.propertiesファイルもHerokuにアップロードします。HerokuのJava Buildpackは、アップロードされたsystem.propertiesファイルを検出し、その中に記述されたjava.runtime.versionに基づいてJVMをダウンロード・設定し、アプリケーションをビルド・実行します。

デプロイプロセス中に、Herokuのログに「Building with Java X」のようなメッセージが表示されれば、正しくJavaバージョンが指定されている証拠です。

デプロイ後のJavaバージョン確認

アプリケーションがデプロイされたら、実際に意図したJavaバージョンで実行されているかを確認することができます。

方法1: Herokuログの確認 デプロイ時のログ (heroku logs --tail) や、アプリケーションが起動した後のログで、Javaバージョンに関するメッセージを探します。

方法2: heroku runコマンドの利用 アプリケーションが動作しているdyno上で直接コマンドを実行して、Javaバージョンを確認できます。

Bash
heroku run java -version --app your-heroku-app-name

このコマンドを実行すると、以下のような出力が得られ、指定したJavaバージョンで実行されていることが確認できます。

Running java -version on ⬢ your-heroku-app-name... up, run.1234 (Free)
openjdk version "11.0.12" 2021-07-20
OpenJDK Runtime Environment (build 11.0.12+7-heroku)
OpenJDK 64-Bit Server VM (build 11.0.12+7-heroku, mixed mode)

ハマった点やエラー解決

1. system.propertiesファイルが読み込まれない

  • 問題: デプロイしてもJavaバージョンが変わらない、またはデフォルトのままになる。
  • 原因: system.propertiesファイルがプロジェクトのルートディレクトリ以外の場所に配置されている、またはWARファイルがsystem.propertiesファイルとは別の場所からデプロイされている。heroku deploy:warコマンドは、指定されたWARファイルと同じディレクトリパス内のsystem.propertiesを探索します
  • 解決策: system.propertiesは、pom.xmlbuild.gradleと同じ階層(プロジェクトのルート)に配置されていることを確認してください。また、heroku deploy:warコマンドは、そのルートディレクトリから実行するか、WARファイルのパスを正しく指定し、system.propertiesがそのWARファイルの親ディレクトリにあることを確認します。

2. サポートされていないJavaバージョンを指定

  • 問題: デプロイ中にビルドエラーが発生し、「Requested Java version X is not supported」のようなメッセージが表示される。
  • 原因: system.propertiesにHerokuのJava BuildpackがサポートしていないJavaバージョン(例: 古すぎるバージョンや最新すぎてまだサポート対象外のバージョン)を指定している。
  • 解決策: Heroku Dev Centerで最新のJava BuildpackがサポートするJavaバージョンリストを確認し、サポートされているLTSバージョン(8, 11, 17, 21など)を指定してください。

3. java.runtime.versionのスペルミス

  • 問題: system.propertiesファイルが無視される。
  • 原因: java.runtime.versionのキー名が間違っている。
  • 解決策: キー名が正確にjava.runtime.versionであることを確認してください。

解決策

上記で述べたように、Heroku CLIでWARファイルをデプロイする際にJavaバージョンを指定する最も確実な方法は、プロジェクトのルートディレクトリにsystem.propertiesファイルを正しく配置し、そのファイルにjava.runtime.version=XXと記述することです。そして、そのsystem.propertiesファイルを含んだプロジェクトディレクトリからWARファイルをビルド・デプロイすることで、HerokuのJava Buildpackが意図したJavaバージョンを自動的に適用してくれます。

常にHerokuのドキュメントで最新のサポート状況を確認し、ログを注意深く監視することが、スムーズなデプロイの鍵となります。

まとめ

本記事では、Heroku CLIを使ってJava WARファイルをデプロイする際に、デフォルトではなく特定のJavaバージョンを指定する方法について解説しました。

  • system.propertiesファイルの活用: プロジェクトのルートディレクトリにsystem.propertiesを作成し、java.runtime.version=XXと記述することでJavaバージョンを指定できます。
  • heroku deploy:warコマンド: このコマンドがWARファイルとともにsystem.propertiesファイルをHerokuにアップロードし、Buildpackがそれを解釈します。
  • Heroku Buildpackの働き: HerokuのJava Buildpackがsystem.propertiesを読み込み、指定されたJavaバージョン環境を構築します。

この記事を通して、HerokuでのJavaアプリケーション開発において、より柔軟なJavaバージョンの選択と管理ができるようになったことと思います。特定のJavaバージョンへの依存や、新しいバージョンの検証が必要な場面で、本記事の内容が役立てば幸いです。

今後は、Heroku Buildpackのカスタマイズ方法や、Dockerを使ったより高度なデプロイ戦略についても記事にする予定です。

参考資料