1年半ほど前にブログで、ViewExpiredExceptionに苦しんだ記録をまとめましたが、再度、似たようなトラブルに直面してしまいました。
タイトルがその原因だったわけですが、この問題についてもまとめておこうと思います。
STATE_SAVING_METHODについて
JavaEE7のWebアプリケーションでは、STATE_SAVING_METHODの設定で、クライアントごとのView情報をどこで保管するかを管理します。
デフォルトでは、serverになっており、Viewの数も15と少な目に設定されています。(下記の設定は、定義しなくてもデフォルトで反映されます)
<context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>sever</param-value> </context-param> <context-param> <param-name>com.sun.faces.numberOfViewsInSession</param-name> <param-value>15</param-value> </context-param> <context-param> <param-name>com.sun.faces.numberOfLogicalViews</param-name> <param-value>15</param-value> </context-param>
前回、JavaEEアプリの設定(web.xml)で、「javax.faces.STATE_SAVING_METHOD」を「server」から「client」に変更することで、view情報保持数の制限がなくなりました。(ただし、セキュリティ的に危険な状態の設定ではあります。)
今回のトラブル内容
今回起きたトラブルは、STATE_SAVING_METHODを「client」にしているのも関わらず、数ヵ月に1~2回、view情報が消失してしまうというもの。
テスト機で再現させようとトライするも、なかなか発生せず・・・。いったい何故???
ユーザー側にも、きちんとした原因を説明することができず、もどかしい状態が続いておりました。
ちなみに、利用しているソフトウェア構成は下記の通りです。
ソフトウェア構成
- JavaEE7(Payara 4.1.1.154)
- JSF2.2
- Primefaces5.3
原因発見
かなり、困惑させられましたが、PrimeFacesの「Dialog Framework」で作成した検索画面を25回連続で呼び出して、呼び出し元画面に戻ってきたときに、呼び出し元画面のView Scope情報が消失されました!
stackoverflowでも、下記の記事を発見することができ、25画面情報だけが保持されているという仮説が正しいことを確認しました。
では、なぜ「Dialog Framework」が1画面扱いでカウントされてしまうのか?
PrimeFacesのDialog Frameworkでは、基本的にiframe(HTMLのタグの一つで、Webページ内に矩形の領域を設け別のページなどを読み込んで表示する)タグの中で他のビューを見せているようで、それ自身のviewスコープを持っています。
Dialog Framework画面で、特定のモデルを選択しても、Close扱いでDialogを終わらせても、結果的にはDialog Frameworkのview情報が残ってしまいます。
セッションタイムが終了したタイミングで、viewも合わせて消失されます。ということは、セッションが生きている間、view情報が生きていることになります。どんだけ~♪
「Dialog Framework」を初めて知ったときには、これで疎結合にシンプルな開発が実現できるぞ!と思っておったのですが、こういう問題が潜伏していたとは!(ただし、こういう部分をきちんと事前検証・調査しておくことが、自分のミッションではありました。。。反省!)
改善策
この辺のサイトを確認しますと、デフォルトで「p:dialog」を推奨するとありました。 「p:dialog」では呼び出し元ページと同じview scope内に存在するので、view数を食いつぶしてしまうことはなくなりそうです。
ただし、現時点で大量の「Dialog Framework」のviewを作成しており、ひとつずつ、複合コンポーネント化するなどして、各種検索画面を「p:dialog」へ切り替えていく必要がありそうです。
また、view情報の保持する設定を拡張できないかと調査したのですが、こちらの情報はJSF2.2では設定不可っぽいのです。
次回のJSF2.3では反映されるでしょうか。
[JAVASERVERFACES-4015] Provide documentation and tuning options for activeViewMaps - Java.net JIRA
いずれにしましても、1人が25画面も同時に別タブで使うことなどありえませんので、やはりコツコツと「p:dialog」へ移行していくほうが最善策かと思っております。
今回は、かなり骨が折れましたが、原因がわかって、かなりスッキリできました!