tags:

views:

307

answers:

0

Hello,

My application is using JSF 1.2 and Richfaces 3.3.2. We have implemented our own datatable component, which is based on the Richfaces datatable component.

One of the features of our datatable is to modify the header to include some new components (such as a data scroller). What I do is that I modify the content of the <f:facet name="header">. For example, in my XHTML page, I get that:

<my:dataTable id="table1" value="#{aBean.aList}">
    <f:facet name="header">
        <a4j:commandButton action="#{aBean.doSomething}" value="Go" reRender="table1"/>
    </f:facet>
    ...
</my:dataTable>

On the Java side, my renderer class is manipulating the content of the facet to encapsulate it into another component. In a simplified version of my code, the content of the facet is encapsulated in a simple <h:panelGroup>:

@Override
public void doEncodeBegin(ResponseWriter writer, FacesContext context, UIDataTable table, ComponentVariables vars) throws IOException {
    ...
    modifyHeader(context, table);
    ...
}

private void modifyHeader(FacesContext context, UIDataTable table) {
    UIComponent facetContent = table.getFacet("header");
    if ((facetContent == null) || !facetContent.isRendered()) {
        return;
    }
    HtmlPanelGroup group = new HtmlPanelGroup();
    group.getChildren().add(facetContent);
    table.getFacets().put("header", group);
}

This code is working well, except when Ajax is used in my page. Let's have two simple tables in my page:

<my:dataTable id="table1" value="#{aBean.aList}">
    <f:facet name="header">
        <a4j:commandButton action="#{aBean.doSomething}" value="Go" reRender="table1"/>
    </f:facet>
    ...
</my:dataTable>
<my:dataTable id="table2" value="#{aBean.anotherList}">
    <f:facet name="header">
        <a4j:commandButton action="#{aBean.doOtherThing}" value="Go 2" reRender="table2"/>
    </f:facet>
    ...
</my:dataTable>

If I click on the first button, the method aBean.doSomething is called. If I click again on the first button, the method aBean.doSomething is still called. However, if I clicked on the second button, the method aBean.doOtherThing is not called.

The order of the button has no impact: if I start clicking on the second button, aBean.doOtherThing is called. Once the page is refreshed, the first button will not work anymore.

Why do I get this behavior?

Note that I can make this working using three little fixes:

1. Make the two tables re-rendered by Ajax, i.e. having :

<a4j:commandButton action="#{aBean.doSomething}" value="Go" reRender="table1,table2"/>
...
<a4j:commandButton action="#{aBean.doOtherThing}" value="Go 2" reRender="table2,table1"/>

2. Forcing an ID for all the buttons:

<a4j:commandButton id="btn1" action="#{aBean.doSomething}" value="Go" reRender="table1"/>
...
<a4j:commandButton id="btn2" action="#{aBean.doOtherThing}" value="Go 2" reRender="table2"/>

3. Just avoid to encapsulate the facetContent in another component in the method modifyHeader(). But this means that I do not modify the table, which is not what I want.

What do I do wrong??


Edit:

No error is shown on the Javascript console. An Ajax is sent, all the lifecycle is executed on the server, but the 5th phase - Invoke application - does not call the corresponding Java bean method.