21 Keeping Data Fresh Using TopLink Live Data Queries

This chapter describes how to use TopLink Live Data queries ("live queries") to monitor the backing data store for changes and then asynchronously deliver any modified data to the client application.

Use Case

Data in a backing data store is added, changed, or deleted after a TopLink-enabled application executes a query on it. It is important for the application to receive notification of the updates, without having to re-execute the query.

Solution

Use TopLink live queries in combination with Oracle Database Continuous Query Notification (CQN) and cache merge tracking to notify the client of data changes.

Components

Sample

For an example that illustrates the use of TopLink live queries with Oracle WebLogic Server Web Sockets, see the tlds.live.ws example from http://www.oracle.com/toplink/.

21.1 Introduction to the Solution

TopLink live data queries are used with Oracle Database Continuous Query Notification (CQN) and TopLink cache merge tracking to asynchronously notify the client application of changes in the backing data store. The database (and, optionally, the cache) are monitored for changes to data that match the criteria of the query, and those changes are returned to the client.

21.1.1 About Oracle Database CQN and TopLink Cache Tracking

CQN is a feature in the Oracle Database that allows an application to register queries with the database for change notifications. A query can be registered so that the database notifies the application whenever a transaction changes the result of the query. This kind of CQN notification is called a Query Result Change Notification (QRCN.)

Note:

In Oracle Database releases before 11g, the change notification feature was called Database Change Notification (DCN). In release 11g, the name was changed to Oracle Database Continuous Query Notification (CQN).

TopLink live queries take advantage of QRCN, so that any changes to data matching the criteria specified in the query are returned to the application through the implementation of a client notifier.

Note:

You must run the initial query and subscribe to changed results in two operations.

For more information about CQN and QRCN, see "Using Continuous Query Notification (CQN)" in Oracle Database Development Guide. In particular, see "Query Result Change Notification (QRCN)."

Cache subscriptions are provided through the oracle.toplink.dataservices.livedata.cache.CacheSubscriptionProvider class.

21.1.2 Creating and Using TopLink Live Data Queries

Provide the name of the query, subscribe to notifications based on events in the database (and, optionally in the cache), configure the subscription through a properties object

The key steps in setting up a live data query are:

  • Define an implementation of the ClientNotifier interface.

  • Create a properties object to configure a QRCN subscription.

  • Subscribe to the QRCN notification.

  • Specify the name of the named query to use. See Using Continuous Query Notification (CQN)" in Oracle Database Development Guide for guidelines on the kinds of queries supported by QRCN.

  • Specify the parameters for the query.

  • Create the subscription.

  • Add your implementation of ClientNotifier to the subscription.

  • Create and add an implementation of ClientNotifier.

In addition to subscribing to notifications based on events in the database, you can also subscribe to notifications based on events in the cache. Create the cache subscription with the same query, parameters and ClientNotifier as are used for the database subscription.

21.2 Implementing the Solution

This section contains the following tasks for setting up and using TopLink live queries to notify the client of data changes:

21.2.1 Step 1: Prerequisites

To use live queries, you must have the following:

  • Oracle Database 11.2.0.2 or later

  • TopLink 12c Release 1 (12.1.2) or later.

21.2.2 Step 2: Grant Database Privileges

Among other permissions, the database user must be granted the CHANGE NOTIFICATION privilege. To do this, you must have a DBA privilege, such as SYS, or have your database administrator apply it:

grant change notification to user

For information about granting Oracle Database privileges, see "Configuring Privilege and Role Authorization" in Oracle Database Security Guide.

21.2.3 Step 3: Create the Live Data Query and CQN Subscription

Create the live data query and the CQN subscription as exemplified in Example 21-1. This example shows the portion of a class definition that defines a subscription for a CQN notification with a given PersistenceContext.

Note:

A complete class definition would also include code for notifying the client and, optionally, logging. That is outside the scope of this chapter.

Example 21-1 Subscribing a TopLink Live Data Query to a CQN Notification

...
// Import TopLink Live Data classes
import oracle.toplink.dataservices.DataServicePersistenceContext;
import oracle.toplink.dataservices.livedata.Subscription;
import oracle.toplink.dataservices.livedata.SubscriptionFactory;
import oracle.toplink.dataservices.livedata.cache.CacheSubscriptionProvider;
import oracle.toplink.dataservices.livedata.notification.ClientNotifier;
import oracle.toplink.dataservices.livedata.notification.Notification;
import oracle.toplink.dataservices.livedata.notification.NotificationType;
import oracle.toplink.dataservices.livedata.qcn.QCNSubscriptionProvider;
import weblogic.websocket.WebSocketConnection;
...
// Client notifier code---
class Notifier implements ClientNotifier {
// The implementation of the client notifier)
...
}
 
// Notification subscription code---

// The name of the query.
private String queryName;

// The parameters associated with the query. 
private Map<String, String> parameters;

// The persistence context that this CQN notifier listens to.
private DataServicePersistenceContext persistenceContext;
 
 // Returns the query parameters associated with this notifer.
Map<String, String> getParameters() {
return this.parameters;
}

// Returns the name of the query that this notifier listens to.
String getQueryName() {
return this.queryName;
}
 
// Subscribe with the associated PersistenceContext, to listen to query result change events.
public void subscribe() {

   // properties object for configuation of the subscription
   Map<String, Object> properties = new HashMap<String, Object>();

   // subscribe to notifcation through Oracle CQN 
   properties.put(SubscriptionFactory.SUBSCRIPTION_TYPE, QCNSubscriptionProvider.QCN);
   properties.put(CacheSubscriptionProvider.QUERY_PARAMETERS, this.parameters);
   properties.put(CacheSubscriptionProvider.QUERY_NAME, this.queryName);
   Subscription subscription = this.persistenceContext.getSubscriptionFactory().
                                    getOrCreateSubscription(this.queryName, properties);
   // Register for QRCN subscription
   subscription.addClientNotifier(this);

   properties.put(SubscriptionFactory.SUBSCRIPTION_TYPE, CacheSubscriptionProvider.CACHE);
   subscription = this.persistenceContext.getSubscriptionFactory().
                       getOrCreateSubscription(this.queryName, properties);
   // Register for cache subscription
   subscription.addClientNotifier(this);
}
 
public String toString() {
return "Notifier [query = " + this.queryName + "]";
}
 
// Unsubscribe from the PersistenceContext listening to query result change events.
 */
public void unsubscribe() {
   Map<String, Object> properties = new HashMap<String, Object>();
   properties.put(SubscriptionFactory.SUBSCRIPTION_TYPE, QCNSubscriptionProvider.QCN);
   properties.put(CacheSubscriptionProvider.QUERY_PARAMETERS, this.parameters);
   properties.put(CacheSubscriptionProvider.QUERY_NAME, this.queryName);
   Subscription subscription = this.persistenceContext.getSubscriptionFactory().getSubscription(this.queryName, this.parameters);
   subscription.removeClientNotifier(this);
}
// Update the object with changes 
public void updatedObject(Object updatedObject) {
sendMessage(updatedObject, NotificationType.UPDATE);
}

21.3 Additional Resources

See the following for more information about TopLink live data queries: