org.apache.wicket.Sessionと実際のセッションが自動的に結びつかない場合

はじめに

 普通は「org.apache.wicket.Sessionと実際のセッションを結びつける」なんてことは意識しなくて良いのですが、レアケースでは考えなくてはいけません。
 今回はそんなメモ。

環境

org.apache.wicket.Sessionと実際のセッションが自動的に結びつかないケース

 下図のアプリについて、2番目のページでは、トップページでセッションに設定した値が取り出せそうですが、実は取り出せません。
 理由を端的に言うと、「トップページがステートレスだと判断されるから」です。
 ステートレスだと判断されると、どうして「org.apache.wicket.Sessionと実際のセッションが勝手に結びつかないのか」は後述します。

org.apache.wicket.Sessionと実際のセッションを結びつけている箇所

 org.apache.wicket.Sessionと実際のセッションはPage.onBeforeRenderで結びつけます。
 以下に該当メソッドを抜粋します。

protected void onBeforeRender()
{
    super.onBeforeRender();
    // If any of the components on page is not stateless, we need to bind the session
    // before we start rendering components, as then jsessionid won't be appended
    // for links rendered before first stateful component
    if (getSession().isTemporary() && !isPageStateless())
    {
        getSession().bind();
    }
}

 getSession().bind()で実際の結びつけ処理が行われます。
 getSession().bind()が実行されるためには上記の引用箇所から分かるように、下記の条件を全て満たす必要があります。

  • getSession().isTemporary()がtrueを返す。
  • Page.isPageStateless()がfalseを返す。

 getSession().isTemporary()は、org.apache.wicket.Sessionと実際のセッションを結びついているときにfalseを返すので、わりとどうでも良いです。要は、getSession().bind()を呼び出しても何も起きない場合にfalseです。

 問題は、isPageStateless()です。
 今回取り上げた例の場合、トップページ表示時にisPageStateless()がtrueであり、ステートレス扱いされています。
 結果、getSession().bind()が行われません。

ステートレスだと判断される条件

 下記の全てを満たす場合に、isPageStateless()がtrueを返すため、ステートレスだと判断されます。

  1. Page.isBookmarkable()がtrueを返す。
  2. Page.getStatelessHint()がtrueを返す。
  3. Pageに状態を持つコンポーネントが1個も存在しない。
    URLに履歴番号を持つようなコンポーネントは、状態を持ちます。例外があるのかは不明です。

 狙わないと、なかなか全ての条件は満たせないかもですね。

Page.isPageStateless()がtrueを返すケースで、org.apache.wicket.Sessionと実際のセッションを結びつけたい場合

二つ方法はあるのですが、どちらが正攻法なのかは私には分かっていません。

  • this.setStatelessHint(false)をPageクラスのコンストラクタで呼び出す。
  • getSession().bind()をPageクラスのコンストラクタで呼び出す。

とはいうものの

 一回でもどこかでgetSession().bind()が呼び出されてしまえば、org.apache.wicket.Sessionと実際のセッションは結びつくわけで、これを意識するケースはほぼ無いような気はします。

余談

 下図はorg.apache.wicket.Sessionと実際のセッションの関係です。
 間にAbstractHttpSessionStoreなんていうのが居るのですね。もっとも、具象クラスはまた別のクラスですが。