Details
-
Bug
-
Status: Open
-
Major
-
Resolution: Unresolved
-
1.2.13-core
-
None
-
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.