Why are expired @ViewScoped beans not destroyed until the session expires

故事扮演 提交于 2019-11-26 21:50:40

问题


I'm using Mojarra 2.2.4 on GlassFish 4 with Java 7.

As I understand from BalusC's answer to How and when is a @ViewScoped bean destroyed in JSF?, @ViewScoped beans should be destroyed in three cases:

  1. Post-back with non-null outcome
  2. Session expiration
  3. Maximum number of logical views in session exceeded

My beans are being destroyed in the first two cases, but not when the maximum number of logical views is exceeded. I have verified that the beans do expire when the maximum is exceeded (I get a ViewExpiredException), but they are still not destroyed until the session itself expires.

For memory consumption reasons, I would like to have the beans destroyed in this third case, especially since they are not usable after expiration.

Questions

  • Why are the beans not destroyed when they expire?
  • Is this a bug or expected behavior?
  • What would be a clean work-around to make sure the beans get destroyed?
    • Update: OmniFaces ViewScoped annotation destroys beans as soon as they expire.

Minimal Example

Here is my bean:

@javax.inject.Named("sandboxController")
@javax.faces.view.ViewScoped
public class SandboxController implements Serializable {
    private static final Logger log = Logger.getLogger(SandboxController.class.getName());
    @PostConstruct
    public void postConstruct() {
        log.log(Level.INFO, "Constructing SandboxController");
    }
    @PreDestroy
    public void preDestroy() {
        log.log(Level.INFO, "Destroying SandboxController");
    }
    public String getData() {
        return "abcdefg";
    }
}

and my sandbox.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>
<!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:h="http://xmlns.jcp.org/jsf/html">
    <body>
        <h:form>
            <h:outputText value="#{sandboxController.data}"/>
        </h:form>
    </body>
</html>

and part of my web.xml:

<context-param>  
    <param-name>com.sun.faces.numberOfLogicalViews</param-name>
    <param-value>3</param-value>
</context-param>
<context-param>  
    <param-name>com.sun.faces.numberOfViewsInSession</param-name>  
    <param-value>3</param-value>
</context-param>

If I refresh the sandbox.xhtml 50 times, I get 50 copies of INFO: Constructing SandboxController in the log. The beans are not destroyed, regardless of how many times I refresh. VisualVM confirms that the beans are still referenced by the UIViewRoot's ViewMap. In my full-size bean, which maintains a fair bit of state, I quickly get an OutOfMemoryException.

When I manually expire the session, I get 50 copies of INFO: Destroying SandboxController.

If I add a submit button to sandbox.xhtml and load it up in 4 different tabs, then try to submit the first one, I get a ViewExpiredException, as expected, but the bean is still not destroyed.

The behavior is the same if I instead use the javax.faces.bean.ManagedBean and javax.faces.view.ViewScoped annotations. However, the OmniFaces annotation org.omnifaces.cdi.ViewScoped works properly.

To clarify...

My @ViewScoped beans are being destroyed on session expiration, unlike problems described in related questions such as Linked ViewScoped beans lead to memory leaks

I am not asking why each bean is not destroyed immediately on subsequent refresh as questioned here: JSF 2.1 ViewScopedBean @PreDestroy method is not called. I want to know why it is that even when they expire, and are no longer useful, they are still not destroyed, and thus continue consuming memory.


回答1:


I was able to find a clean work-around by using the OmniFaces @ViewScoped annotation (org.omnifaces.cdi.ViewScoped) instead of the standard @ViewScoped (javax.faces.view.ViewScoped).

The OmniFaces ViewScoped correctly destroys the beans as soon as they expire.

See here for more details: http://showcase.omnifaces.org/cdi/ViewScoped



来源:https://stackoverflow.com/questions/20930396/why-are-expired-viewscoped-beans-not-destroyed-until-the-session-expires

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!