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

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

App EngineでOpen Session In View

以前のエントリに、ひがさんからご丁寧なコメントをいただいて、もったいないので新しいエントリにさせていただきました。

AMFでの通信なら、persistentなうちにクライアントが触る可能性のある関連は触っておくのが一番無難な気がします。

この辺は、EJB3(EntityBean)ときにある程度答えが出ていて、
-OpenSessionInView
-Eager Loading
-Trigger(関連を触る)
-Using DTO(エンティティからDTOに関連をフラットな形にして渡す)
が方法として存在します。
どこまで関連を解決しておくのかは、あらかじめ決められないことが多いので、Eager Loadingはあまり現実的ではありません。
OpenSessionInViewが一番楽ですが、使えない場合は、Triggerがちょっと間抜けですが、次に楽な気がします。
DTOは確実ですが、めんどくさい。

私は、Flex/AIRでも、AMFではなく、HTTPServiceを使ってシンプルに通信するのが好みです。
サーバーからクライアントに返すときには、JSPでHTMLではなくXMLを返すようにしてあげれば、OpenSessionInViewを使えます。
このやり方だと、クライアントはFlexに限らずどれでも、サーバーは同じように処理できます。

ひがさん、ご丁寧な解説ありがとうございます! 

この辺は、EJB3(EntityBean)ときにある程度答えが出ていて、

なるほど。これらのパターンはそのままApp Engineにも当てはまりますね。DTOはおっしゃるとおり面倒なので(私もEJB2のころはMap+動的ProxyとかDTO自動化を模索しました)、Open Session In Viewがラクそうですね。

私は、Flex/AIRでも、AMFではなく、HTTPServiceを使ってシンプルに通信するのが好みです。
このやり方だと、クライアントはFlexに限らずどれでも、
サーバーは同じように処理できます。

じつは私も、今作っているシステムでは、ひがさんが提案された「フィルタによるOpen Session In View」に似た手法でPMを管理してます。

  • XXXControllerクラス(=RailsのControllerのようなもの)を用意
  • AMF/HTTPまたはXML/HTTPでリクエストを受けると、Controllerクラスのpublicメソッドを呼び出し
    • Rails風のルーティング規則(/xxx/yyyならxxxControllerのyyyメソッド)を適用
  • Controllerのpublicメソッド実行時の前後でインターセプト
    • ThreadLocalにひもづけたPMとQueryのopen/close
      • ただし多数回実行するQueryはexecuteするたびにcloseしておかないとエラーが起きる
    • システム例外のキャッチとエラー処理、ログ記録など
    • 本当はTransactionもここでcommit/rollbackしたかったけれど、よく考えたらエンティティグループごとに別々なのでムリでした。せめて@Transactionalでラクしたい〜(でもSpringを入れるほどでもない)

という感じで実装しました(フレームワークってほどではなくて、とりあえずPMのcloseをラクにしたかったのです)。Controllerクラスのロジック内ではエンティティはpersistentなので、クライアントで必要なエンティティを取得しておきます(時には二重ループで)。ロジックを出るとdetachedになるので、AMFの場合はそのままFlexクライアントに渡せます。

今はXML/HTTPとAMF/HTTPの両方を使い分けてますが、上の仕組みではどちらも同じように処理できます。AMFだと何も考えずにオブジェクトを1個返すだけで、芋づる式に他のオブジェクトもシリアライズしてくれるので重宝してます。一方、iPhone等も同時サポートする必要がある用途にはXML/HTTPを使っています。