ICEfaces
  1. ICEfaces
  2. ICE-7055

Window scoped beans get reactivated after disposal

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: EE-2.0.0.GA, 2.0.2
    • Fix Version/s: 2.1-Beta, 3.0
    • Component/s: None
    • Labels:
      None
    • Environment:
      Scopes test
    • Assignee Priority:
      P1

      Description

      Using the scopes test, the web.xml needs to be modified first by including the following context-param:

          <context-param>
              <param-name>org.icefaces.lazyWindowScope</param-name>
              <param-value>false</param-value>
          </context-param>

      To reproduce the issue, follow these steps:

      - Go to http://host:port/scopes/window-scope-A.jsf
      - Check the server logs for a window scoped bean that has been created, something like:
            created >> org.icefaces.demo.scopes.WindowScopedCounter@14323d5
      - Go to http://www.google.ca/ (or any other non-scopes application page) and stay on this page for a couple of seconds
      - Go to http://host:port/scopes/window-scope-A.jsf again (NOT USING THE BACK BUTTON)
      - Check the server logs for disposal of the old window scoped bean and the creation of a new window scoped bean, something like:
            destroyed >> org.icefaces.demo.scopes.WindowScopedCounter@14323d5
            created >> org.icefaces.demo.scopes.WindowScopedCounter@1abdac9
      - Go to http://www.google.ca/ (or any other non-scopes application page) and wait for the session to timeout
      - Check the server logs for disposal of the new window scoped bean and incorrectly also another disposal of the old window scoped bean, something like:
            destroyed >> org.icefaces.demo.scopes.WindowScopedCounter@1abdac9
            destroyed >> org.icefaces.demo.scopes.WindowScopedCounter@14323d5 <===--- 2nd invocation of @PreDestroy on the same window scoped bean

      What seems to be happening is as follows:

      - When go to Google for the 1st time the old window scoped bean is removed from the windowScopedMaps and put in the disposedWindowScopedMaps using the disactivate() method:
              private void disactivate(State state) {
                  deactivateTimestamp = System.currentTimeMillis();
                  state.disposedWindowScopedMaps.addLast(state.windowScopedMaps.remove(id));
              }
      - When returning to the scopes application the new window scoped bean is added to the windowScopedMaps and the old window scoped bean is removed from the disposedWindowScopedMaps using the discardIfExpired() method:
              private void discardIfExpired(FacesContext facesContext) {
                  State state = getState(facesContext);
                  if (System.currentTimeMillis() > deactivateTimestamp + state.expirationPeriod) {
                      boolean processingEvents = facesContext.isProcessingEvents();
                      try {
                          facesContext.setProcessingEvents(true);
                          ScopeContext context = new ScopeContext(ScopeName, this);
                          facesContext.getApplication().publishEvent(facesContext, PreDestroyCustomScopeEvent.class, context);
                      } finally {
                          state.disposedWindowScopedMaps.remove(this);
                          facesContext.setProcessingEvents(processingEvents);
                      }
                  }
              }
      - So far so good, but something kicks off another JSF lifecycle:
              at java.lang.Thread.dumpStack(Thread.java:1249)
              at org.icefaces.impl.application.WindowScopeManager$ScopeMap.activate(WindowScopeManager.java:452)
              at org.icefaces.impl.application.WindowScopeManager$ScopeMap.access$700(WindowScopeManager.java:363)
              at org.icefaces.impl.application.WindowScopeManager.determineWindowID(WindowScopeManager.java:234)
              at org.icefaces.impl.application.WindowScopeManager$1.beforePhase(WindowScopeManager.java:92)
              at com.sun.faces.lifecycle.Phase.handleBeforePhase(Phase.java:228)
              at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:99)
              at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:116)
              at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
              at org.icefaces.impl.application.WindowScopeManager.disposeViewScopeBeans(WindowScopeManager.java:305)
              at org.icefaces.impl.application.WindowScopeManager.disposeWindow(WindowScopeManager.java:291)
              at org.icefaces.impl.application.WindowScopeManager.handleResourceRequest(WindowScopeManager.java:152)
              at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
              at javax.faces.application.ResourceHandlerWrapper.handleResourceRequest(ResourceHandlerWrapper.java:125)
              at javax.faces.webapp.FacesServlet.service(FacesServlet.java:407)
              at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
              at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
              at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
              at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
              at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
              at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
              at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
              at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
              at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
              at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
              at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
              at java.lang.Thread.run(Thread.java:662)
      - As seen from the stack dump, the activate() method is invoked for the old window scoped bean:
              private void activate(State state) {
                  state.windowScopedMaps.put(id, this);
                  activateTimestamp = System.currentTimeMillis();
              }
      - From this point the windowScopedMaps contains both the old and new window scoped beans (though the @PreDestroy of the old window scoped bean has already been invoked).

        Issue Links

          Activity

          Hide
          Jack Van Ooststroom added a comment -

          Assigning to Mircea for investigation.

          Show
          Jack Van Ooststroom added a comment - Assigning to Mircea for investigation.
          Hide
          Mircea Toma added a comment -

          Changed view scope bean disposal to run after the restore phase is executed to avoid running the additional JSF cycle which causes the reactivation of scope maps while disposing views/window. Refactored also anonymous phase listeners into inner classes. Registered phase listeners declaratively insted of doing it programmatically.

          Show
          Mircea Toma added a comment - Changed view scope bean disposal to run after the restore phase is executed to avoid running the additional JSF cycle which causes the reactivation of scope maps while disposing views/window. Refactored also anonymous phase listeners into inner classes. Registered phase listeners declaratively insted of doing it programmatically.

            People

            • Assignee:
              Mircea Toma
              Reporter:
              Jack Van Ooststroom
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: