Uploaded image for project: 'MyFaces Trinidad'
  1. MyFaces Trinidad
  2. TRINIDAD-1762

actionListener called to often

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 1.2.13-core
    • None
    • Components, Facelets
    • None
    • Win XP, facelets 1.1.15-jsf1.2, Mojarra 1.2_12

    Description

      I use myfaces trinidad 1.2.13 together with facelets 1.1.15-jsf1.2 to deploy a war file in the JBoss 5.1.0.GA application server.
      As JSF implementation the RI Mojarra (1.2_12-b01-FCS) shipped with JBoss 5.1.0 is used.

      I detected the problem that actionListener method defined on a tr:commandButton were called multiple times.

      <tr:commandButton id="myId" textAndAccessKey="#

      {msg['bundlekey.mybutton']}

      " binding="#

      {myBean._myButton}

      " disabled="#

      {!myBean.editable}

      " partialTriggers="otherId" action="#

      {myBean.myAction}

      " actionListener="#

      {myBean.myListenerAction}

      " blocking="true" />

      Here are my analysis:

      In web.xml i have set following parameters as i found here: https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=1176

      <context-param>
      <param-name>com.sun.faces.IS_SAVE_BINDINGS_STATE</param-name>
      <param-value>false</param-value>
      </context-param>

      <context-param>
      <param-name>facelets.BUILD_BEFORE_RESTORE</param-name>
      <param-value>true</param-value>
      </context-param>

      <context-param>
      <param-name>facelets.RECREATE_VALUE_EXPRESSION_ON_BUILD_BEFORE_RESTORE</param-name>
      <param-value>true</param-value>
      </context-param>

      In the facelets class com.sun.facelets.tag.jsf.ComponentHandler which is the super class of
      org.apache.myfaces.trinidadinternal.facelets.TrinidadComponentHandler in the method apply(FaceletContext ctx, UIComponent parent) there is following code.

      1.) If component doesn't exist it is created and com.sun.facelets.tag.jsf.ComponentHandler line 165 it calls
      this.setAttributes(ctx, c);

      which in turn comes to com.sun.facelets.tag.jsf.ActionSourceRule$ActionListenerMapper2 method
      applyMetadata(FaceletContext ctx, Object instance)

      which creates a javax.faces.event.MethodExpressionActionListener instance and adds it as listener to the
      org.apache.myfaces.trinidad.component.core.nav.CoreCommandButton

      2.) If the component exists then com.sun.facelets.tag.jsf.ComponentHandler line 155 calls
      recreateValueExpressions(ctx, c);

      This method comes also to com.sun.facelets.tag.jsf.ActionSourceRule$ActionListenerMapper2 method applyMetadata(FaceletContext ctx, Object instance)

      which creates a javax.faces.event.MethodExpressionActionListener instance and adds it as listener to the
      org.apache.myfaces.trinidad.component.core.nav.CoreCommandButton

      And so we have a second listeners, and 3rd and 4th and so on.

      The listeners are held in an ArrayList and unfortunately there is no check if the added javax.faces.event.MethodExpressionActionListener represents the same expression.

      I think it is a bug and org.apache.myfaces.trinidad.component.UIXComponentBase method addFacesListener(FacesListener listener) should do something
      to prevent that multiple javax.faces.event.MethodExpressionActionListener can be added that are representing the same EL expression which results in multiple calls of the same method when listeners are informed (FacesEvent broadcasted by org.apache.myfaces.trinidad.component.UIXComponentBase).

      Callstack for 1.)

      UIXFacesBeanImpl(FacesBeanImpl).addEntry(PropertyKey, Object) line: 189
      CoreCommandButton(UIXComponentBase).addFacesListener(FacesListener) line: 1108
      CoreCommandButton(UIXCommand).addActionListener(ActionListener) line: 366
      ActionSourceRule$ActionListenerMapper2.applyMetadata(FaceletContext, Object) line: 98
      MetadataImpl.applyMetadata(FaceletContext, Object) line: 36
      TrinidadComponentHandler(MetaTagHandler).setAttributes(FaceletContext, Object) line: 76
      TrinidadComponentHandler(ComponentHandler).apply(FaceletContext, UIComponent) line: 165
      CompositeFaceletHandler.apply(FaceletContext, UIComponent) line: 47
      TrinidadComponentHandler(ComponentHandler).applyNextHandler(FaceletContext, UIComponent) line: 360

      Callstack for 2.)
      UIXFacesBeanImpl(FacesBeanImpl).addEntry(PropertyKey, Object) line: 189
      CoreCommandButton(UIXComponentBase).addFacesListener(FacesListener) line: 1108
      CoreCommandButton(UIXCommand).addActionListener(ActionListener) line: 366
      ActionSourceRule$ActionListenerMapper2.applyMetadata(FaceletContext, Object) line: 98
      MetadataImpl.applyMetadata(FaceletContext, Object) line: 36
      TrinidadComponentHandler(MetaTagHandler).recreateValueExpressions(FaceletContext, UIComponent) line: 87
      TrinidadComponentHandler(ComponentHandler).apply(FaceletContext, UIComponent) line: 155
      CompositeFaceletHandler.apply(FaceletContext, UIComponent) line: 47
      TrinidadComponentHandler(ComponentHandler).applyNextHandler(FaceletContext, UIComponent) line: 360

      Remark:
      In the meantime i found out that the improvement in facelets 1.1.15 are only in effect with RI Mojarra 1.2_14. I will use 1.2_12 shipped with JBoss 5.1.0.GA.
      Therefore i had commented out the 3 context-parameters in web.xml and avoided the problem.
      But nevertheless the improvements of Mojarra 1.2_14 together with facelets 1.1.15 can't be used with myfaces trinidad 1.2.13 due to the explained problem.

      Attachments

        Activity

          People

            Unassigned Unassigned
            mardinator Martin Walla
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

              Created:
              Updated: