Tuesday, May 5, 2009

How to force a table to refresh itself

Sometimes you will need to refresh a table after some event takes place in your backing bean.  You can refresh the table component using a partial trigger or refresh it from the backing bean using   getAdfFacesContext().addPartialTarget(uicomponent);  but that pulls the current values from the model through the page binding and doesn't necessarily pull fresh data from the database when the data has not been inserted from the ADF application.  I was having a problem in that when data was modified externally to our application (for example by an external web service call), that refreshing the table itself was not re-executing the query to bring in the new data.

This technique is simple and works across region boundaries instead of using contextual events.  Contextual events are Oracles' recommended practice for inter-region communication and I use them in many places but I have found them to carry a performance penalty, at least at the time of this writing and they are more difficult to configure.

When you have a table somewhere on your page (any region) that needs refreshing, perform the following steps

  • In a backing bean method, set a Boolean.TRUE into a requestScope variable. (see code in red below).
    .put("refreshNeeded", Boolean.TRUE);
    This can be done from the backing bean of any region (task flow) running on the page.
  •  In the executable bindings for your table, add a invokeAction executable (named refreshIfNeeded) and bind it to the Execute or ExecuteWithParams action binding for your table’s view (on the left hand side).
  • Set the refreshIfNeeded binding to refresh “Always”
  • Add a refresh condition expression that references your request scope variable.

In your backing bean you could  retrieve the "Execute" Action from the bindings and executed it yourself but that only works if your backing bean is in the same region as the table you want to refresh.  Also, this technique assures the query is only executed once during the ADF lifecycle.   If the variable is set on requestScope more than once by different regions, no harm done.  You will still need to refresh the table component itself either through a partial trigger or from the backing bean as mentioned but this technique will force the query to execute as well.