サーブレットを扱うときにリダイレクトの問題があります。リクエストスコープにバインドした値が維持できないなどの問題です。これはリダイレクトというのは純粋に別リクエストであるため為、ごく当然の話であるわけです。
ではリダイレクトを使わなければよいのかというと、話がちょっと違います。最近ではブラウザで[F5]ボタンや[戻る]ボタンに対応する為に、Post Redirect Getといわれる俗に言うPRGパターンが採用される事が多いです。ですので、いかにリダイレクトと付き合っていくかを考えなければいけません。
リダイレクトのために値を引き継ぐ方法として2つの方法があります。URLパラメータとセッションです。URLパラメータでは文字列しか渡せず、オブジェクトを引き継ぐ事は出来ません。セッションの場合は有用ですがライフサイクルを考えると無駄が多いです。そもそもセッションをリダイレクトのために扱うということは、セッションの解放処理などを考慮しなければならずシームレスに値の維持ができないわけです。
そこで最近ではStruts ShaleやJBoss Seam等、リクエストとセッションを内部で組み合わせた独自のスコープを提供しています。フレームワーク内部で処理される為、シームレスにスコープを扱う事ができ、その中でリダイレクトの問題も解決されています。
しかし、既存のフレームワークの組み合わせの中で解決できないものでしょうか。例えばリクエストスコープの値が維持できるだけでも、かなりな問題が解決できます。そこで以下の方法を考えました。(明日にでも実証しようかなと・・・)
- サーブレットフィルタ内でHttpServletResponseをサーブレットフィルタで独自のレスポンスラッパーでラップする
- レスポンスラッパーのsendRedirectが呼ばれたときに、リクエストスコープの値を全て取得
- セッションに格納する為の重複しないキーを生成
- 3で生成したキーで2の値をセッションスコープに格納する
- リダイレクトする際に、URLパラメータに3で生成したキーを付与する
- リクエストを受けたときに、時にリダイレクト用のセッションのキーが存在するかチェックし、リクエストスコープに復元する
要約すると、リダイレクトをハンドルしてセッションスコープにリクエストスコープの値を退避、そのキー(リダイレクトID)をURLパラメータに付けてリダイレクトを行います。でリダイレクトされたリクエストでリダイレクトIDを受け取ったときにセッションから復元を行うという感じです。
うまくやれば、これを元にリダイレクトを跨いだOpen Session In Viewパターンの実現が可能になるでしょう。HibernateやEJB3の遅延ローディングがリダイレクトを跨いでも出来るわけです。この辺は本来JBoss Seam当たりで解決できる問題ですが、既存のStrutsとHibernateオンリーな組合わせに導入するには最適ではないでしょうか。