これは正しくないようです。コードのクリーンアップを行っていたところ、これに気づきました。すべてのajaxリクエストは、コンストラクターと@PostConstruct
Beanの@ViewScoped
を起動しています。単純なデータベースのページ付けでさえ、それを起動しています。
I 理解@ViewScoped
は@RequestScoped
よりも長く、リクエストごとに再構築するべきではないこと。 GETによるページの完全なリロード後にのみ。
つまり、@ViewScoped
Beanは@RequestScoped
Beanのように動作します。ポストバックリクエストごとに最初から再作成されています。これには多くの考えられる原因がありますが、そのほとんどは、関連付けられたJSFビューがJSF状態で使用できなくなり、デフォルトでHTTPセッションに関連付けられていることです。
HTTPセッション自体が問題の根本原因ではないことを確認できる場合、つまり@SessionScoped
が完全に正常に機能する場合は、以下の考えられる原因のリストを確認してください。それ以外の場合、HTTPセッション自体も破棄され、すべてのリクエストで再作成される場合は、一歩下がってセッションcookieとサーバー構成を確認する必要があります。壊れたHTTPセッションに関連する原因は、少なくともJSFのコンテキストを超えています。
Mojarra 2.1.17以前を使用しており、ビューには、ビュースコープのBeanプロパティを ビュービルド時間 の間に評価されるタグ属性にバインドするEL式が含まれています。例としては、JSTL <c:if>
、<c:forEach>
など、またはJSF <ui:include>
、<x:someComponent id="#{...}"
、<x:someComponent binding="#{...}">
などがあります。これは、Mojarraのバグが原因です( issue 1492 )。参照 Beanが@ViewScopedであるのに@PostConstructコールバックが毎回起動するのはなぜですか?JSF
これは、Mojarraバージョン2.1.18ですでに修正されています。新しいバージョンにアップグレードできない場合の回避策は、以下のweb.xml
で部分的な状態保存を無効にすることです。 JSF2 FaceletsのJSTL ...意味がありますか? も参照してください。
<context-param>
<param-name>javax.faces.PARTIAL_STATE_SAVING</param-name>
<param-value>false</param-value>
</context-param>
または、特定のJSFビューのセットのみをターゲットにする場合:
<context-param>
<param-name>javax.faces.FULL_STATE_SAVING_VIEW_IDS</param-name>
<param-value>/foo.xhtml;/bar.xhtml;/folder/baz.xhtml</param-value>
</context-param>
言及することが重要なのは、JSFコンポーネントのid
またはbinding
属性の値をビュースコープのBeanプロパティにバインドすることは悪い習慣であるということです。それらは実際にはリクエストスコープのBeanプロパティにバインドする必要があります。そうでない場合は、別のプロパティを探す必要があります。参照 JSFで「バインディング」属性はどのように機能しますか?いつどのように使用する必要がありますか?
Mojarra 2.2.0を使用していますが、そのバージョンのみに、2.2.1ですでに修正されているビュースコープの維持に(まだ不明な)バグがあります。 問題2912 も参照してください。解決策は、新しいバージョンにアップグレードすることです。
@ViewScoped
アノテーションが間違ったパッケージからインポートされています。 JSFは、2つの@ViewScoped
アノテーションを提供します。1つはjavax.faces.bean
でアノテーションが付けられたJSFマネージドBean用の@ManagedBean
パッケージから、もう1つはjavax.faces.view
でアノテーションが付けられたCDIマネージドBean用の@Named
パッケージからです。 BeanスコープアノテーションがBean管理アノテーションと一致しない場合、実際のBeanスコープはBean管理フレームワークのデフォルトスコープになります。これは、JSF管理対象Beanでは@RequestScoped
、CDI管理対象Beanでは@Dependent
です。
次の構成のいずれかがあり、それらを混在させないようにする必要があります。 JSF 2.2を使用する場合、ポストバック要求ごとに@ViewScoped Beanが再作成されます も参照してください。
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
@ManagedBean
@ViewScoped
public class CorrectJSFViewScopedBean implements Serializable {
import javax.inject.Named;
import javax.faces.view.ViewScoped;
@Named
@ViewScoped
public class CorrectCDIViewScopedBean implements Serializable {
ビューは(偶然に?)<f:view transient="true">
を介して一時的なものとしてマークされます。これにより、基本的に「ステートレスJSF」がオンになります。これは、Mojarra2.1.19以降の新機能です。これにより、JSFビューはJSF状態で保存されなくなり、論理的な結果として、参照されているすべてのビュースコープのBeanをJSFビューに関連付けることができなくなります。も参照してください JSFでのステートレスの有用性は何ですか?
Webアプリケーションは、true
を「回避」しようとする誤った試みで、com.Sun.faces.enableRestoreView11Compatibility
contextparamをViewExpiredException
に設定して構成されています。このコンテキストパラメータを使用すると、ViewExpiredException
がスローされることはありませんが、ビュー(および関連するすべてのビュースコープのBean)は最初から再作成されます。ただし、それがすべてのリクエストで発生する場合、このアプローチは実際には別の問題を隠します。ビューの有効期限が早すぎるということです。これは、JSFビューステートやHTTPセッションの維持に問題がある可能性があることを示しています。それを適切に解決/構成する方法は、 javax.faces.application.ViewExpiredException:ビューを復元できませんでした に進んでください。
Webアプリケーションのランタイムクラスパスは、複数の異なるバージョンのJSFAPIまたはimpl関連クラスで汚染されています。これにより、JSFビューステートの識別子/マーカーに破損/不一致が発生します。 webappの/WEB-INF/lib
に複数のJSFAPIJARファイルがないことを確認する必要があります。 Mavenを使用している場合は、サーバーが提供するライブラリを<scope>provided</scope>
としてマークするように注意してください。 JSF wikiページ の「JSFのインストール」セクションおよびこの関連する質問への回答も参照してください: Mavenを介してJSFライブラリを適切にインストールおよび構成する方法 。
PrimeFaces <p:dialog>
を使用している場合は、<p:dialog>
に独自の<h:form>
があり、別の<h:form>
にネストされていないことを確認してください。 p:dialog内のp:fileUploadが@ViewScoped値を失う も参照してください。
PrimeFaces FileUploadFilter
をPrettyFacesと組み合わせる場合は、FileUploadFilter
がPrettyFacesで書き換え/転送されたリクエストでも実行されることを確認してください。参照 FileUploadListenerがPrettyFacesを使用して呼び出されたときに再構築されたViewScoped Bean および PrimeFaces p:fileUploadの使用方法?リスナーメソッドが呼び出されないか、UploadedFileがnull /エラーをスローする/使用できない 。
PrettyFacesを使用している場合、CSS/JS /画像リソースを@ViewScoped
Beanに関連付けられたJSFページにリダイレクトする不適切に構成された書き換えルールも誤解を招く動作を引き起こします。参照 CDI ViewScope&PrettyFaces:@PostConstruct(JSF 2.2)への複数の呼び出し 。