JSF UI Framework

Ajax4jsf Best Practices

Updated: July 17, 2023

This page lists some good practices to follow to ensure correct rendering, HTML and testing.

Some of this content is outdated and needs to be reviewed.

Use a4j:region to Speed up Ajax Rendering

Wrap JSF components that are affected by rerender targets or a4j:support tags with a a4j:region renderRegionOnly="true" in order to both lower the network bandwidth usage and the CPU pressure on the server since a much smaller part of the JSF tree will be processed:

TODO: add an example here

Use a4j:outputPanel as Target of Rerender Clauses

If you have JSF elements with dynamic render clause that are evaluated to false in the first page rendering, a4j reRendering will fail to make them appear afterward since will not be present in the JSF rendering tree. Wrapping them with a a4j:outputPanel that holds the reRender target id will solve the issue.

TODO: add an example here

Also see for reference: http://www.jroller.com/a4j/entry/ajax_regions_and_output_panels

Use Attribute layout="block" on a4j:outputPanel Tag

If the a4j:outputPanel tag will contain divs or tables, for instance, you should use attribute layout="block" so that it's displayed using a div instead of a span, as a span tag containing divs or tables will produce invalid HTML.

See the reference documentation at http://docs.jboss.org/richfaces/latest_3_3_X/en/devguide/html/a4j_outputPanel.html

For instance if you naively replace h:commandLink by a4j:commandLink in the sort column links of a document listings you can get no effect on the first click (but works the second time but with the wrong arrow position).

The reason is that h:commandLink is a traditional JSF JavaScript postback that first sends a POST request to apply the new values and then redirect the browser using HTTP code 302 to the updated page using a second GET request that renders the results. In the a4j:commandLink case this is a different story since there is only one HTTP request to perform both the model values update and the new HTML fragment rendering. Hence if you use Seam variables computed by EVENT scoped factory, it is computed twice in the first case and only once (and then "cached") in the second case.

For instance the SortActionsBean has been improved to allow the caller to invalidate Seam components using an additional f:param with name invalidateSeamVariables to invalidate the filterSelectModel that gets cached too early (before we change the order with the Ajax action): http://hg.nuxeo.org/nuxeo/nuxeo-jsf/rev/7e388aa56786.

Hence the sort title controls can be ajaxified in the following way:

<a4j:commandLink id="title" action="#{sortActions.repeatSearch}"
              rendered="#{provider.sortable}" reRender="filterResultTable" >
      <h:outputText value="#{messages['label.content.header.title']}" />
      <f:param name="providerName" value="#{providerName}" />
      <f:param name="sortColumn" value="dc:title" />
      <f:param name="invalidateSeamVariables" value="filterSelectModel" />
      <h:panelGroup rendered="#{provider.sortInfo.sortColumn == 'dc:title' }"
        <h:graphicImage value="/icons/arrow_down.gif"
            rendered="#{provider.sortInfo.sortAscending}" />
        <h:graphicImage value="/icons/arrow_up.gif"
            rendered="#{!provider.sortInfo.sortAscending}" />
      </h:panelGroup>
</a4j:commandLink>

Use the New a4j Namespace

The URI for a4j: and rich: namespaces are changed to "http://richfaces.org/a4j" and "http://richfaces.org/rich". The previous URIs are also available for a backward compatibility but it is recommended to switch to the new names for consistency.

Testing with Selenium

Add the following functions in your user-extensions.js of your Selenium tests suite to be able to setup smart waiters in your Selenium tests suite that have a far better stability than "pause" steps that may slowdown then set suite a lot while still breaking randomly if the Selenium server is otherwise put under too much load: http://www.nuxeo.com/blog/development/2009/03/selenium-ajax-requests/.

There seems to be bugs remaining with this method: it works most of the time but sometimes breaks later unexpectedly. More investigations are needed to make it robust.