2009年9月7日月曜日

Google App EngineでBlazeDSのRemoting通信を試す

Google App Engine(以下GAE/J)でBlazeDSのRemotingObjectを拡張したリモーティング通信を試してみる。

[環境]
  • OS : Windows Vista SP2
  • IDE : Eclipse v3.4.2(Ganymade)
  • SDK : appengine-sdk-1.2.5/JDK1.6.0_07/Flex Builder3.2.0
  • ライブラリ : BlazeDS3.2.0.3978

[サーバーサイド]

1.Eclipse上でWeb Application Projectとして新規プロジェクトを作成

2.1で作ったプロジェクト下にBlazeDS用のライブラリや設定ファイルをコピー

デプロイ図
BlazeDSをダウンロードして展開するとblazeds.warがある。それが基本的にBlazeDSの動作に最低限必要なコンポーネントになっている。

なのでblazeds.warを展開し、WEB_INFの下にある、flexフォルダ(4つのxmlファイルがある)、及びlibフォルダ(12個のjarファイルがる)をコピーし、GAE/Jのプロジェクト/war/WEB-INF下に配置する。

プロジェクト内のリソースの配置は以下。赤枠は新規追加したファイル。青枠はプロジェクト作成時に自動生成されるファイルで変更が必要なファイル。









3.クラス作成

動作確認のため、HelloWorld的な簡単な文字列を返すクラスを作ってみる。コードはこんな感じ。
package jp.co.tricell.sonicboom.rpc;
import java.util.logging.Logger;
public class HelloDS {
 // ロガーを指定
 private static final Logger log =  Logger.getLogger(HelloDS.class.getName());
 public String sayHello(String name) {
  log.info("input str = " + name);
  return "こんにちは、" + name + "さん!";
 }
}

4.WEB-INF/flex/remoting-config.xmlにdestinationを追加

HelloDSクラスをリモーティング接続先として設定ファイルに追加する。SyntaxHighlighterが一行だけで閉じるxmlのタグの書き方に対応していないのでワザワザ</adapter-definition>と書いてますが、実際は<adapter-definition id=~ default="true"/>でOKです。


    
        
    

    
        
    
    
    
          
              jp.co.tricell.sonicboom.rpc.HelloDS
          
    



5.WEB-INF/flex/services-config.xmlのsystemタグにmanageableの値falseを追加

これは今回の環境で必要な設定なのか不明だが、GAE/J上でBlazeDSを動作させるために参考にしたいくつかのページで記述されていたので設定として追加。
参考:
・Martin's Blog: AppEngine & Adobe BlazeDS (fix)
・Flex/AIRハマり帳 ~第2回 Google App Engine for Java+BlazeDSでハマらない方法・後編~ | デベロッパーセンター
    
 
        
        false
 
        
            false
            
        
    

6.WEB-INF/appengine-web.xmlのsessions-enabledタグに値trueを追加

セッションを有効にするため設定を追加する。
 true

 
 
  
 

