Notifying ADF applications of database changes – fast and lean using Active Data Service for Server to Client Push – Part Two

Yesterday I wrote that in two articles, I would demonstrate how we can ensure that changes in the database – new, changed or deleted data – can rapidly be reflected in ADF based user interfaces running in browsers. This story involves a two-step push-mechanism: push from database to middle tier and push from middle tier to browser. For the former – discussed in Notifying ADF applications of database changes – fast and lean using Database Query Result Change Notification – Part One – we will use the Oracle Database (and JDBC Driver) feature Query Result Change Notification and for the latter we leverage the Active Data Service in ADF Faces. The latter – server to browser push – is the topic of this second part. It will hook into where the first part took us (so you are advised to first read part one) and take the changes the database notifies us all the way up into the user interface.

A sketch of the architecture of the application we will create in this article looks like this:

The two push steps are marked with the green ellipses. The red box indicates the area under scrutiny in this article.

Part one concluded with a set up in which changes in the data in table EMP were reported through Database Query Result Change Notification to the ADF Model layer and from there via an Application Scope mediator bean to Session Scope beans. It also demonstrated how the ViewObject could be made to re-execute its query in order to retrieve the changed data from the database – through an invokeAction in the Page Definition that executes the ViewObject’s Execution operation and that has its refreshCondition tied to the sessionScope bean that receives word of changes in table EMP. The one thing still lacking from this pretty picture was the mechanism to let the browser know that a change is pending and a server request is desired from the browser. At this point we wait for such a request to take place in order to piggy back the pending changes on that request back to the browser.

ADF Faces provides a mechanism called Active Data Service that allows us push changes from the server to the client. Through Active Data Services, we can inform the browser about the fact that changes are available. The browser can respond by queuing a server event that through a serverListener results in a request that is handled by a bean in the server. At that point, the piggy back construction (mainly because of the change event policy on the iteratorBinding set to ppr) kicks in and the changes are automatically pushed on the response up to the browser.

The important elements are the activeOutputText component (invisible) in the UI that is bound to a session scope bean that extends the Active Data Service abstract class. This bean has registered with the application scope event handler that is notified from the model about any database changes. The activeOutputText has a clientListener that fires upon property changes. That means that it will fire (and invoke a Javascript function) whenever the active bean updates its state. The JavaScript function in this case will push a server event onto the queue that will be handled by a server listener, a method in bean on the server.

Implementation steps

These are steps for implementing the nudge based push of EMP changes to the UI:

Create serverListener (in the page) to link the server event to a server side bean method

Implement managed bean with method to handle server event by clearing the cache of the ViewObject (or making a boolean refreshIsInOrder available to the invokeAction that executes the ViewObject’s query action as was discussed in part one of this series).

The ActivePageNotifierBean is created, extending from the ADS base class BaseActiveDataModel and implementing the interface DataUpdateListenerI that was created to register listeners with the application scope DatabaseNotificationProcessor bean – the ones that routes through the EMP notifications received from the Model. When such a notification is handled, the processDataUpdate() method is invoked on the ActivePageNotifierBean and from this method, the triggerDataUpdate() method is called to handle updating the state of the Active bean.

Note how in the setupActiveData method – annotated with @PostConstruct, to be executed after the bean has been created by JSF – the object is registered as a listener with the DatabaseNotificationProcessor bean that has been injected.

The configuration in the faces-config.xml file for this bean:

Create activeOutputText bound to activeBean

The activeOutputText component has its value attribute bound to the state property of the ActivePageNotifierBean . This means that whenever the fireActiveDataUpdate() method is invoked inside the bean, the ADS push mechanism kicks in and pushes the change to the browser.

When changes are received from ADS in the activeOutputText, its value is updated and an associated clientListener for the propertyChange event would fire. Here we tie a call to JavaScript function activeDataCallback to this event.

Create JavaScript function that pushes the server event

Function activeDataCallback that is invoked from the clientListener is the function that will push the server event to be sent back to the server in what is the start of the required request onto which the changes we need in the UI can be piggy backed.

This function locates the outputText component in the page with id tableToRefresh. This component is required because it has the serverListener that provides our bridge from browser to client. When the component is located, a server event called refreshDataEvent is push on to the queue, targeted at the outputText component.

Create serverListener (in the page) to link the server event to a server side bean method

The serverListener attached to the outputText component finally handles the the refreshDataEvent pushed by the activeDataCallback JavaScript function by sending it to the server side dataRefresher bean’s refreshDataFromTable method:

The dataRefresher bean to enforce requery of the ViewObject

Next we implement the managed bean with method to handle server event by clearing the cache of the ViewObject (or making a boolean refreshIsInOrder available to the invokeAction that executes the ViewObject’s query action as was discussed in part one of this series).

And…Action

The application in action is not hugely spectacular, especially when all you see is screenshots. Just to give you a small taste I will show the browser with the Employees Table. Then the update (and commit) of EMP data in the database. Then the browser again, less than a second after committing the database transaction. I swear that I did not touch the browser nor did anything to make it refresh. The changes were pushed! Really!

The browser with the original table with Employee records:

Updating salaries and committing these changes in the database:

The browser with the changes pushed in:

Resources

Download the JDeveloper 11g (11.1.1.4) application with the complete example described in this article: ADFApplicationWithDBQRCN.

meta

Subscribe to Blog via Email

Enter your email address to subscribe to this blog and receive notifications of new posts by email.

Join 206 other subscribers

Email Address

About

AMIS is internationally recognized for its deep technological insight in Oracle technology. This knowledge is reflected in the presentations we deliver at international conferences such as Oracle OpenWorld, Hotsos and many user conferences around the world. Our AMIS Technology Blog, the most referred Oracle technology knowledge base outside the oracle.com domain. However you arrived here, we appreciate your interest in AMIS. Link to our Google+ Profile AMIS