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.
Our challenge here is the mechanism that informs the browser and puts into motion the mechanism that sends the server event. What we will be using is the nudge pattern (described in my presentation at JavaOne 2011 – http://www.slideshare.net/lucasjellema/dont-call-us-well-push-cross-tier-push-architecture-javaone-2011) where a UI component is nudged to have it initiate a request. The nudge itself does not do anything more than tell the browser that stuff is waiting for it.
This illustration describes the nudge pattern:
These are steps for implementing the nudge based push of EMP changes to the UI:
- Create activeBean that registers as listener with application scope event handler
- Create activeOutputText bound to activeBean
- 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).
Create activeBean that registers as listener with application scope event handler
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.
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 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).
The configuration of this bean in the faces-config.xml file:
The entire application architecture is outlined in this picture:
taken from the Oracle Open World 2011 presentation: http://www.slideshare.net/lucasjellema/push-to-the-limit-rich-and-proactive-user-interfaces-with-adf-oracle-open-world-2011.
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:
Download the JDeveloper 11g (188.8.131.52) application with the complete example described in this article: ADFApplicationWithDBQRCN.