2012-08-29 12 views
6

のJBoss 7.1.1に、我々がSeamFaces @ViewScopedとメモリリークを持っているようです。ViewScoped Beanでメモリリークが発生しましたか?私たちの<strong>JavaEE6</strong>プロジェクト(<strong>EJB3</strong>、</strong><strong>JSF2)で

我々は事実を確認するために少しのプロトタイプを作った:

  • 我々はページ200回を呼び出すためのJMeterを使用します。
  • このページには、ステートフルEJBを注入するビュースコープのBeanが含まれています。
  • セッションタイムアウトを1分で修正しました。テストの終わりに

、我々は我々が得たもの、ここでVisualVMのとメモリの内容を確認し、そして:

  • @ViewScoped豆で、我々はまだ、ステートフルMyControllerの200のインスタンスを取得します - @PreDestroyメソッドは呼び出されません。
  • @ConversationScoped bean、@preDestroyメソッドはセッション終了と呼ばれ、クリーンメモリを取得します。

ビュースコープを悪く使用していますか、それとも本当にバグですか?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:f="http://java.sun.com/jsf/core" 
    xmlns:h="http://java.sun.com/jsf/html" 
    xmlns:ui="http://java.sun.com/jsf/facelets" 
    xmlns:s="http://jboss.org/seam/faces"> 
    <f:metadata> 
     <f:viewParam name="u" value="#{myBean.uselessParam}" /> 
     <s:viewAction action="#{myBean.callService}" /> 
    </f:metadata> 
    <h:body > 
     <f:view> 
     </f:view> 
    </h:body>  
</html> 

今含ま豆myBean


はここでXHTMLページです。 @ConversationScopedバリアントの場合、すべてのコメント部分のコメントは解除されます。

@ViewScoped 
// @ConversationScoped 
@Named 
public class MyBean implements Serializable 
{ 
    @Inject 
    MyController myController; 
    //@Inject 
    //Conversation conversation; 

    private String uselessParam; 

    public void callService() 
    { 
     //if(conversation.isTransient()) 
     //{ 
     //   conversation.begin(); 
     //} 
     myController.call(); 
    } 

    public String getUselessParam() 
    { 
     return uselessParam; 
    } 

    public void setUselessParam(String uselessParam) 
    { 
     this.uselessParam = uselessParam; 
    } 
} 

そして、注入されたステートフルBean MyController

@Stateful 
@LocalBean 
public class MyController 
{ 
    public void call() 
    { 
     System.out.println("call "); 
    } 

    @PreDestroy 
    public void destroy() 
    { 
     System.out.println("Destroy"); 
    } 
} 

答えて

5

多くの開発者がMyface CODIで@ViewAccessScopedに満足しています。 フィードバックをお寄せください。

+2

私たちはCODIで試してみましたが、テストは順調でした。ニース! –

3

チャンスは、これはバグです。正直なところ、Seam 3の実装はそれほど素晴らしいものではなく、CODI(そしてDeltaSpikeに含まれるもの)はずっと優れています。

5

JSFマネージド@ViewScoped beanで上記の問題が発生しました。いくつかのブログを参照した後、私はJSFがビューのBeanの状態をhttpセッションに保存し、セッションが無効になったときにのみ破棄されることを理解しました。ページで参照される新しいビュースコープBeanが作成されるたびに、jsfページをクリックするたびに私はSpring Custom View Scopeを使用して作業を行いました。それはうまく動作します。以下は詳細コードです。 JSF 2.1の場合

ステップ1:次のようにリスナーを構築ビュースコープビーンポストを作成します。

public class ViewScopeBeanConstructListener implements ViewMapListener { 

    @SuppressWarnings("unchecked") 
    @Override 
    public void processEvent(SystemEvent event) throws AbortProcessingException { 
     if (event instanceof PostConstructViewMapEvent) { 
      PostConstructViewMapEvent viewMapEvent = (PostConstructViewMapEvent) event; 
      UIViewRoot viewRoot = (UIViewRoot) viewMapEvent.getComponent(); 
      List<Map<String, Object>> activeViews = (List<Map<String, Object>>) 
       FacesContext.getCurrentInstance().getExternalContext().getSessionMap(). get("com.org.jsf.activeViewMaps"); 
      if (activeViews == null) { 
       activeViews = new ArrayList<Map<String, Object>>(); 
       activeViews.add(viewRoot.getViewMap()); 
       FacesContext.getCurrentInstance().getExternalContext().getSessionMap(). put("com.org.jsf.activeViewMaps", activeViews); 
      } else { 
       activeViews.add(viewRoot.getViewMap()); 
      } 
     } 
    } 

ステップ2:faces-configにイベントリスナーを登録します。xml

<system-event-listener> 
    <system-event-listener-class> 
     com.org.framework.custom.scope.ViewScopeBeanConstructListener 
    </system-event-listener-class> 
    <system-event-class>javax.faces.event.PostConstructViewMapEvent</system-event-class> 
    <source-class>javax.faces.component.UIViewRoot</source-class> 
</system-event-listener> 

手順3:次のようにカスタムビュースコープBeanを作成します。

public class ViewScope implements Scope { 

    @Override 
    public Object get(String name, ObjectFactory objectFactory) { 
     Map<String, Object> viewMap = FacesContext.getCurrentInstance().getViewRoot().getViewMap(); 
      if (viewMap.containsKey(name)) { 
        return viewMap.get(name); 
      } else { 
       List<Map<String, Object>> activeViewMaps = (List<Map<String, Object>>) 
       FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("com.org.jsf.activeViewMaps"); 
       if (activeViewMaps != null && !activeViewMaps.isEmpty() 
        && activeViewMaps.size() > 1) { 
         Iterator iterator = activeViewMaps.iterator(); 
        if (iterator.hasNext()) { 
          Map<String, Object> oldViewMap = (Map<String, Object>) 
          iterator.next(); 
          oldViewMap.clear(); 
          iterator.remove(); 
        } 
        } 
       Object object = objectFactory.getObject(); 
       viewMap.put(name, object); 
       return object; 
      } 

    } 

注:他のオーバーライドされたメソッドは空にすることができます。 JSF 2.2の場合

JSF 2.2は、キーとして 'com.Sun.faces.application.view.activeViewMaps' でHTTPセッション中にナビゲートビューマップを保存します。以下のコードをSpring Custom View Scopeに追加してください。 JSF 2.1のようなリスナーは必要ありません

public class ViewScope implements Scope { 

    public Object get(String name, ObjectFactory objectFactory) { 
     Map<String, Object> viewMap = 
      FacesContext.getCurrentInstance().getViewRoot().getViewMap(); 
       if (viewMap.containsKey(name)) { 
        return viewMap.get(name); 
       } else { 
         LRUMap lruMap = (LRUMap) FacesContext.getCurrentInstance(). 
    getExternalContext().getSessionMap().get("com.sun.faces.application.view.activeViewMaps"); 
       if (lruMap != null && !lruMap.isEmpty() && lruMap.size() > 1) { 
        Iterator itr = lruMap.entrySet().iterator(); 
        while (itr.hasNext()) {//Not req 
        Entry entry = (Entry) itr.next(); 
        Map<String, Object> map = (Map<String, Object>) entry.getValue(); 
        map.clear(); 
        itr.remove(); 
        break; 
        } 
       } 
       Object object = objectFactory.getObject(); 
       viewMap.put(name, object); 
       return object; 
     } 
} 
+0

LRUMapなどのインポートをコード内で共有できますか?多くのインポートオプションがありますが、現時点では失敗しています。 – user1746582

+0

こんにちは@ Sathishクマール、私は知っているそれはかなり古いこのポストです。しかし、私が直面しているのと同じ問題で私を導くなら、本当に役に立ちます。私はパブリックObject get(String name、ObjectFactory objectFactory)をオーバーライドできません。私はメソッドがパブリックTypeVariable ルックアップ(文字列名)を取得しています。 私はJSF-APIバージョン2.1.3を使用しています。 私を助けてください。 –

関連する問題

 関連する問題