目次


Bluemix を利用したハイブリッド・クラウドに Java アプリケーションをマイグレーションする、パート 3

スタンドアロンの Java プログラムを Bluemix にマイグレーションする

Comments

このシリーズのパート 1パート 2 では、標準的な Java EE を使用して Web アプリケーションを Bluemix にマイグレーションする方法を説明しましたが、スタンドアロンの Java アプリケーションについてはどうでしょう? main() メソッドがある Java プログラムを Bluemix 内で実行するにはどうすればよいのでしょう?

スタンドアロンの Java アプリケーションがあるのはごく一般的な状況ですが、こうしたアプリケーションを Bluemix へマイグレーションする理由は数多くあります。例えば、アプリケーションが定期的に実行されるバッチ・プログラムであり、終了する前やスリープ状態になる前に短時間で集中的なデータ処理を行うようになっているかもしれません。あるいは、アプリケーションが AMQP などのプロトコルでコマンドをリッスンするプログラムであるかもしれません。さらには、アプリケーションが Spring や JEE のようなフレームワークの代わりに、Netty などの組み込み HTTP サーバーを使用しているかもしれません。

私たちはこうした状況を再現するプロセスに取り組む中で、Cloud Foundry と Bluemix のアーキテクチャーについて、さらにこれらのアーキテクチャーでは、どのようにしてアプリケーションを管理するのかについて、いくつかの興味深いことを学びました。前述の質問に対する回答は、結局のところ 1 行に簡潔にまとめられます。これについてはこのチュートリアルの終わりで説明しますが、その 1 行の回答が真実である理由や、自力でこのような回答に至る方法については、私たちの説明に従って異なるいくつかの方法を試してみない限り、理解できるようにはならないでしょう。

アプリケーションを作成するために必要となるもの

このチュートリアル・シリーズのパート 3 では、スタンドアロンの Java プログラムを Bluemix 内で実行する方法を検討します。その中で Cloud Foundry マニュアルのナビゲーション方法、CF コマンド・ライン・ツールの使用方法、Cloud Foundry および Bluemix でのデバッグ方法についてのヒントを紹介します。

PaaS を利用するメリットとデメリット

Bluemix は、PaaS (Platform as a Service) と称されているサービスの一例です。プラットフォームをサービスとして利用すると、開発者が行わなければならない最も一般的な作業を容易に行えるようにする、単純なツールとランタイムが提供されるので、開発者は作業を楽に行えるようになります。ただし、「最も一般的な」という言葉に注意してください。ほとんどの PaaS 層では同じ原則を共有しており、その原則では、開発者がある特定の明確な方法に従って開発を行うことを前提としています。開発者がその前提とされる方法から逸脱すると、これらの PaaS 層は何らかのガイダンスを提供するでしょうが、その開発者が行った方法に一般的な方法と同様の評価が付けられることを期待してはいけません。

これが、私たちがサンプル・アプリケーションで直面した問題でした。Bluemix アプリケーションの数多くの例を調べるとわかりますが、Java アプリケーションを作成する際に従う最も一般的な方法は、断然、Liberty アプリケーション・サーバーを使用してアプリケーションを作成する方法です。しかし、私たちのサンプル・アプリケーションはもっと単純で、main() メソッドを使用するプログラムがあるだけなので、アプリケーション・サーバーは必要ありません。私たちは、どのように開発を始めればよいかの答えを得るために、最初のステップを踏み出す必要がありました。

ステップ 1. Java JAR ファイルを作成する

アプリケーションのさまざまな要素が動作する仕組み、問題につながる可能性がある要素、デバッグの方法などを理解するために、私たちが実行している Java アプリケーションの簡易版を出発点とします。Eclipse を使用してコードを開発しますが、Bluemix 用の Eclipse プラグインは使用せずに、このサンプル・アプリケーションをデプロイします。このプラグインの代わりに使用するのは、Cloud Foundry コマンド・ライン・インターフェースであり、アプリケーションをデバッグする際にはそのログを使用します。

この例では、hellojavamain.jar と hellojavamainrunnable.jar という 2 つの Java JARファイルを使用しています。これら 2 つのファイルは、上掲の「コードを入手する」ボタンをクリックすることによって、入手することができます。そうせずに (おそらく、もう少し詳しく学びたくて) 自力でコードを作成したいという場合は、以下のステップに従ってください。

  1. Eclipse で新規 Java プロジェクトを作成します (「File (ファイル)」 > 「New (新規)」 > 「Java Project (Java プロジェクト)」の順にクリックします)。このサンプルには「HelloJava」という名前を付けます。「Create a Java Project (Java プロジェクトの作成)」ウィンドウでは、必ず実行環境として「JavaSE-1.6」を設定してから「Finish (完了)」をクリックします。
  2. HelloJavaMain という新規 Java クラスを作成します (「File (ファイル)」 > 「New (新規)」 > 「Class (クラス)」の順にクリックします)。この例の場合、デフォルト・パッケージ内に新規クラスを作成して構いません)。
  3. クラスのソース・コードを以下の Java ソースで置き換えます。
    public class HelloJavaMain {
    public static void main(String[] args) {
    	for (int i=0; i<1000; i++) {
    	System.out.println("It worked! Hello World!");
    	try {
    		Thread.sleep(1000);
    	 } catch (InterruptedException e) {
    	// This should not happen
    		e.printStackTrace();
    	}
    	}
    }
    }

    このようにするのは、長時間実行される Java プロセスの単純な例になることを意図しています。最終的にプロセスは 1000 秒後に終了しますが、この例には十分な長さです。このコードは、例えばデータを処理したり、非同期プロトコルで接続をリッスンしたりするなどの興味深いことを行う複雑なコードの代わりとなる、単純化されたコードに過ぎません。
  4. コードをテストするために、クラスを選択した上で、メニューから「Run As (実行)」 > 「Java Application (Java アプリケーション)」の順に選択します。
  5. Eclipse コンソールに、以下のような大量の出力が表示されるはずです。
    It worked! Hello World!
  6. Eclipse のエクスポート機能を使用して、このプロジェクトを JAR ファイルとしてエクスポートします (「File (ファイル)」 > 「Export (エクスポート)」の順にクリックします)。
  7. エクスポート・ウィンドウで「Java」 > 「JAR File (JAR ファイル)」の順に選択し、プロジェクトを選択します。JAR ファイルに「hellojavamain.jar」という名前を付けてから、「Finish (完了)」をクリックします。

ステップ 2. アプリケーションを Bluemix にデプロイする: 試行その 1

この単純で素朴な手法の興味深い部分は、ここから始まります。読者の皆さんは、Bluemix と Cloud Foundry を使用する他の多数のサンプルと同じく、このサンプルも以下のように cf push に追加のパラメーターをいくつか設定して実行するだけでデプロイできると思うのではないでしょうか。
cf push hellojavamain-ABC -p hellojavamain.jar

この場合、push に対する 1 番目のパラメーターは、作成または更新するアプリケーションの名前です。-p パラメーターは、実行するコード (つまり、JAR ファイル) の場所を指定します。

  1. Cloud Foundry ツールにログインして、以下のようなコマンドを入力します。
    cf push hellojavamain-<自分のイニシャル> -p hellojavamain.jar
    以下に一例を示します。
    cf push hellojavamain-ABC -p hellojavamain.jar
    (注: アプリケーションの名前が一意でないために失敗するのを回避できるよう、自分のイニシャルまたはランダムに選んだ任意の 3 文字を追加してください)。
  2. コードを正しく作成していれば、前途は有望です。上記のコマンドは指定された JAR ファイルを Java コードとして認識することから開始して、Java Liberty ビルドパックを選択します。次に、ドロップレット (コードに Java Liberty を加えてパッケージ化されたコンテナー) をアップロードして実行を試みます。しかしながら、cf push コマンドの出力には、以下のメッセージが繰り返されるだけです。
    0 of 1 instances running, 1 starting
    0 of 1 instances running, 1 starting

    最終的に、この長々と繰り返されるメッセージの出力は、以下の異常終了メッセージで終わります。
    FAILED
  3. 何が失敗したのかを明らかにするには、以下のコマンドを入力します。
    cf logs hellojavamain-ABC -–recent
  4. ログをひと通り調べるうちに、ログの途中に以下のような興味深い行が見つかります。
    2015-08-09T17:09:15.31-0400 [App/0] ERR [ERROR ] CWWKZ0124E: Application myapp does not contain any modules.
    この行が伝えていることは、アプリケーションが期待していた JAR ファイルは、main() メソッドが含まれた Java SE JAR ファイルではなく、JEE モジュールが格納された JAR ファイルであったということです。これが、私たちが最初に学んだ教訓です。つまり、最も単純で素朴なデプロイメント・メカニズムは機能しません。

ステップ 3. アプリケーションを Bluemix にデプロイする: 試行その 2

この時点で皆さんは (私たちがそうであったように)、このアプリケーションには Liberty アプリケーション・サーバーはまったく必要ないのに、Bluemix はデフォルトで Java Liberty ビルドパックを選択していることが問題だと考えるかもしれません。このシリーズのパート 1 を読むと、Bluemix では Java 開発の別の方法として標準的な Java ビルドパックも使用できることがわかります。自動的に選択されるビルドパックではなく、別のビルドパックを選択するには、push で -b コマンド・ライン・オプションを使用します。

  1. Cloud Foundry ツールにログインして、以下のコマンドを入力します。
    cf push hellojavamain-ABC -p hellojavamain.jar -b java_buildpack
    ここで ABC は、自分のイニシャルまたはランダムな任意の 3 文字で置き換えてください。
  2. 今度は、別の新たな問題が浮上してきます。上記のコマンドは push を実行しようとしますが、その試行は以下のエラーで終わります。
    FAILED
    Server error, status code: 400, error code: 170004, message: App staging failed in the buildpack compile phase
  3. どうして失敗したのでしょう?今度は以下のコマンドを入力します。
    cf logs hellojavamain-ABC --recent
    すると、以下の行がログの奥深くに埋もれているのがわかります。
    2015-08-09T17:25:19.52-0400 [STG] ERR No container can run this application
  4. 皆さんは先ほどと同様に「これは何を意味しているのだろう?」と思うかもしれません。ここでは、IBM Bluemix のコンテナー・サービスは一切利用していません。このエラー・メッセージで使われている「container (コンテナー)」という語が何を指しているのかは、実際のところ少し曖昧です。このメッセージは、Docker コンテナーや IBM のコンテナー・サービスについて言及しているわけではありません。Bluemix の資料には、「コンテナー・コンポーネントは、アプリケーションを実行する手段を表しています。コンテナーのタイプには、従来のアプリケーション・サーバーやサーブレット・コンテナーから、単純な Java main() メソッドの実行まであります。」と記載されています。
  5. これがまさしく、この例で発生した問題です。失敗の原因は、「コンテナー・コンポーネント」がどのようにアプリケーションを実行することになっているかを認識していないことにありました。事実、Bluemix の資料をもう少し深く掘り下げていくと、「main() メソッドがある Java アプリケーションは、自己実行可能な JAR としてパッケージ化されている場合に実行することができます。」という情報が見つかります。

ステップ 4. 実行可能な JAR ファイルを作成して、アプリケーションを Bluemix にデプロイする: 試行その 3

ステップ 3 のサブステップ 5 に記載した情報が、まさに私たちに必要だったヒントです。Java プログラミングでは、main() メソッドが含まれるクラスを manifest.mf ファイル内に記述することで、JAR ファイルを実行可能にします。これを Eclipse で行うには、JAR ファイルを通常の JAR ファイルとしてではなく、Eclipse で「Runnable JAR ファイル」と呼ばれるものとしてエクスポートします。

  1. Eclipse に戻り、「File (ファイル)」 > 「Export (エクスポート)」の順に選択します。この操作によって開く「Export (エクスポート)」ウィンドウで、標準的な JAR ファイルではなく、「Runnable JAR file (Runnable JAR ファイル)」としてエクスポートするように指定します。
  2. 次のウィンドウでは、「Launch Configuration (起動構成)」のドロップダウン・メニューから「HelloJavaMain」クラスを選択します。これにより、JAR ファイルをエクスポートすると、マニフェスト・ファイル内の適切なエントリーが JAR ファイル内に作成されます。Runnable JAR を指定する画面のスクリーンショット
    Runnable JAR を指定する画面のスクリーンショット
  3. これで問題は解決されるでしょうか?それを明らかにする前に触れておきますが、皆さんが Eclipse を使用しているのではなく、コマンド・ラインだけに従っているときのために、変更後のファイル hellojavamainrunnable.jar のコピーを用意しておきました。JAR ファイルを Runnable JAR ファイルとしてエクスポートし直したら、以下のコマンドで再試行することができます。
    cf push hellojavamain-ABC -p hellojavamainrunnable.jar -b java_buildpack
  4. 最初は、このプロセスは上手く行きそうに見えます。ビルドパックがコンパイルされ、アプリケーションがデプロイされ、今回はコードが見つかります。しかし出力を見ると、以下の情報が示されています。
    0 of 1 instances running, 1 starting
    0 of 1 instances running, 1 starting
    0 of 1 instances running, 1 down
    0 of 1 instances running, 1 down
    再びログを調べると (前と同じコマンドを使用)、アプリケーションは実際に実行されていて情報を出力しているものの、長く実行されてはいないことがわかります。結局のところ、極めて重要な情報がまだ欠けているのです。ログ内の以下の行に注目してください。
    2015-09-07T10:33:35.10-0400 [DEA] ERR Instance (index 0) failed to start accepting connections
  5. HTTP でリッスンしない Java アプリケーション (このサンプル・アプリケーションもその 1 つです) では、push コマンドに -no-route パラメーターを追加する必要があります。そうしなければ、Cloud Foundry は、皆さんが HTTP トラフィックを自分のプログラムにルーティングしたいものと見なしてしまいます。このパラメーターを指定しない場合、最初はクラスが Java コードにロードされて起動され、正常に動作しますが、最終的には DEA がタイムアウト・エラーをスローすることになります。

以上の理由から、アプリケーションは最初の試行で実際に起動されたものの、リスナー・ポートでリッスンしていないため、Cloud Foundry はアプリケーションがダウンしていると見なしたというわけです。

ステップ 5. ワーカー・プロセスを指定する

Java ワーカー・プロセスをデプロイするための最後のコマンドで、すべてを完成させましょう。そのコマンドは以下のとおりです。
cf push hellojavamain-ABC -p hellojavamainrunnable.jar -no-route

この時点で、Java ビルドパックを指定する -b オプションはどうなったのか疑問に思うかもしれません。このオプションを使用したのは、皆さんに Java ビルドパックを紹介し、Cloud Foundry Web サイトのマニュアルを参照してもらい、Runnable JAR ファイルと -no-route オプションが必要な理由を理解してもらいたかったからです。実際のところ、Java ビルドパックを指定できる一方で、Java ビルドパックをベースに作成されているデフォルトの Liberty ビルドパックを使用して、こうしたすべてを行うこともできました。どちらのビルドパックを使用しても構いません。使用するビルドパックを切り替えるには、-b パラメーターを明示的に使用します。

  1. 以下のコマンドを入力します。
    cf push hellojavamain-ABC -p hellojavamainrunnable.jar -b java_buildpack -no-route
    または
    cf push hellojavamain-ABC -p hellojavamainrunnable.jar -b liberty-for-java -no-route
  2. いずれかのコマンドを実行した後、コンソールには「requested state」として「started」と示されるはずです。関連付けられている URL はなく、「state」には「running」と示されます。コンソールに表示されたプログラムのステータスのスクリーンショット
    コンソールに表示されたプログラムのステータスのスクリーンショット
  3. ログには、一連の成功メッセージが記録されていて、エラーはないはずです。コンソールに表示された、その後のプログラムのステータスのスクリーンショット
    コンソールに表示された、その後のプログラムのステータスのスクリーンショット
  4. これまでのチュートリアルと同じく、使用し終わったアプリケーションはクリーンアップすることをお勧めします。それにはまず、アプリケーションを停止します。
    cf stop hellojavamain-ABC
  5. 次に、アプリケーションを削除します。
    cf delete hellojavamain-ABC and answer Y.

まとめ

ここで行った方法では、いくつかの試行をしなければなりませんでしたが、最終的には目的を果たすことができ、Bluemix 内の Java アプリケーションのデバックについて多くを学ぶことができました。ここまでで皆さんは、標準的なスタンドアロンの Java アプリケーションを Bluemix にマイグレーションするプロセスを始められるようになったはずです。今では、このシリーズの以前のチュートリアルで取り上げた手法を適用して、アプリケーションにサービスをバインドし、Bluemix で提供しているさまざまなサービスを利用することができます。今後のチュートリアルでは、Java アプリケーションをオンプレミス・データベースに接続する方法を見ていく予定です。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Cloud computing, Java technology
ArticleID=1024521
ArticleTitle=Bluemix を利用したハイブリッド・クラウドに Java アプリケーションをマイグレーションする、パート 3
publish-date=12242015