为什么过期的@ViewScoped bean 在会话过期之前不会被销毁 [英] Why are expired @ViewScoped beans not destroyed until the session expires

查看:22
本文介绍了为什么过期的@ViewScoped bean 在会话过期之前不会被销毁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 GlassFish 4 和 Java 7 上使用 Mojarra 2.2.4.

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

我从 BalusC 对 的回答中了解到在JSF中@ViewScoped bean是如何以及何时被销毁的?,@ViewScoped bean应该在三种情况下被销毁:

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. 具有非空结果的回传
  2. 会话过期
  3. 超过会话中的最大逻辑视图数

我的 bean 在前两种情况下被销毁,但在超过最大逻辑视图数时不会.我已经验证了当超过最大值时 bean 会过期(我得到一个 ViewExpiredException),但它们仍然没有销毁,直到会话本身过期.

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.

出于内存消耗的原因,我希望在第三种情况下销毁 bean,特别是因为它们在过期后不可用.

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

  • 为什么 Bean 过期时没有销毁?
  • 这是错误还是预期行为?
  • 确保豆子被破坏的干净的解决方法是什么?
    • 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.

      这是我的豆子:

      @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";
          }
      }
      

      和我的 sandbox.xhtml:

      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>
      

      和我的 web.xml 的一部分:

      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>
      

      如果我刷新 sandbox.xhtml 50 次,我会在日志中得到 50 个 INFO: Constructing SandboxController 副本.无论刷新多少次,豆子都不会被破坏.VisualVM 确认这些 bean 仍然被 UIViewRoot 的 ViewMap 引用.在我的全尺寸 bean 中,它保持了相当多的状态,我很快得到一个 OutOfMemoryException.

      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.

      当我手动使会话过期时,我获得了 50 个 INFO: Destroying SandboxController 副本.

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

      如果我向 sandbox.xhtml 添加一个提交按钮并在 4 个不同的选项卡中加载它,然后尝试提交第一个,我得到一个 ViewExpiredException,正如预期的那样,但 bean 仍然没有被销毁.

      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.

      如果我改为使用 javax.faces.bean.ManagedBean 和 javax.faces.view.ViewScoped 注释,则行为是相同的.但是,OmniFaces 注释 org.omnifaces.cdi.ViewScoped 可以正常工作.

      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.

      我的@ViewScoped bean 正在在会话到期时被销毁,这与 链接的 ViewScoped bean 导致内存泄漏

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

      问为什么每个 bean 没有在后续刷新时立即销毁,如此处所质疑:JSF 2.1 ViewScopedBean @PreDestroy 方法未被调用.我想知道为什么即使它们过期了,不再有用,它们仍然没有被销毁,从而继续消耗内存.

      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.

      推荐答案

      我能够通过使用 OmniFaces @ViewScoped 注释 (org.omnifaces.cdi.ViewScoped) 找到一个干净的解决方法而不是标准的@ViewScoped (javax.faces.view.ViewScoped).

      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).

      OmniFaces ViewScoped 会在 bean 过期后立即正确销毁它们.

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

      请参阅此处了解更多详情:http://showcase.omnifaces.org/cdi/ViewScoped

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

      这篇关于为什么过期的@ViewScoped bean 在会话过期之前不会被销毁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