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 -
          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 ]
          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 ]
          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: