スティルハウスの書庫の書庫

はてなダイアリーで書いてた「スティルハウスの書庫」を移転してきました。

BlazeDSの本番環境へのデプロイでハマる

(この記事は、アドビシステムズAdobe Developer Connection」向けに書いたものを再掲しています)

ご都合.comの特徴は、GAE/Jで動作するAdobe BlazeDSによって、FlexのRemoteObjectを利用したリモーティングによる通信を用いている点です。前回は、BlazeDSの各種ライブラリファイルや設定ファイルをGAE/JプロジェクトのWEB-INFフォルダ以下に配置し、ローカル環境で問題なくテストできたところまで説明しました。

しかし問題は、GAE/Jの本番環境へのデプロイ時に起こりました。GAE/Jプラグインの「デプロイ」ボタンをクリックしてコードをデプロイし、FlexクライアントからGAE/Jの本番環境へ接続してリモート呼び出しをテストすると、以下のようなエラーがGAE/Jのダッシュボード上に表示されました。

**** MessageBrokerServlet failed to initialize due to runtime exception:   Error: java.lang.NoClassDefFoundError: java.lang.management.ManagementFactory is a restricted class. Please see the Google App Engine developer's guide for more details.


GAE/Jのダッシュボード上に表示されたエラーログ

これはどうやら、MessageBrokerServletが利用する管理用APIが、GAE/Jのサンドボックスの制限に引っかかっているようです。「もしかしてBlazeDSってGAE/Jでは動かない……?」と不安になりつつも、ネット検索で先人たちの情報を探しました。すると、Martin Zoldano氏のすばらしいブログ記事を見つけました。

このブログ記事を要約すると、「BlazeDS Community release 3.2.0.3978をGAE/Jで動作させることができた(ただしremoting機能のみ)。以下の3つの点の修正が必要となる」

  1. 管理機能のオフ(上述のエラーの原因)
  2. AbstractAmfInput.javaクラスのソースコード修正
  3. BaseHTTPEndpointクラスのソースコード修正

では、これらの手順を以下に説明します。ただし、ここで紹介するのは要約ですので、詳しくは上記ブログを参照してください。

まずは、管理機能をオフにします。サーバ側のservices-config.xmlにて、system要素に以下の1行を追加します。

<manageable>false</manageable>

これにより、BlazeDSの管理機能がオフとなり、上述のエラーが発生しなくなりました。しかしこれだけではまだ動作しません。Flexクライアントからリモート呼び出しを実行すると、クライアント側で通信エラーが発生してしまいます(サーバ側にはエラーが記録されません)。この原因は、上記ブログによると、GAE/Jのサンドボックスによるリクエストデータの読み込み動作が通常のサーブレットコンテナとは異なるため、例外を発生させているということのようです。

そこで、上記2の手順が必要です。これはBlazeDSソースコードの修正ですので、それに先だってBlazeDSのダウンロードページ(http://opensource.adobe.com/wiki/display/blazeds/Release+Builds)よりソースコードblazeds-src-3.2.0.3978.zip)をダウンロードし、付属のドキュメントにしたがってビルドする環境を整えます。ビルド可能な状態になったら、flex.messaging.io.amf.AbstractAmfInput.javaクラスの58行目を以下のように修正します。

this.in = new DataInputStream( new java.io.BufferedInputStream( in ) );

この修正後にビルドを実行し、それによって生成されたJARファイルを再度WEB-INF/lib以下にコピーしました。しかし、今度はBlazeDS側で「セッションが重複している」というエラーが発生してしまいます。この原因もはっきりとは分かりませんが、上記ブログによると、おそらくGAE/Jが自動的に複数のサーバノード上でサーブレットを展開するために、1つのクライアントからのセッション情報が重複したように見えてしまうという原因のようです。

これに対処するには、上記3の手順が必要です。flex.messaging.endpoints.BaseHTTPEndpointクラスのソースファイルを開き、setupFlexClientメソッドにてセッション重複エラーを発生させる部分(404行目〜418行目)をコメントアウトし、BlazeDSを再度ビルドして、JARファイルを更新します。

以上の対処により、どうやらエラーを発生させずにBlazeDSをGAE/J上で動作させることができました。これらの手順を実施したのちは、まったくエラーも発生せずにスムーズに動作しています。上記ブログを書かれたMartin氏には本当に感謝したいと思います。