2012-08-29 5 views
6

보스 7.1.1에, 우리가 SeamFaces @ViewScoped와 메모리 누수가 보인다. ViewScoped bean에서 메모리 누수가 발생합니까? 우리 <strong>JavaEE6</strong> 프로젝트 (<strong>EJB3</strong>,</strong><strong>JSF2)에서

우리는 사실을 확인하기 위해 약간의 프로토 타입을 만든 : 우리는 페이지를 200 번 호출하여 JMeter를 사용

  • 을;
  • 이 페이지는 stateful EJB를 삽입하는 viewscoped bean을 포함하고 호출합니다.
  • 1 분에 세션 시간 초과가 수정되었습니다.
우리가 무엇을 가지고 테스트, 우리가 여기 VisualVM과 함께 메모리의 내용을 확인하고의 끝에서

하십시오 @ViewScoped

  • , 우리는 여전히 상태 MyController 200 개 인스턴스를 얻을 - @PreDestroy 메서드는 호출되지 않습니다.
  • @ConversationScoped 콩, @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; 
    } 
} 

그리고 주입 된 상태 콩 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 managed @ViewScoped bean에서 위에서 언급 한 문제점에 직면 해 있습니다. 몇 블로그를 참조한 후에 JSF는 뷰 빈 상태를 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 쿠마르, 나는이 게시물이 꽤 오래되었음을 알고 있습니다. 하지만 제가 직면하고있는 것과 동일한 문제로 저를 인도하면 정말 도움이 될 것입니다. 공용 객체 get (String name, ObjectFactory objectFactory)을 재정의 할 수 없습니다. 메서드가 public TypeVariable 조회 (문자열 이름)입니다. JSF-API 2.1.3 버전을 사용하고 있습니다. 나를 도와주세요. –