ViewExpiredException

<< 戻る   トップ >>

ここのところ、ViewExpiredException に悩まされていた。あやふやな知識によれば、JSF Facelet はマネージドビーンと連携し、マネージドビーンのプロパティに値を保存する。マネージドビーンには寿命 (スコープ) がある。例えば、デフォルトの @RequestScoped では、リクエスト開始からレスポンス送信までアクセス可能で、それ以降は Expire される。Expire された後にマネージドビーンにアクセスしようとして発生するのが件の ViewExpiredException である。

例外の発生を避けるために、まずサーバ資源の無駄を覚悟でスコープを広げてみた。セション単位 @SessionScoped にしても、最大の @ApplicationScoped にしても、ViewExpiredException は発生は抑止できなかった。とくに @ApplicationScoped では Web アプリケーションがアクティブである限り Expire しないはずなので、この結果は腑に落ちない。長時間アクセスがないとまさかアプリケーションが不活性化してしまうのだろうか。

そもそも、ページャ動作など初歩的な CGI プログラミングである。<form> の <input type="hidden"/> に次の開始レコードと1ベージあたりのレコード数増分を設定し、<input type="submit"/> によって CGI パラメータとしてリクエストする。プログラムはパラメータを解釈して HTML ストリームを出力すればよいのだ。ところが、Facelet では Facelet の <inputHidden/> ではなくマネージドビーンに値を保持させるから、ビーンの寿命が問題になるのである。まさか CGI 的な動作ができないのだろうか。

Stack OverFlow (a question and answer site for professional and enthusiast programmers だって。Enthsiast かい。)の "javax.faces.application.ViewExpiredException: View could not be restored" によると、<f:view> に transient=true というパラメータをつけることで値をマネージドビーンで保持せず、CGI 的な動作をするようになるんだそうだ。試してみてブラウザで Facelet が同展開されたか確認すると、<form> 内の JSF/Facelet の隠しフィールド <input type="hidden" name="javax.faces.ViewState" value="stateless"/> で値が stateless になる。これで問題が解決するのであった。

解決しないと、例えば鴨乃嘴南蛮 Sesto に訪れて30分ぐらい経過してからなにか操作をするだけで、例外を投げてエラーメッセージを表示する。「ビジネス」時の動作としては30分の不在はすなわち不審であるからこれが望ましい動作だろうが、たかがブログのページングでは困るのだ。これで懸案がなくなったので、ページャの動作制限 (開始レコードが負になったり、レコード数以上になったりすることを制止する) に進みたい。


作成: 2014-06-11 14:48:23.0更新: 2014-06-11 18:58:34.0
http://museo-anonimo.jp/nanban/?id=1281,http://museo-anonimo.jp/nanban/tr/1281