7.WEB-INF/web.xmlにMessageBroker Servletを追加

  
        flex.messaging.HttpFlexSession
  
  
  
    
        MessageBrokerServlet
        MessageBrokerServlet
        flex.messaging.MessageBrokerServlet
        
            services.configuration.file
            /WEB-INF/flex/services-config.xml
       
       1
    
    
        MessageBrokerServlet
        /messagebroker/*
    

[クライアントサイド]

Airアプリを作ってみました。encpoint先はお持ちのGAE/Jのドメインを指定してください。
タグを含んだコードの場合、SyntaxHighlighterがコードを全て、Firefoxなどは小文字(<mx:WindowedApplication~→<mx:windowedapplication~など)、Internet Explorerの場合は大文字に展開してしまいます。コードをコピーする場合は大文字小文字に注意してください。

  
  
    
  
   
      
      
      
   


[動作確認]

Airアプリをクライアントとしてつくり、HelloDSと通信させてみた。但し!!!ここで問題が・・・
GAE/J上にデプロイしたクラスと通信させてみたら、以下のようなメッセージが表示され実行失敗orz。
[RPC Fault faultString="Detected duplicate HTTP-based FlexSessions, generally due to the remote host disabling session cookies. Session cookies must be enabled to manage the client connection correctly." faultCode="Server.Processing.DuplicateSessionDetected" faultDetail="null"]
at mx.rpc::AbstractInvoker/http://www.adobe.com/2006/flex/mx/internal::faultHandler()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\rpc\AbstractInvoker.as:220]
at mx.rpc::Responder/fault()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\rpc\Responder.as:53]
at mx.rpc::AsyncRequest/fault()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\rpc\AsyncRequest.as:103]
at NetConnectionMessageResponder/statusHandler()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\messaging\channels\NetConnectionChannel.as:569]
at mx.messaging::MessageResponder/status()[C:\autobuild\3.2.0\frameworks\projects\rpc\src\mx\messaging\MessageResponder.as:222]
GAE/Jが自動的に複数のサーバノード上でサーブレットを展開するために、1つのクライアントからのセッション情報が重複したように見えてしまうのが原因らしい。参考サイトを元にソースコードを編集してビルドする。
参考:http://prepro.wordpress.com/2009/05/17/googleappengineでblazeds環境を構築してみた


[エラー解決までの道のり]

1.BlazeDSのソースコードをダウンロード
BlazeDSのページからソースコードをダウンロードする。

2.BaseHTTPEndpoint.javaのコードの一部をコメント
ソースコードのzipを展開。編集が必要なソースは、flex.messaging.endpoints.BaseHTTPEndpoint.java。 ここの405行目からのduplicateSessionDetectedのチェックをコメントする。
/*if (duplicateSessionDetected)
        {
            List sessions = flexClient.getFlexSessions();
            for (Iterator iter = sessions.iterator(); iter.hasNext();)
            {
                FlexSession session = (FlexSession)iter.next();
                if (session instanceof HttpFlexSession)
                    session.invalidate();
            }
            
            // Return an error to the client.
            DuplicateSessionException e = new DuplicateSessionException();
            e.setMessage(ERR_MSG_DUPLICATE_SESSIONS_DETECTED);
            throw e;
        }*/
return flexClient;

3.ソースのビルドのため、Antをダウンロード
Apache Ant 1.7.1をダウンロード。

4.ソースのビルドのため、Ant-CONTRIBをダウンロード
Ant-CONTRIB 1.0b3をダウンロード。
展開してできるlibフォルダ内に有るant-contrib-1.0b3.jarをantフォルダのlib内にコピペ。

5.環境変数としてANT_HOMEを設定

6.環境変数PATHに%ANT_HOME%\binを追加

7.ビルド実行
BlazeDSのソースコードを展開したフォルダから
#ant clean
#ant make
を実行。
ビルド失敗orz
BUILD FAILED
C:\blazeds-src-3.2.0.3978\build.xml:73: The following error occurred while executing this line:
build.xml:156: Unable to rename old file
(C:\blazeds-src-3.2.0.3978\lib\flex-messaging-common.jar) to temporary file
編集したコードが含まれるflex-messaging-common.jarが権限が足りず変更できないらしい。はぅー。
参考:Adobe Forums: build blazeDS source code

結局Windows環境では権限をフルコントロールにしてもビルドエラーがどないもこないも解決できなかったので、Macでビルド。
ビルド成功!ほー(^-^;)

新しく出来た、flexから始まる5つのjarをGAE/JのプロジェクトのWEB-INF/libにコピペ。

8.通信テスト
GAE/J上にデプロイし、Airクライアントと通信。
通信成功ぉ~~!やたっ!

Windows環境でビルドに困る人のために、修正したコードでビルド済みのjarファイル5つを公開しま~す。この5つのjarをGAE/JのプロジェクトのWEB-INF/libにコピペしてGAE/Jへデプロイすればビルドせずにリモーティング通信できると思います。
元ソース:
blazeds-src-3.2.0.3978.zip

修正後jarファイル:
flex-messaging-common.jar
flex-messaging-core.jar
flex-messaging-opt.jar
flex-messaging-proxy.jar
flex-messaging-remoting.jar

4 件のコメント :

  1. blazedsのソースに手を入れなければならないとは・・・

    GAEjはやはり普通のサーブレットコンテナとは別と考えた方が良さそうですね。

    ともかく、動くという事が分かって何より(^^)/

    返信削除
  2. 苦労したなり~。
    でもappengineのsdkがつい最近1.2.5になったばかりと言うこともあり、同じ轍を踏んじゃう方もいるかもしれないと思って、ログアップしました。

    返信削除
  3. あとで気がついたんですが、いちいちビルドしなくても同一パッケージで同一クラスを作って、そちらをjarよりも先に読ませてやればよかったりします。

    # クラスファイルが同一の場合の読み込みは先勝ちなので...

    返信削除