同じFlexページの同時起動を禁止する

今作っているアプリケーションはStrutsで作成した登録ウィザードの移植なのですが、トランザクションをテストしようと思って同じページを複数開いたら、ウィザードの登録データが混ざってしまって大変なことに。

なぜかというと、ウィザードの進行中の一時データはサーバー側のセッションに持たせているからです。
IEでサイトを開いてログインし、別のウィンドウを(ファイル->新規作成で)開いて、そっちでもログインさせると、Java側が同じセッションIDを受け取ってしまうので、混じってしまうのです。
しかも、片方でログアウトすると、もう片方も強制ログアウトされてしまう。
痛い。とても痛い。

現象自体は、セッションのデータをさらにウィンドウIDごとに持たせ、さらにセッションIDへの参照をカウントアップさせれば、(大まかには)何とかなります。
しかし、そんなことしてたらせっかくサーバー側を流用した意味がない・・・。

てか、一人で同時に登録処理なんかさせてたまるかって話です。
ということで、アプリケーションのほうを同時起動させないようにしました。

やり方は簡単。LocalConnectionを同一アプリケーションで監視するだけです。

package
{
  import flash.net.LocalConnection;
  public dynamic class SingleApplicationEnforcer extends LocalConnection
  {
     public function SingleApplicationEnforcer(connectionName:String)
     {
        try{
          connect(connectionName);       
        }catch (error:ArgumentError){
          //connectionが有効なものかどうか試す
          var ping:Function =function():void{
            trace("ping!");
          }
          try{
            send(connectionName,"ping");
            //他のインスタンスが有効だと例外が出ない
            //つまり二重起動
            _isExistOther = true;
          }catch(e:*){
            //接続は残っていてもアプリケーションはない
            //継続してOK

            //接続確認用コールバックメソッド
            this["ping"] = ping;
          }
       }
    }
  }
}
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
  creationComplete="completeHandler(event)">
  <mx:Script>
    <![CDATA[
      import mx.controls.Alert;
      private var ls:SingleApplicationEnforcer;

      private function completeHandler(e:Event):void{
        ls = new SingleApplicationEnforcer('connSample');
        if(ls.isExistOther){
          Alert.show("Second Applications");
          enabled = false;
        }
      }
    ]]>
  </mx:Script>
</mx:Application>

ブラウザが違う場合でも有効なのは、果たしていいことなのか・・・。
まぁ、人によっては役に立つこともあろうかと思います。

しかし、このセッションの使い方のミスは痛恨。
調べてないけど、FlexSessionだとFlashインスタンスごとに割り振られたりとかしないのかなぁ・・・。

[2009/3/4追記]
このコードだと、同じサイトを開いていないのに検出してしまう場合があることがわかりました。
Flash Playerは、Flashアプリケーションが一つでも起動している間はすべてのLocalConnectionを保持しているみたいです。
つまり、全く関係のないFlashアプリケーションが動いている状態では、一度アプリケーションを閉じて2度目に立ち上げたときに、以前のLocalConnectionを検出するのです。
これを防ぐためには、アプリケーションを閉じる際に必ず明示的にConnectionを閉じればいいのですが、Flashではそれができない場合も多いので、LocalConnectionのコールバックメソッドがあるかどうかで判定することになるかと。
そのうちこのサンプルにも手を入れます。

[2009/3/8追記]
上の通り、サンプルコード修正しました。
手抜きでdynamicクラスにしています。