ICEfaces
  1. ICEfaces
  2. ICE-4604

Navigation clearing current lifecycle state

    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:
      Tomcat 6, JSF 1.1

      Description

      This is the underlying problem for ICE-4565. It looks like, when a commandLink is pressed, that a redirect navigation rule is executed, which causes the current view to be cleaned-up:

      com.icesoft.faces.context.BridgeFacesContext.resetLastViewID(BridgeFacesContext.java:839)
      com.icesoft.faces.context.BridgeExternalContext.redirect(BridgeExternalContext.java:412)
      com.sun.faces.application.NavigationHandlerImpl.handleNavigation(NavigationHandlerImpl.java:149)
      com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:109)
      javax.faces.component.UICommand.broadcast(UICommand.java:332)
      com.icesoft.faces.component.panelseries.UISeries$RowEvent.broadcast(UISeries.java:617)

      The problem is that UIData/UISeries still does more processing after the ActionEvent is broadcasted. Because the UIViewRoot in BridgeFacesContext has been nulled out, then the RenderKit is no longer accessible, so the clientId calculation code throws a NPE.

      java.lang.NullPointerException
      javax.faces.component.UIComponentBase.getRenderer(UIComponentBase.java:1093)
      javax.faces.component.UIComponentBase.getClientId(UIComponentBase.java:272)
      com.icesoft.faces.component.panelseries.UISeries.restoreChild(UISeries.java:523)
      com.icesoft.faces.component.panelseries.UISeries.restoreChildState(UISeries.java:475)
      com.icesoft.faces.component.panelseries.UISeries.restoreChildState(UISeries.java:478)
      com.icesoft.faces.component.panelseries.UISeries.restoreChildState(UISeries.java:478)
      com.icesoft.faces.component.panelseries.UISeries.restoreChildrenState(UISeries.java:463)
      com.icesoft.faces.component.panelseries.UISeries.setRowIndex(UISeries.java:139)
      com.icesoft.faces.component.panelseries.UISeries$RowEvent.broadcast(UISeries.java:644)
      com.icesoft.faces.component.panelseries.UISeries.broadcast(UISeries.java:286)
      com.icesoft.faces.component.paneltabset.PanelTabSet.broadcast(PanelTabSet.java:303)
      javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:287)
      javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:401)
      com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:95)

      Even if we swap out our ICEfaces container components for stock JSF ones, like h:dataTable, it still has the same problem:

      java.lang.NullPointerException
      javax.faces.component.UIComponentBase.getRenderer(UIComponentBase.java:1093)
      javax.faces.component.UIComponentBase.getClientId(UIComponentBase.java:272)
      javax.faces.component.UIData.restoreDescendantState(UIData.java:1095)
      javax.faces.component.UIData.restoreDescendantState(UIData.java:1111)
      javax.faces.component.UIData.restoreDescendantState(UIData.java:1071)
      javax.faces.component.UIData.setRowIndex(UIData.java:416)
      javax.faces.component.UIData.broadcast(UIData.java:678)
      javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:287)
      javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:401)
      com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:95)

      I think that somehow we have to defer the cleanup in BridgeFacesContext.resetLastViewID() until later on, instead of doing it right in BridgeExternalContext.redirect().

      But, I was able to make a simple work-around, that keeps this from being an issue within ICEfaces container components, it's just that it won't help within a stock JSF container, like h:dataTable. First, in UISeries.RowEvent.broadcast(), we omit the row state saving code when we detect the JSF lifecycle is being short-circuited:

              public void broadcast() {
                  int oldRowIndex = getRowIndex();
                  setRowIndex(eventRowIndex);
                  event.getComponent().broadcast(event);
      + // If we're doing a navigation rule, don't alter state
      + FacesContext facesContext = FacesContext.getCurrentInstance();
      + if (facesContext == null ||
      + facesContext.getRenderResponse() ||
      + facesContext.getResponseComplete()) {
      + return;
      + }
                  setRowIndex(oldRowIndex);
              }

      Secondly, I believe I found a bug, whereby UISeries.queueEvent(FacesEvent) is redundantly having its superclass UIData do similar processing, which has to be fixed. Basically, instead of calling super.queueEvent(FacesEvent), which will call UIData.queueEvent(FacesEvent), just do what UIComponentBase.queueEvent(FacesEvent) will do, inline.

          public void queueEvent(FacesEvent event) {
              FacesEvent rowEvent = new RowEvent(this, event, getRowIndex());
      - super.queueEvent(rowEvent);
      + UIComponent parent = getParent();
      + if (parent == null) {
      + throw new IllegalStateException();
      + } else {
      + parent.queueEvent(rowEvent);
      + }
          }

        Issue Links

          Activity

          Mark Collette created issue -
          Hide
          Mark Collette added a comment -

          For assignment to the core team.

          Show
          Mark Collette added a comment - For assignment to the core team.
          Mark Collette made changes -
          Field Original Value New Value
          Assignee Ken Fyten [ ken.fyten ]
          Mark Collette made changes -
          Link This issue blocks ICE-4565 [ ICE-4565 ]
          Hide
          Mark Collette added a comment -

          ICE-4565 has the sales info, the test WAR, and the ammended web.xml and faces-config.xml files for duplicating the issue.

          Show
          Mark Collette added a comment - ICE-4565 has the sales info, the test WAR, and the ammended web.xml and faces-config.xml files for duplicating the issue.
          Arran Mccullough made changes -
          Salesforce Case [50070000008oeIp]
          Ken Fyten made changes -
          Fix Version/s 1.8.2 [ 10190 ]
          Assignee Priority P1
          Assignee Ken Fyten [ ken.fyten ] Mircea Toma [ mircea.toma ]
          Repository Revision Date User Message
          ICEsoft Public SVN Repository #19000 Fri Jun 26 06:50:01 MDT 2009 mircea.toma ICE-4604 Delay resetting viewRoot variable until the end of lifecycle.
          Files Changed
          Commit graph MODIFY /icefaces/trunk/icefaces/core/src/com/icesoft/faces/context/BridgeFacesContext.java
          Hide
          Mircea Toma added a comment -

          Delay resetting viewRoot variable until the end of lifecycle.

          Show
          Mircea Toma added a comment - Delay resetting viewRoot variable until the end of lifecycle.
          Mircea Toma made changes -
          Status Open [ 1 ] Resolved [ 5 ]
          Resolution Fixed [ 1 ]
          Ken Fyten made changes -
          Fix Version/s 1.8.2-RC1 [ 10210 ]
          Ken Fyten made changes -
          Status Resolved [ 5 ] Closed [ 6 ]
          Assignee Priority P1

            People

            • Assignee:
              Mircea Toma
              Reporter:
              Mark Collette
            • Votes:
              1 Vote for this issue
              Watchers:
              4 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: