ログインフォーム問題というより、ServletRequest の処理問題

これは、どう直すかな・・・。ややこしくて、少々誤認していた部分もあるが、理解するのに時間がかかった。問題は、PortalFilterをかませたときに発生する。PortalFilterがHttpServletRequestWrapperで実装した場合は、PortalFilter->実Request と言う感じにラップする。そんで、Tomcat でポートレットを呼び出すときには、includeの形で呼び出すが、そのときに、Tomcat が ApplicationHttpRequest をPortalFilterと実Request の間に挟み込む。この挟み込みによって、各コンテキスト内でセッションを共有できなくしたり、違うコンテキストとしての動作をする。つまり、Tomcatがポートレットをincludeで呼び出し、挟み込みを行い、Request を書き換えるので、ポートレット内で、JetspeedRequestContextを呼び出したときにはその挟み込まれたRequestを取得してしまい、セッションを取得したときには、ApplicationHttpServletRequestが書き換え、本来のセッションが取得できない。で、ポートレットでの処理が終わったら、TomcatはunwrapRequest()して、元に戻す・・・。

というわけで、HttpServletRequestWrapperによるPortalFilterの実装をやめて、HttpServletRequestをインターフェースして、試してみると、フォワードがダメになる。原因は、forwardしたときに、これまた、そのPortalRequestに対して、ラップ処理を行い、処理が一通り終わったときにunwrapRequest()を実行して、ClassCastExceptionと言う感じ。どうも、unwrapRequest()の終了条件にRequestFacadeクラスかどうかをチェックするところがあり、独自拡張しているPortalFilterはこの条件にマッチしないので、ラップされているRequestと勘違い?して、キャストして親を得ようとする(この動きはバグなのか?仕様っぽくない気もするが)。そんで、終了・・・。つまり、独自拡張したServletRequestで、フォワードするなと言うことか・・・。

うーん、はて、どうしたものかと考える。今思いつく解決策は、「JetspeedRequestContextでセッションを保持するRequest経由で呼び出すのをやめて、privateとかで値を保持する」か、「ServletPortletInvokerとかで、ポートレットの処理に入る前に、Requestを新規に生成する」などだろうか。JetspeedRequestContextを変える方のが楽な気もするな。でも、この問題は、現在はそうなっていないと思うが、ポートレットをマルチスレッドで呼び出したりする拡張を考えると、ポートレット用にRequestをコピーして、それを渡すのが良いのかもな・・・。

コメントを残す

メールアドレスが公開されることはありません。