Search code examples
jsfcommandbuttonbootsfaces

b:commandButton in tagfile invokes methods twice with action listener is added to action


I try to write an jsf tag libary. So i have created a libary which provides a facelet: AbButton.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:b="http://bootsfaces.net/ui" xmlns:o="http://omnifaces.org/ui"
                xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">

    <c:choose>
        [... other button variants...]
        <c:when test="#{type == 'command' and not empty look}">
            <b:commandButton value="#{value}" action="#{bean[action]}" id="#{id}" actionListener="#{bean[actionListener]}"
                         update="#{update}" look="#{look}" size="#{size}" iconAwesome="#{icon}" style="#{style}"/>
        </c:when>
    </c:choose>
</ui:composition>

And i have created a taglib.xml which describes the attributes.

<tag>
    <tag-name>abButton</tag-name>
    <description><![CDATA[Flexible Button Implementierung. Von Bootsfaces Button abgeleitet.]]></description>
    <source>resources/tags/AbButton.xhtml</source>

    [...]
    <attribute>
        <description><![CDATA[ stuff]]></description>
        <name>action</name>
        <required>false</required>
        <type>javax.el.MethodExpression</type>
    </attribute>
    <attribute>
        <description><![CDATA[stuff]]></description>
        <name>actionListener</name>
        <required>false</required>
        <type>javax.el.MethodExpression</type>
    </attribute>
    [...]
</tag>

Last but not least i implemented it in a test application. Button.xhtml

<h:body>
    <h:form>
        <a:abButton type="command" id="command" bean="#{button}" action="action" actionListener="actionListener" value="Command Button" style="margin-right:20px;" look="primary"/>
    </h:form>
</h:body>

And a Backing Bean named Button.java

@Named("button")
@RequestScoped
public class Button {

    public void action(){
        System.out.println("action");
    }

    public void actionListener(){
        System.out.println("action listener");
    }
}

If i now klick the button, both action and actionListener method get executed 2 times. If i remove the actionListener, the action method is only one time executed. Same thing is happening is i use different beans, lets say

AbButton.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:b="http://bootsfaces.net/ui" xmlns:o="http://omnifaces.org/ui"
                xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">

    <c:choose>
        [... other button variants...]
        <c:when test="#{type == 'command' and not empty look}">
            <b:commandButton value="#{value}" action="#{bean2[action]}" id="#{id}" actionListener="#{bean[actionListener]}"
                         update="#{update}" look="#{look}" size="#{size}" iconAwesome="#{icon}" style="#{style}"/>
        </c:when>
    </c:choose>
</ui:composition>

and Button.xhtml

<h:body>
    <h:form>
        <a:abButton type="command" id="command" bean="#{button}" bean2="#{button}" action="action" actionListener="actionListener" value="Command Button" style="margin-right:20px;" look="primary"/>
    </h:form>
</h:body>

And the absolut same happens if i use the Omnifaces o:methodParam this way:

AbButton.xhtml

<ui:composition xmlns="http://www.w3.org/1999/xhtml"
                xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
                xmlns:b="http://bootsfaces.net/ui" xmlns:o="http://omnifaces.org/ui"
                xmlns:c="http://xmlns.jcp.org/jsp/jstl/core">

    <c:choose>
        [... other button variants...]
        <c:when test="#{type == 'command' and not empty look}">
            <o:methodParam name="actionMethod" value="#{action}"/>
            <o:methodParam name="actionListenerMethod" value="#{actionListener}"/>
            <b:commandButton value="#{value}" action="#{actionMethod}" actionListener="#{actionListenerMethod}" id="#{id}" look="#{look}"
                         update="#{update}" size="#{size}" iconAwesome="#{icon}" style="#{style}"/>
        </c:when>
    </c:choose>
</ui:composition>

and button.xhtml

<h:body>
    <h:form>
        <a:abButton type="command" id="command" action="#{button.action}" actionListener="#{button.actionListener}" value="Command Button" style="margin-right:20px;" look="primary"/>
    </h:form>
</h:body>

The same happens. With action and actionListener active both are executed twice. If i remove the actionListener the action method is only executed one time. I hope it is now a better to understand. Any help?


Solution

  • Ah now i've got it. This is a bug in bootsfaces 0.8.1 related here Issue 295. With a update to Bootsfaces 0.8.5 everything works as expected. Maybe this helps someone facing the same problem.