SAStrutsのインターセプタでセッションを使う
どうも、かつて書いた次の記事に誤りがあるようなので、訂正したいと思う。
SAStrutsでログイン確認インターセプタを使う - idesaku blog
SAStrutsでHttpSessionを使いたい場合、通常はフィールドを一つ定義してやればそこに自動的にバインディングされる。
@Binding private HttpSession httpSession;
これはActionやServiceでは有効なのだが、インターセプタではこの方法が通用しない。セッションを使って何かするインターセプタを書きたい場合、どうすればよいのか?
かつてSAStrutsでログイン確認インターセプタを使う - idesaku blogを書いた際にこの問題にぶつかり、ネットを調べて回った結果、次のように処理することにした。
HttpSession session = (HttpSession) SingletonS2ContainerFactory .getContainer() .getExternalContext() .getSession();
これでうまくいったのだが、どうもHotDeploy時に動作しない場合があるらしい(ClassCastExceptionが投げられる)。この件についてメーリングリストに質問がポストされていた。
[Seasar-user:17184] [SAStruts]インターセプター中での HOT deploy と COOL deploy の違い
これに対する、ひが氏の回答。
Interceptorで、直接セッションを触っているためだと思います。
[Seasar-user:17185] Re: [SAStruts] インターセプター中での HOT deploy と COOL deploy の違い
MapsessionScope =
SingletonS2Container.getComponent("sessionScope");
のようにSeasar2で管理しているオブジェクト経由で
セッションには触るようにしてください。
あー、そう書くのが正しいんですか。なので、前の記事で書いたコードは、次のように書くべきなのだろう。
private boolean isLoggedIn() { Map<String, Object> sessionScope = SingletonS2Container.getComponent("sessionScope"); LoginDto dto = (LoginDto) sessionScope.get("loginDto"); return (loginDto != null && loginDto.id != null); }
動作確認していないのだが、たぶん動くだろう。動かなかったらごめん。
それにしても、当該スレッドで提示されているコード、俺が書いたやつとよく似ている…。ありがちな処理だから、誰が書いても似たような外見になるのだろうか。それとも参考にしてくれたのか。そうだったら嬉しいが、同時に変な問題を抱えさせて申し訳ないなぁとも思う。そういうわけで、慌てて訂正した次第。
追記
Seasar 2.4.35で機能追加され、直接HttpSessionを触っても問題無いようになっている。そのため、本記事に合わせてコードを変更するまでもなく、単にバージョンアップさせれば問題は解決する。
しかし、BugではなくImprovementになっているところを見ると、やはり元々はsessionScopeを使って欲しかったのだろうなぁ。