Uploaded image for project: 'MyFaces Core'
  1. MyFaces Core
  2. MYFACES-2710

Cannot call UIComponent.getCurrentComponent() from UIComponent.restoreState() or UIComponent.saveState()

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.0.0
    • 2.0.1
    • JSR-314
    • None

    Description

      From jsr-314-open list:

      The javadoc of UIComponent.processRestoreState() says this:

      "....Perform the component tree processing required by the Restore View phase of the request processing lifecycle for all facets of this component, all children of this component, and this component itself, as follows.

      • Call the restoreState() method of this component.
      • Call pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent).
      • Call the processRestoreState() method of all facets and children of this UIComponent in the order determined by a call to getFacetsAndChildren(). After returning from the processRestoreState() method on a child or facet, call popComponentFromEL(javax.faces.context.FacesContext)..."

      The javadoc of UIComponent.processSaveState() says this:

      ".....Perform the component tree processing required by the state saving portion of the Render Response phase of the request processing lifecycle for all facets of this component, all children of this component, and this component itself, as follows.

      • consult the transient property of this component. If true, just return null.
      • Call pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent).
      • Call the processSaveState() method of all facets and children of this UIComponent in the order determined by a call to getFacetsAndChildren(), skipping children and facets that are transient. Ensure that popComponentFromEL(javax.faces.context.FacesContext) is called correctly after each child or facet.
      • Call the saveState() method of this component.
      • Encapsulate the child state and your state into a Serializable Object and return it....."

      The question is: Doesn't suppose that when you call UIComponent.getCurrentComponent() inside UIComponent.restoreState(), it returns the "current component"?. There is one case when we need to do this call and is on the wrapper used by UIComponent.subscribeToEvent(). The javadoc of this method says this:

      "....Install the listener instance referenced by argument componentListener as a listener for events of type eventClass originating from this specific instance of UIComponent. The default implementation creates an inner SystemEventListener instance that wraps argument componentListener as the listener argument. This inner class must call through to the argument componentListener in its implementation of SystemEventListener.processEvent(javax.faces.event.SystemEvent) and its implementation of SystemEventListener.isListenerForSource(java.lang.Object) must return true if the instance class of this UIComponent is assignable from the argument to isListenerForSource...."

      Both myfaces and mojarra has the wrapper described by the javadoc, and that one is responsible to save/restore the system event listeners attached. To restore the "component" reference required, both implementations call UIComponent.getCurrentComponent() and both call processEvent but for the parent!.

      It is obviously a bug (I don't see a valid reason why do the algorithm described), if you look other methods like processDecodes, you see the right pattern:

      • If the rendered property of this UIComponent is false, skip further processing.
      • Call pushComponentToEL(javax.faces.context.FacesContext, javax.faces.component.UIComponent).
      • Call the processDecodes() method of all facets and children of this UIComponent, in the order determined by a call to getFacetsAndChildren().
      • Call the decode() method of this component.
      • Call popComponentFromEL(javax.faces.context.FacesContext) from inside of a finally block, just before returning.
      • If a RuntimeException is thrown during decode processing, call FacesContext.renderResponse() and re-throw the exception.

      I'll change myfaces algorithm to look like processDecodes(). But anyway, it is necessary to do the proper change on mojarra and on spec javadoc.

      The spec issue is this:

      http://javaserverfaces-spec-public.dev.java.net/issues/show_bug.cgi?id=792

      Attachments

        Activity

          People

            lu4242 Leonardo Uribe
            lu4242 Leonardo Uribe
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: