2016-08-18 39 views
2

JSF 2.2 + PrimeFaces対応アプリケーションでSPAアプローチを使用しています。 基本的な考え方は、もともと非常によくここに記載された:豆を@ViewScoped使用するときに我々が知っているように、このSPAのアプローチを使用して、SPA JSF 2.2アプリケーションで@ViewScoped Beanを削除する

Refreshing dynamic content with AJAX in JSF using SPA approach

しかし、欠点があります。

実際には常に同じJSFビューにとどまっているため、パネルグループのコンテンツを新しいSPAコンテンツで置き換えると、@ViewScoped Beanはメモリから削除されません。

私は解決策を見つけましたが、正しいアプローチであるか、欠落しているかどうかを知りたいと思います。新しいSPA後、

private void clearViewScopedBeans() { 
    Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap(); 
    for(Iterator<Map.Entry<String, Object>> it = viewMap.entrySet().iterator(); it.hasNext();) { 
     Map.Entry<String, Object> entry = it.next(); 
     it.remove();  
    } 
} 

これはそれを確認する必要があります:

基本的には、SPA AJAX要求中にレンダリングされるページの名前を保持している当社のNavigationService豆、に、私たちは常に次のコードを実行しますスニペットがレンダリングされると、以前のすべての既存の@ViewScoped Beanが削除されます。

しかし、上記のコードでは、View Scoped Beanのみが削除されますが、関連するView Statesは削除されないと思います。あれは正しいですか ?

私はもう少しロジックを行うように見える古いブログエントリが見つかりました: http://javaevangelist.blogspot.sg/2014/08/jsf-21-tip-of-day-clearing-viewscope.html

を、それが同様に正確だ場合、私は知りません。

実行している場合:私たちは現在のSPAスニペットページ名を保持し、私たちのNavigationService Beanを複数のウィンドウタブをサポートしたい場合はまた、同様@ViewScoped、これは小さな問題を紹介しなければならない

既存の@ViewScoped Beanをすべて削除するためのコードです... NavigationService Bean自体を除外する必要があります。そうしないと、新しいページの代わりにデフォルトのSPAページ名を使用してNavigationServiceの新しいインスタンスがインスタンス化されるため、常に同じページがロードされてしまいます。

私たちのコードは最終的にはこのようになります。ここでは、SPAページの更新時に削除したくない「除外された」ビーン名のマップを保持しています(SPAを保持するNavigationService beanページ名)

private void clearViewScopedBeans() { 
    Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap(); 
    for(Iterator<Map.Entry<String, Object>> it = viewMap.entrySet().iterator(); it.hasNext();) { 
     Map.Entry<String, Object> entry = it.next(); 
     if(!exclusionViewScopedBeans.contains(entry.getKey())) { 
      logger.info("Removing an instance of a @ViewScoped bean -> " + entry.getKey()); 
     it.remove(); 
     } 
    } 
} 

今すぐ質問... これはSPAの状況のこれらの種類を処理するための正しいアプローチですか?ここに何か不足していますか?

フィードバックは非常に高く評価されるでしょう...事前に多くのおかげで!私が思う

+1

これは私が使用した実装です - 正しいアプローチの点で私はJSFでこのようなことを避けるべきですが、現実は時々必要です – farrellmr

+0

対話スコープのBeanを使用しないのはなぜですか? – Kukeltje

+0

この特定のプロジェクトでは、CDIの代わりにSpring IoCが使用されているため、組み込みの会話スコープは現在のところありません。しかし、これまでのところ、私はPrimeFaces TabViewコンポーネント用のTabScopeを作成しました。それぞれのTabは独自のJSF Beanスコープを持つことができますが、タブの作成時に作成され、タブが閉じられたときに破棄されます。同じアプローチを使用してより一般的な会話スコープを作成することができますね... –

答えて

0

は、あなたMaikelよりも、SPA(シングルページアプリ)でViewScopedBeansをクリアする/削除するためのよりよい解決策はありません。

private void clearViewScopedBeans() { 
Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap(); 
for(Iterator<Map.Entry<String, Object>> it = viewMap.entrySet().iterator(); it.hasNext();) { 
    Map.Entry<String, Object> entry = it.next(); 
    it.remove();  
} 
} 

私は多くのことを見つける試してみましたが、SPAは「公式推奨」ではありませんJSFを使用する方法、つまりマルチページアプリなので、SPAはより多くの手間を必要とします。

または、Maikel、あなたは何か別の方法を見つけましたか?

+0

SPAはあくまでも非推奨の方法ではありません。それは特定のビューに関連しています**あなたはビュースコープのビーンズを「乱用する」のではなく、より簡単にコントロールできる他のスコープ付きビーンズを使うことができます(そして、あなたはそれをこのように解決します)。 – Kukeltje

+0

こんにちはRadekとKukeltje。これまでのところ、私たちが使っているアプローチであり、サーバー側に関してはうまくいきます。最後に最大の問題はクライアント側で、多くのPrimeFaces jQuery UIウィジェットはそうではありませんでした完全にSPA対応、大きなメモリリークを引き起こします。新しいビューに移動する前に、各SPAページ上のすべてのPFウィジェットをループし、特定のPFウィジェット、およびその他のトリッキーなシナリオ(ポーリング、アイドルタイマー、キーバインディングを無効にする)のイベントを手動でバインド解除する必要があります。しかし、これまでのところ、PrimeFacesとSPAのアプローチでJSF 2.2を使用しており、大きな問題は発生していないと言えます。 –

+0

こんにちはMaikel(とKukeltje) - あなたの経験とオプションに感謝します。私はこのSPAのアプローチが現実世界で働いていることを嬉しく思います。私たちはViewScopedBean(これは、標準のJSF 2.3のViewScopedBeanとは異なり、POST/GETリクエストごとに破棄されます)でOmnifaces(以前はTomcatのCDIを取り入れていました)を使い始めました。 SPAのアプローチでOmnifaces/ViewScopedBeanを使用する可能性があります。私はそれが良い選択であることを願っています。 – Radek

関連する問題