javaserverfaces
  1. javaserverfaces
  2. JAVASERVERFACES-2561

Implement requirements for @PreDestroy invocation upon session expiration on @ViewScoped managed beans

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 2.0, 2.1
    • Fix Version/s: 2.1.16, 2.2.0-m07
    • Component/s: lifecycle
    • Labels:
      None

      Description

      See JAVASERVERFACES_SPEC_PUBLIC-905. Particularly see the new specification content in javax.faces.bean.ViewScoped.

      1. 20121026-0924-i_spec_905.patch
        49 kB
        Ed Burns
      2. changebundle.txt
        47 kB
        Manfred Riem

        Issue Links

          Activity

          Hide
          Ed Burns added a comment -

          Stan said

          We're also getting reports of memory leaks with view-scoped beans. I've verified the leak, but not traced its exact cause. I'm assuming that the leak is related to this issue.

          Any opinion on that or insight into how the instances are referenced? I'm assuming that if view-scoped beans aren't eligible for GC when the session ends then they must be tied to application scope or to a ThreadLocal. Any other possibilities?

          After partially implementing this, I can see where a leak happens, and I believe it will be fixed by this issue.

          Show
          Ed Burns added a comment - Stan said We're also getting reports of memory leaks with view-scoped beans. I've verified the leak, but not traced its exact cause. I'm assuming that the leak is related to this issue. Any opinion on that or insight into how the instances are referenced? I'm assuming that if view-scoped beans aren't eligible for GC when the session ends then they must be tied to application scope or to a ThreadLocal. Any other possibilities? After partially implementing this, I can see where a leak happens, and I believe it will be fixed by this issue.
          Hide
          ssilvert added a comment - - edited

          The patch does fix the leak, but it can produce a NPE if the session has been invalidated and then it later times out.

          BeanManager.getViewRootsWithViewScopedBeansDirectlyFromSession() doesn't take into account that httpSession.getAttribute() can return null. Just add a finally block like this:

             public static List<UIViewRoot> getViewRootsWithViewScopedBeansDirectlyFromSession(HttpSession httpSession) {
                   List<UIViewRoot>  result = null;
                   try {
                       result = (List<UIViewRoot>)httpSession.getAttribute(VIEWROOTS_WITH_VIEWSCOPED_BEANS_KEY);
                   } catch (IllegalStateException ise) {
                       if (LOGGER.isLoggable(Level.FINEST)) {
                           LOGGER.log(Level.FINEST, "Unable to obtain list of ViewScoped beans for clean up on session expiration", ise);
                       }
                   } finally {
                       if (result == null) {
                           result = Collections.emptyList();
                       }
                   }
                   return result;
               } 
          
          Show
          ssilvert added a comment - - edited The patch does fix the leak, but it can produce a NPE if the session has been invalidated and then it later times out. BeanManager.getViewRootsWithViewScopedBeansDirectlyFromSession() doesn't take into account that httpSession.getAttribute() can return null. Just add a finally block like this: public static List<UIViewRoot> getViewRootsWithViewScopedBeansDirectlyFromSession(HttpSession httpSession) { List<UIViewRoot> result = null ; try { result = (List<UIViewRoot>)httpSession.getAttribute(VIEWROOTS_WITH_VIEWSCOPED_BEANS_KEY); } catch (IllegalStateException ise) { if (LOGGER.isLoggable(Level.FINEST)) { LOGGER.log(Level.FINEST, "Unable to obtain list of ViewScoped beans for clean up on session expiration" , ise); } } finally { if (result == null ) { result = Collections.emptyList(); } } return result; }
          Hide
          Manfred Riem added a comment -

          Applied to 2.1 branch,

          svn commit -m "Fixed http://java.net/jira/browse/JAVASERVERFACES-2561, r=rogerk, push the ViewScope into the session, maintained by the JSF runtime, so it properly calls the constructor, @PostConstruct and @PreDestroy all only once."
          Sending jsf-api\src\main\java\javax\faces\component\UIViewRoot.java
          Sending jsf-ri\src\main\java\com\sun\faces\application\WebappLifecycleListener.java
          Sending test\agnostic\pom.xml
          Adding test\agnostic\scope
          Adding test\agnostic\scope\pom.xml
          Adding test\agnostic\scope\view
          Adding test\agnostic\scope\view\pom.xml
          Adding test\agnostic\scope\view\src
          Adding test\agnostic\scope\view\src\main
          Adding test\agnostic\scope\view\src\main\java
          Adding test\agnostic\scope\view\src\main\java\com
          Adding test\agnostic\scope\view\src\main\java\com\sun
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\ConstructorBean.java
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\InvalidatedBean.java
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\NavigateAwayBean.java
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\NavigateBean.java
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\PostConstructBean.java
          Adding test\agnostic\scope\view\src\main\resources
          Adding test\agnostic\scope\view\src\main\webapp
          Adding test\agnostic\scope\view\src\main\webapp\WEB-INF
          Adding test\agnostic\scope\view\src\main\webapp\WEB-INF\glassfish-web.xml
          Adding test\agnostic\scope\view\src\main\webapp\WEB-INF\web.xml
          Adding test\agnostic\scope\view\src\main\webapp\constructor.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\invalidatedPerform.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\invalidatedSession.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\invalidatedVerify.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\navigate.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\navigateAway.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\navigatedAway.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\postconstruct.xhtml
          Adding test\agnostic\scope\view\src\test
          Adding test\agnostic\scope\view\src\test\java
          Adding test\agnostic\scope\view\src\test\java\com
          Adding test\agnostic\scope\view\src\test\java\com\sun
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope\view
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope\view\Issue2561IT.java
          Transmitting file data .....................
          Committed revision 11050.

          Show
          Manfred Riem added a comment - Applied to 2.1 branch, svn commit -m "Fixed http://java.net/jira/browse/JAVASERVERFACES-2561 , r=rogerk, push the ViewScope into the session, maintained by the JSF runtime, so it properly calls the constructor, @PostConstruct and @PreDestroy all only once." Sending jsf-api\src\main\java\javax\faces\component\UIViewRoot.java Sending jsf-ri\src\main\java\com\sun\faces\application\WebappLifecycleListener.java Sending test\agnostic\pom.xml Adding test\agnostic\scope Adding test\agnostic\scope\pom.xml Adding test\agnostic\scope\view Adding test\agnostic\scope\view\pom.xml Adding test\agnostic\scope\view\src Adding test\agnostic\scope\view\src\main Adding test\agnostic\scope\view\src\main\java Adding test\agnostic\scope\view\src\main\java\com Adding test\agnostic\scope\view\src\main\java\com\sun Adding test\agnostic\scope\view\src\main\java\com\sun\faces Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\ConstructorBean.java Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\InvalidatedBean.java Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\NavigateAwayBean.java Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\NavigateBean.java Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\PostConstructBean.java Adding test\agnostic\scope\view\src\main\resources Adding test\agnostic\scope\view\src\main\webapp Adding test\agnostic\scope\view\src\main\webapp\WEB-INF Adding test\agnostic\scope\view\src\main\webapp\WEB-INF\glassfish-web.xml Adding test\agnostic\scope\view\src\main\webapp\WEB-INF\web.xml Adding test\agnostic\scope\view\src\main\webapp\constructor.xhtml Adding test\agnostic\scope\view\src\main\webapp\invalidatedPerform.xhtml Adding test\agnostic\scope\view\src\main\webapp\invalidatedSession.xhtml Adding test\agnostic\scope\view\src\main\webapp\invalidatedVerify.xhtml Adding test\agnostic\scope\view\src\main\webapp\navigate.xhtml Adding test\agnostic\scope\view\src\main\webapp\navigateAway.xhtml Adding test\agnostic\scope\view\src\main\webapp\navigatedAway.xhtml Adding test\agnostic\scope\view\src\main\webapp\postconstruct.xhtml Adding test\agnostic\scope\view\src\test Adding test\agnostic\scope\view\src\test\java Adding test\agnostic\scope\view\src\test\java\com Adding test\agnostic\scope\view\src\test\java\com\sun Adding test\agnostic\scope\view\src\test\java\com\sun\faces Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope\view Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope\view\Issue2561IT.java Transmitting file data ..................... Committed revision 11050.
          Hide
          Manfred Riem added a comment -

          Applied to 2.2 trunk,

          svn commit -m "Fixed http://java.net/jira/browse/JAVASERVERFACES-2561, r=rogerk, push the ViewScope into the session, maintained by the JSF runtime, so it properly calls the constructor, @PostConstruct and @PreDestroy all only once."
          Sending jsf-api\src\main\java\javax\faces\component\UIViewRoot.java
          Sending jsf-ri\src\main\java\com\sun\faces\application\WebappLifecycleListener.java
          Sending test\agnostic\pom.xml
          Adding test\agnostic\scope
          Adding test\agnostic\scope\pom.xml
          Adding test\agnostic\scope\view
          Adding test\agnostic\scope\view\pom.xml
          Adding test\agnostic\scope\view\src
          Adding test\agnostic\scope\view\src\main
          Adding test\agnostic\scope\view\src\main\java
          Adding test\agnostic\scope\view\src\main\java\com
          Adding test\agnostic\scope\view\src\main\java\com\sun
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\ConstructorBean.java
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\InvalidatedBean.java
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\NavigateAwayBean.java
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\NavigateBean.java
          Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\PostConstructBean.java
          Adding test\agnostic\scope\view\src\main\webapp
          Adding test\agnostic\scope\view\src\main\webapp\WEB-INF
          Adding test\agnostic\scope\view\src\main\webapp\WEB-INF\glassfish-web.xml
          Adding test\agnostic\scope\view\src\main\webapp\WEB-INF\web.xml
          Adding test\agnostic\scope\view\src\main\webapp\constructor.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\invalidatedPerform.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\invalidatedSession.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\invalidatedVerify.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\navigate.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\navigateAway.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\navigatedAway.xhtml
          Adding test\agnostic\scope\view\src\main\webapp\postconstruct.xhtml
          Adding test\agnostic\scope\view\src\test
          Adding test\agnostic\scope\view\src\test\java
          Adding test\agnostic\scope\view\src\test\java\com
          Adding test\agnostic\scope\view\src\test\java\com\sun
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope\view
          Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope\view\Issue2561IT.java
          Transmitting file data .....................
          Committed revision 11051.

          Show
          Manfred Riem added a comment - Applied to 2.2 trunk, svn commit -m "Fixed http://java.net/jira/browse/JAVASERVERFACES-2561 , r=rogerk, push the ViewScope into the session, maintained by the JSF runtime, so it properly calls the constructor, @PostConstruct and @PreDestroy all only once." Sending jsf-api\src\main\java\javax\faces\component\UIViewRoot.java Sending jsf-ri\src\main\java\com\sun\faces\application\WebappLifecycleListener.java Sending test\agnostic\pom.xml Adding test\agnostic\scope Adding test\agnostic\scope\pom.xml Adding test\agnostic\scope\view Adding test\agnostic\scope\view\pom.xml Adding test\agnostic\scope\view\src Adding test\agnostic\scope\view\src\main Adding test\agnostic\scope\view\src\main\java Adding test\agnostic\scope\view\src\main\java\com Adding test\agnostic\scope\view\src\main\java\com\sun Adding test\agnostic\scope\view\src\main\java\com\sun\faces Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\ConstructorBean.java Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\InvalidatedBean.java Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\NavigateAwayBean.java Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\NavigateBean.java Adding test\agnostic\scope\view\src\main\java\com\sun\faces\test\agnostic\scope\view\PostConstructBean.java Adding test\agnostic\scope\view\src\main\webapp Adding test\agnostic\scope\view\src\main\webapp\WEB-INF Adding test\agnostic\scope\view\src\main\webapp\WEB-INF\glassfish-web.xml Adding test\agnostic\scope\view\src\main\webapp\WEB-INF\web.xml Adding test\agnostic\scope\view\src\main\webapp\constructor.xhtml Adding test\agnostic\scope\view\src\main\webapp\invalidatedPerform.xhtml Adding test\agnostic\scope\view\src\main\webapp\invalidatedSession.xhtml Adding test\agnostic\scope\view\src\main\webapp\invalidatedVerify.xhtml Adding test\agnostic\scope\view\src\main\webapp\navigate.xhtml Adding test\agnostic\scope\view\src\main\webapp\navigateAway.xhtml Adding test\agnostic\scope\view\src\main\webapp\navigatedAway.xhtml Adding test\agnostic\scope\view\src\main\webapp\postconstruct.xhtml Adding test\agnostic\scope\view\src\test Adding test\agnostic\scope\view\src\test\java Adding test\agnostic\scope\view\src\test\java\com Adding test\agnostic\scope\view\src\test\java\com\sun Adding test\agnostic\scope\view\src\test\java\com\sun\faces Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope\view Adding test\agnostic\scope\view\src\test\java\com\sun\faces\test\agnostic\scope\view\Issue2561IT.java Transmitting file data ..................... Committed revision 11051.
          Hide
          tedgoddard added a comment -

          Now that the ViewScope is stored in the session, does this mean that ViewScope is never cleared until the session expires?

          Show
          tedgoddard added a comment - Now that the ViewScope is stored in the session, does this mean that ViewScope is never cleared until the session expires?
          Hide
          Manfred Riem added a comment -

          It should clear the view map once the user navigates away, or if the session expires. If that is not the behavior you are seeing please send us a reproducer so we can make sure we have not missed a corner case!

          Show
          Manfred Riem added a comment - It should clear the view map once the user navigates away, or if the session expires. If that is not the behavior you are seeing please send us a reproducer so we can make sure we have not missed a corner case!
          Hide
          tedgoddard added a comment -

          This appears to leak for direct URLs visited in the application. One solution would be to implement a listener on LRUMap to remove the ViewScope when the component tree is removed.

          Show
          tedgoddard added a comment - This appears to leak for direct URLs visited in the application. One solution would be to implement a listener on LRUMap to remove the ViewScope when the component tree is removed.
          Hide
          facboy added a comment -

          the upshot of this seems to be that ViewScoped managed beans are always kept in the session now. We have an app that was relying on ViewScoped managed beans being serialized into the ViewState so they had no server-side state. Am I right in saying that this is no longer the case?

          Show
          facboy added a comment - the upshot of this seems to be that ViewScoped managed beans are always kept in the session now. We have an app that was relying on ViewScoped managed beans being serialized into the ViewState so they had no server-side state. Am I right in saying that this is no longer the case?
          Hide
          Manfred Riem added a comment -

          The ViewScoped beans are now in the session as the serialization did not follow <init> + @PostConstruct and @PreDestroy. Now the @ViewScoped beans are properly following this as any other bean. Note both @ViewScoped aka CDI and non-CDI are now consistent with each other. And yes you are correct.

          Show
          Manfred Riem added a comment - The ViewScoped beans are now in the session as the serialization did not follow <init> + @PostConstruct and @PreDestroy. Now the @ViewScoped beans are properly following this as any other bean. Note both @ViewScoped aka CDI and non-CDI are now consistent with each other. And yes you are correct.

            People

            • Assignee:
              Manfred Riem
              Reporter:
              Ed Burns
            • Votes:
              2 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Time Tracking

                Estimated:
                Original Estimate - 8 hours
                8h
                Remaining:
                Remaining Estimate - 8 hours
                8h
                Logged:
                Time Spent - Not Specified
                Not Specified