GAE/J: セッション破棄時の処理は行われない

全部ちゃんと検証したわけじゃないんだけど、Google App Engine for Java (GAE/J) では、

  • javax.servlet.http.HttpSessionListener がサポートされていない
  • javax.servlet.http.HttpSessionに格納したデータは、削除されずにデータストアに残り続ける

らしい。

javax.servlet.http.HttpSessionListener がサポートされていない

Google Groups の下記スレッドによると、HttpSessionListener は GAE/J ではサポートされておらず、GAE サーバ上に配備すると sessionCreated メソッドおよび sessionDestroyed メソッドは呼び出されない。開発環境では呼び出されてしまうが、例えばsessionDestoyredメソッド内でデータストアに対してアクセスしようとすると例外が発生する。

Session destruction events, API availability therein
http://groups.google.com/group/google-appengine-java/browse_thread/thread/672879dd9a3ba137

セッションが破棄された時に何らかの処理 (不要になったデータの削除とか、ユーザのログインステータスを変更するとか) を行いたい場合は、それ用のcron ジョブを作らないといけないようだ。

GAE の ITS にも下記の通り登録されているが、なんともならない気がする。これってたぶんアーキテクチャ的に無理ってことだよね。

[]Issue 2117
Development server fires sessionCreated and sessionDestroyed, shouldn't.[]:http://code.google.com/p/googleappengine/issues/detail?id=2117

javax.servlet.http.HttpSessionに格納したデータは、削除されずにデータストアに残り続ける

ドキュメントで説明されている通り、そもそも GAE/J ではデフォルトだとセッションが使えず、使いたければ設定ファイルで指定しなければならない。有効にすると、HttpSession に setAttribute で格納したデータは、実際にはデータストアに永続化される。

で、セッション破棄のイベントを捕まえられないのは、HttpSessionListener だけでなく、GAE/J のフレームワークにとっても同じらしい。つまり、永続化されたセッションデータを消すことができず、データストアに残されたままになってしまう。これもやはり cron ジョブを実行して、古いものを消さないといけないらしい。もっとも、これについては Google 側で実装したものが提供されており、設定だけすればいいようだ。サンプルが下記のスレッドにある。

Provide a servlet for session cleanup
http://groups.google.com/group/google-appengine-java/browse_thread/thread/4f0d9af1c633d39a