ICEfaces
  1. ICEfaces
  2. ICE-4924

NullPointerException with PersistentFacesState.redirectTo

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.8.1
    • Fix Version/s: 1.8.2-RC1, 1.8.2
    • Component/s: Framework
    • Labels:
      None
    • Environment:
      ICEfaces

      Description


      When PersistentFacesState.redirectTo() is invoked in a push application (such as when added to auctionMonitor with a Thread.sleep() added to one of the getters), the application can fail with a NullPointerException in various places, such as:


      javax.faces.FacesException: java.lang.NullPointerException
      at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:128)
      at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:139)
      at com.icesoft.faces.webapp.xmlhttp.PersistentFacesState.render(PersistentFacesState.java:176)
      at com.icesoft.faces.webapp.xmlhttp.PersistentFacesState.executeAndRender(PersistentFacesState.java:312)
      at com.icesoft.faces.async.render.RunnableRender.run(RunnableRender.java:143)
      at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:665)
      at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:690)
      at java.lang.Thread.run(Thread.java:637)
      Caused by: java.lang.NullPointerException
      at com.icesoft.faces.application.D2DViewHandler.renderResponse(D2DViewHandler.java:329)
      at com.icesoft.faces.application.D2DViewHandler.renderView(D2DViewHandler.java:159)
      at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:110)
      at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
      ... 7 more

      This appears to be caused by the locking implementation in redirectTo():

          public void redirectTo(String uri) {
              warnIfSynchronous();
              try {
                  view.acquireLifecycleLock();
                  view.installThreadLocals();
                  view.getFacesContext().getExternalContext().redirect(uri);
              } catch (Exception e) {
                  throw new RuntimeException(e);
              } finally {
                  release();
                  view.releaseLifecycleLock();
              }
          }

      view.releaseLifecycleLock() releases all locks held by the current thread. Unfortunately, the current thread may be in the midst of processing a JSF lifecycle, making it vulnerable to corruption from other (push) threads acting on the same view.

        Activity

        Hide
        Ted Goddard added a comment -

        — src/com/icesoft/faces/webapp/xmlhttp/PersistentFacesState.java (revision 19230)
        +++ src/com/icesoft/faces/webapp/xmlhttp/PersistentFacesState.java (working copy)
        @@ -331,18 +331,23 @@
        *

        • @param uri the relative or absolute URI.
          */
        • public void redirectTo(String uri) {
          + public void redirectTo(final String uri) {
          warnIfSynchronous();
        • try { - view.acquireLifecycleLock(); - view.installThreadLocals(); - view.getFacesContext().getExternalContext().redirect(uri); - }

          catch (Exception e)

          { - throw new RuntimeException(e); - }

          finally

          { - release(); - view.releaseLifecycleLock(); - }

          + executorService.execute(new Runnable() {
          + public void run()

          Unknown macro: {+ try { + view.acquireLifecycleLock(); + view.installThreadLocals(); + view.getFacesContext().getExternalContext().redirect(uri); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + release(); + view.releaseLifecycleLock(); + }+ }

          + });
          }

        /**

        Show
        Ted Goddard added a comment - — src/com/icesoft/faces/webapp/xmlhttp/PersistentFacesState.java (revision 19230) +++ src/com/icesoft/faces/webapp/xmlhttp/PersistentFacesState.java (working copy) @@ -331,18 +331,23 @@ * @param uri the relative or absolute URI. */ public void redirectTo(String uri) { + public void redirectTo(final String uri) { warnIfSynchronous(); try { - view.acquireLifecycleLock(); - view.installThreadLocals(); - view.getFacesContext().getExternalContext().redirect(uri); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - release(); - view.releaseLifecycleLock(); - } + executorService.execute(new Runnable() { + public void run() Unknown macro: {+ try { + view.acquireLifecycleLock(); + view.installThreadLocals(); + view.getFacesContext().getExternalContext().redirect(uri); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + release(); + view.releaseLifecycleLock(); + }+ } + }); } /**
        Hide
        Ted Goddard added a comment -

        Making use of the ExecutorService for redirectTo is likely less risky than modifying the locking strategy for View overall.

        Show
        Ted Goddard added a comment - Making use of the ExecutorService for redirectTo is likely less risky than modifying the locking strategy for View overall.
        Hide
        Ted Goddard added a comment -

        The following exception was observed with the fix in place. This exception has no functional impact, and simply indicates that the view being updated via push has been updated and a new view will be added to the render group in its place.

        SEVERE: Missing ViewRoot in restoreState, ice.session: zYPxM_aPinG5rjfawptDZQ, viewNumber: 1
        Sep 9, 2009 10:06:10 AM com.sun.faces.lifecycle.Phase doPhase
        SEVERE: JSF1054: (Phase ID: RESTORE_VIEW 1, View ID: ) Exception thrown during phase execution: javax.faces.event.PhaseEvent[source=com.sun.faces.lifecycle.LifecycleImpl@211c7f8d]
        Sep 9, 2009 10:06:10 AM com.icesoft.faces.webapp.xmlhttp.PersistentFacesState execute
        SEVERE: Exception occured during execute push on Unknown View
        javax.faces.application.ViewExpiredException: viewId:/auctionMonitor.iface - View /auctionMonitor.iface could not be restored.
        at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:189)
        at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100)
        at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:102)
        at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
        at com.icesoft.faces.webapp.xmlhttp.PersistentFacesState.execute(PersistentFacesState.java:285)
        at com.icesoft.faces.webapp.xmlhttp.PersistentFacesState.executeAndRender(PersistentFacesState.java:311)
        at com.icesoft.faces.async.render.RunnableRender.run(RunnableRender.java:143)
        at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:665)
        at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:690)
        at java.lang.Thread.run(Thread.java:637)

        Show
        Ted Goddard added a comment - The following exception was observed with the fix in place. This exception has no functional impact, and simply indicates that the view being updated via push has been updated and a new view will be added to the render group in its place. SEVERE: Missing ViewRoot in restoreState, ice.session: zYPxM_aPinG5rjfawptDZQ, viewNumber: 1 Sep 9, 2009 10:06:10 AM com.sun.faces.lifecycle.Phase doPhase SEVERE: JSF1054: (Phase ID: RESTORE_VIEW 1, View ID: ) Exception thrown during phase execution: javax.faces.event.PhaseEvent [source=com.sun.faces.lifecycle.LifecycleImpl@211c7f8d] Sep 9, 2009 10:06:10 AM com.icesoft.faces.webapp.xmlhttp.PersistentFacesState execute SEVERE: Exception occured during execute push on Unknown View javax.faces.application.ViewExpiredException: viewId:/auctionMonitor.iface - View /auctionMonitor.iface could not be restored. at com.sun.faces.lifecycle.RestoreViewPhase.execute(RestoreViewPhase.java:189) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:100) at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:102) at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118) at com.icesoft.faces.webapp.xmlhttp.PersistentFacesState.execute(PersistentFacesState.java:285) at com.icesoft.faces.webapp.xmlhttp.PersistentFacesState.executeAndRender(PersistentFacesState.java:311) at com.icesoft.faces.async.render.RunnableRender.run(RunnableRender.java:143) at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:665) at edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:690) at java.lang.Thread.run(Thread.java:637)
        Hide
        Ted Goddard added a comment -

        Marking as fixed. Re-open or create new JIRA if redirectTo fails regression testing.

        Show
        Ted Goddard added a comment - Marking as fixed. Re-open or create new JIRA if redirectTo fails regression testing.
        Hide
        Ken Fyten added a comment -

        Why not add to the log for the exception above to indicate that this might be normal, or else catch the exception altogether?

        Show
        Ken Fyten added a comment - Why not add to the log for the exception above to indicate that this might be normal, or else catch the exception altogether?
        Hide
        Ted Goddard added a comment -

        This same exception can likely occur under abnormal circumstances as well, so it's best to leave it as-is. It occurs very rarely.

        Show
        Ted Goddard added a comment - This same exception can likely occur under abnormal circumstances as well, so it's best to leave it as-is. It occurs very rarely.
        Hide
        Ted Goddard added a comment -

        A test case is checked in, however, the test case does not make use of push, so it exercises redirectTo, but would not reproduce the exception.

        Show
        Ted Goddard added a comment - A test case is checked in, however, the test case does not make use of push, so it exercises redirectTo, but would not reproduce the exception.

          People

          • Assignee:
            Ted Goddard
            Reporter:
            Ted Goddard
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: