3 Using JMS/XLA for Event Management

You can use the TimesTen JMS/XLA API (JMS/XLA) to monitor TimesTen for changes to specified tables in a local database and receive real-time notification of these changes. One of the purposes of JMS/XLA is to provide a high-performance, asynchronous alternative to triggers.

You can also use JMS/XLA to build a custom data replication solution, if the TimesTen replication solutions described in Oracle TimesTen In-Memory Database TimesTen to TimesTen Replication Guide do not meet your needs.

JMS/XLA implements Java Message Service (JMS) interfaces to make the functionality of the TimesTen Transaction Log API (XLA) available to Java applications. JMS information and resources are available at the following location:


In addition, the standard JMS API documentation is installed with the Oracle TimesTen In-Memory Database at the following location:


For information about tuning TimesTen JMS/XLA applications for improved performance, see "Tuning JMS/XLA applications".

This chapter includes the following topics:

JMS/XLA concepts

Java applications can use the JMS/XLA API to receive event notifications from TimesTen. JMS/XLA uses the JMS publish-subscribe interface to provide access to XLA updates.

You subscribe to updates by establishing a JMS Session that provides a connection to XLA and creating a durable subscriber (TopicSubscriber). You can receive and process messages synchronously through the subscriber, or you can implement a listener (MessageListener) to process the updates asynchronously.

JMS/XLA is designed for applications that want to monitor a local database. TimesTen and the application receiving the notifications must reside on the same system.


The JMS/XLA API supports persistent-mode XLA. In this mode, XLA obtains update records directly from the transaction log buffer or transaction log files, so the records are available until they are read. Persistent-mode XLA also allows multiple readers to access transaction log updates simultaneously.

This section includes the following topics:

How XLA reads records from the transaction log

As applications modify a database, TimesTen generates transaction log records that describe the changes made to the data and other events such as transaction commits.

New transaction log records are always written to the end of the transaction log buffer as they are generated. Transaction log records are periodically flushed in batches from the log buffer in memory to transaction log files on disk.

Applications can use XLA to monitor the transaction log for changes to the database. XLA reads through the transaction log, filters the log records, and delivers XLA applications with a list of transaction records that contain the changes to the tables and columns of interest.

XLA sorts the records into discrete transactions. If multiple applications are updating the database simultaneously, transaction log records from the different applications will be interleaved in the transaction log.

XLA transparently extracts all transaction log records associated with a particular transaction and delivers them in a contiguous list to the application.

Only the records for committed transactions are returned. They are returned in the order in which their final commit record appears in the transaction log. XLA filters out records associated with changes to the database that have not yet committed.

If a change is made but then rolled back, XLA does not deliver the records for the aborted transaction to the application.

Consider the example transaction log illustrated in Figure 3-1 and Example 3-1 that follow, which illustrate most of these basic XLA concepts.

Figure 3-1 Records extracted from the transaction log

Description of Figure 3-1 follows
Description of "Figure 3-1 Records extracted from the transaction log"

Example 3-1 Reading transaction log records

In this example, the transaction log contains the following records:

CT1 - Application C updates row 1 of table W with value 7.7.
BT1 - Application B updates row 3 of table X with value 2.
CT2 - Application C updates row 9 of table W with value 5.6.
BT2 - Application B updates row 2 of table Y with value "XYZ".
AT1 - Application A updates row 1 of table Z with value 3.
AT2 - Application A updates row 3 of table Z with value 4.
BT3 - Application B commits its transaction.
AT3 - Application A rolls back its transaction.
CT3 - Application C commits its transaction.

An XLA application that is set up to detect changes to tables W, Y, and Z would see the following:

BT2 and BT3 - Update row 2 of table Y with value "XYZ" and commit.
CT1 - Update row 1 of table W with value 7.7.
CT2 and CT3 - Update row 9 of table W with value 5.6 and commit.

This example demonstrates the following:

  • Transaction records for application B and application C all appear.

  • Though the records for application C begin to appear in the transaction log before those for application B, the commit for application B (BT3) appears in the transaction log before the commit for application C (CT3). As a result, the records for application B are returned to the XLA application ahead of those for application C.

  • The application B update to table X (BT1) is not presented because XLA is not set up to detect changes to table X.

  • The application A updates to table Z (AT1 and AT2) are never presented because it did not commit and was rolled back (AT3).

XLA and materialized views

You can use XLA to track changes to both tables and materialized views. A materialized view provides a single source from which you can track changes to selected rows and columns in multiple detail tables. Without a materialized view, the XLA application would have to monitor and filter the update records from all of the detail tables, including records reflecting updates to rows and columns of no interest to the application.

In general, there are no operational differences between the XLA mechanisms used to track changes to a table or a materialized view. However, for asynchronous materialized views, be aware that the order of XLA notifications for an asynchronous view is not necessarily the same as it would be for the associated detail tables, or the same as it would be for a synchronous view. For example, if there are two inserts to a detail table, they may be done in the opposite order in the asynchronous materialized view. Furthermore, updates may be treated as a delete followed by an insert, and multiple operations (such as multiple inserts or multiple deletes) may be combined. Applications that depend on ordering should not use asynchronous materialized views.

XLA bookmarks

An XLA bookmark marks the read position of an XLA subscriber application in the transaction log. Bookmarks facilitate durable subscriptions, enabling an application to disconnect from a topic and then reconnect to continue receiving updates where it left off.

How bookmarks work

When you create a message consumer for XLA, you always use a durable TopicSubscriber. The subscription identifier you specify when you create the subscriber is used as the XLA bookmark name. When you use the ttXlaSubscribe and ttXlaUnsubscribe built-in procedures through JDBC to start and stop XLA publishing for a table, you explicitly specify the name of the bookmark to be used.

Bookmarks are reset to the last read position whenever an acknowledgment is received. For more information about how update messages are acknowledged, see the "XLA acknowledgment modes".

You can remove a durable subscription by calling unsubscribe() on the JMS Session object. This deletes the corresponding XLA bookmark and forces a new subscription to be created when you reconnect. For more information see "Deleting bookmarks".

A bookmark subscription cannot be altered when it is in use. To alter a subscription, you must close the message consumer, alter the subscription using ttXlaSubscribe and ttXlaUnsubscribe, and open the message consumer.


You can also use the ttXlaBookmarkCreate TimesTen built-in procedure to create bookmarks. See "ttXlaBookmarkCreate" in Oracle TimesTen In-Memory Database Reference for information about that function.

Replicated bookmarks

If you are using an active standby pair replication scheme, you have the option of using replicated bookmarks, according to the replicatedBookmark attribute of the <topic> element in the jmsxla.xml file as discussed in "JMS/XLA configuration file and topics". For a replicated bookmark, operations on the bookmark are replicated to the standby database as appropriate, assuming there is suitable write privilege for the standby. This allows more efficient recovery of your bookmark positions if a failover occurs.

You can only read and acknowledge a replicated bookmark in the active database. Each time you acknowledge a replicated bookmark, the acknowledge operation is asynchronously replicated to the standby database.


Alternatively, if you use ttXlaBookmarkCreate to create a bookmark, that function has a bit you can set to specify a replicated bookmark.

Be aware of the following usage notes:

  • The position of the bookmark in the standby database will be very close to that of the bookmark in the active database; however, because the replication of acknowledge operations is asynchronous, you may see a small window of duplicate updates when there is a failover, depending on how often acknowledge operations are performed.

  • If replicated bookmarks exist at the time you enable the active standby pair scheme, the bookmarks will automatically be added to the replication scheme.

  • It is permissible to drop the active standby pair scheme while replicated bookmarks exist. The bookmarks will cease to be replicated at that point.

  • You cannot delete replicated bookmarks while the replication agent is running.

JMS/XLA configuration file and topics

To connect to XLA, you establish a connection to a JMS Topic object that corresponds to a particular database. The JMS/XLA configuration file provides the mapping between topic names and databases.

You can specify a replicated bookmark by setting replicatedBookmark="yes" in the <topic> element when you specify the topic. The default setting is "no". Also see "XLA bookmarks".

By default, JMS/XLA looks for a configuration file named jmsxla.xml in the current working directory. If you want to use another name or location for the file, you must specify it as part of the environment variable in the InitialContext class and add the location to the classpath.

Example 3-2 Specifying the JMS/XLA configuration file

The following code specifies the configuration file as part of the environment variable in the InitialContext class.

Hashtable env = new Hashtable();
env.put(XlaConstants.CONFIG_FILE_NAME, "/newlocation.xml");
InitialContext ic = new InitialContext(env);

The JMS/XLA API uses the class loader to locate the JMS/XLA configuration file if XlaConstants.CONFIG_FILE_NAME is set. In this example, the JMS/XLA API searches for the newlocation.xml file in the top directory in both the location specified in the CLASSPATH environment variable and in the JAR files specified in the CLASSPATH variable.

The JMS/XLA configuration file can also be located in subdirectories, as follows:


In this case, the JMS/XLA API searches for the deepinside.xml file in the com/mycompany/myapplication subdirectory in both the location specified in the CLASSPATH environment variable and in the JAR files specified in the CLASSPATH variable.

The JMS/XLA API uses the first configuration file that it finds.

Example 3-3 Defining a topic in the configuration file

A topic definition in the configuration file consists of a name, a connection string, and a prefetch value that specifies how many updates to retrieve at a time.

For example, the configuration file shown here maps the DemoDataStore topic to the TestDB DSN:

    <topic name="DemoDataStore"
      xlaPrefetch="100" />

Example 3-4 Defining a topic to use replicated bookmarks

A topic definition can also specify whether a replicated bookmark should be used. The following repeats the preceding example, but with a replicated bookmark.

    <topic name="DemoDataStore"
      xlaPrefetch="100" replicatedBookmark="yes" />

XLA updates

Applications receive XLA updates as JMS MapMessage objects. The MapMessage contains a set of typed name and value pairs that correspond to the fields in an XLA update header.

You can access the message fields using the MapMessage getter methods. The getMapNames() method returns an Enumeration object that contains the names of all of the fields in the message. You can retrieve individual fields from the message by name. All reserved field names begin with two underscores, for example __TYPE.

All update messages have a __TYPE field that indicates what type of update the message contains. The types are specified as integer values. As a convenience, you can use the constants defined in com.timesten.dataserver.jmsxla.XlaConstants to compare against the integer types. The supported types are described in Table 3-1.

Table 3-1 XLA update types

Update type Description


A row has been added.


A row has been modified.


A row has been removed.


A transaction has been committed.


A table has been created.


A table has been dropped.


An index has been created.


An index has been dropped.


New columns have been added to the table.


Columns have been removed from the table.


A materialized view has been created.


A materialized view has been dropped.


A sequence has been created.


A sequence has been dropped.


A synonym has been created.


A synonym has been dropped.


The table has been truncated and all rows in the table have been deleted.

For more information about the contents of an XLA update message, see "JMS/XLA MapMessage contents".

XLA acknowledgment modes

The XLA acknowledgment mechanism is designed to ensure that an application has not only received a message, but has successfully processed it. Acknowledging an update permanently resets the application's XLA bookmark to the last record that was read. This prevents previously returned records from being reread, ensuring that an application does not receive previously acknowledged records if the bookmark is reused when an application reconnects to XLA.

JMS/XLA can automatically acknowledge XLA update messages, or applications can choose to acknowledge messages explicitly. You specify how updates are to be acknowledged when you create the Session object.

JMS/XLA supports three acknowledgment modes:

  • AUTO_ACKNOWLEDGE: In this mode, updates are automatically acknowledged as you receive them. Each message is delivered only once. Duplicate messages will not be sent, so messages might be lost if there is an application failure. Messages are always delivered and acknowledged individually, so JMS/XLA does not prefetch multiple records. The xlaprefetch attribute in the topic is ignored.

  • DUPS_OK_ACKNOWLEDGE: In this mode, updates are automatically acknowledged, but duplicate messages might be delivered when there is an application failure. JMS/XLA prefetches records according to the xlaprefetch attribute specified for the topic and sends an acknowledgment when the last record in a prefetched block is read. If the application fails before reading all of the prefetched records, all of the records in the block are presented to the application it restarts.

  • CLIENT_ACKNOWLEDGE: In this mode, applications are responsible for acknowledging receipt of update messages by calling acknowledge() on the MapMessage. JMS/XLA prefetches records according to the xlaprefetch attribute specified for the topic.

Prefetching updates

Prefetching multiple update records at a time is more efficient than obtaining each update record from XLA individually. Because updates are not prefetched when you use AUTO_ACKNOWLEDGE mode, it can be slower than the other modes. If possible, you should design the application to tolerate duplicate updates so you can use DUPS_OK_ACKNOWLEDGE, or explicitly acknowledge updates. Explicitly acknowledging updates usually yields the best performance, as long as you can avoid acknowledging each message individually.

Acknowledging updates

To explicitly acknowledge an XLA update, call acknowledge() on the update message. Acknowledging a message implicitly acknowledges all previous messages. Typically, you receive and process multiple update messages between acknowledgments. If you are using the CLIENT_ACKNOWLEDGE mode and intend to reuse a durable subscription in the future, you should call acknowledge() to reset the bookmark to the last-read position before exiting.

Access control impact on XLA

"Considering TimesTen features for access control" provides a brief overview of how TimesTen access control affects operations in the database. Access control includes impact on XLA, as follows:

  • Any XLA functionality requires the system privilege XLA. This includes connecting to TimesTen as an XLA reader and executing the TimesTen XLA built-in procedures ttXlaBookmarkCreate, ttXlaBookmarkDelete, ttXlaSubscribe, and ttXlaUnsubscribe, all of which are documented in "Built-In Procedures" in Oracle TimesTen In-Memory Database Reference.

  • A user with the XLA privilege has capabilities equivalent to the SELECT ANY TABLE and SELECT ANY SEQUENCE system privileges.

JMS/XLA and Oracle GDK dependency

The JMS/XLA API uses orai18n.jar, part of the Oracle Globalization Development Kit (GDK) for translating from the database character set specified by the DatabaseCharacterSet attribute to UTF-16 encoding. The JMS/XLA API supports a specific version of the GDK with each TimesTen release. If JMS/XLA finds other versions of the GDK loaded in the JVM, it displays a severe warning and continues processing. You can find out the GDK version supported by JMS/XLA by entering the following commands:

$ cd install_dir/lib
$ java -cp ./orai18n.jar oracle.i18n.util.GDKOracleMetaData -version

Also see "Compiling Java applications".

Connecting to XLA

To connect to XLA so you can receive updates, use a JMS connection factory to create a connection. Then use the connection to establish a session. When you are ready to start processing updates, call start() on the connection to enable message dispatching. This is shown in Example 3-5 that follows, from the syncJMS Quick Start demo.

Example 3-5 Connecting to XLA

/** JMS connection */
private javax.jms.TopicConnection connection; 
/** JMS session */
private TopicSession session; 
// get Connection
Context messaging = new InitialContext(); 
TopicConnectionFactory connectionFactory =
connection = connectionFactory.createTopicConnection(); 
// get Session
session = connection.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);

Monitoring tables for updates

Before you can start receiving updates, you must specify to XLA which tables you want to monitor for changes.

To subscribe to changes and turn on XLA publishing for a table, call the ttXlaSubscribe built-in procedure through JDBC.

When you use ttXlaSubscribe to enable XLA publishing for a table, you must specify parameters for the name of the table and the name of the bookmark that will be used to track the table:

ttXlaSubscribe(user.table, mybookmark)

For example, call ttXlaSubscribe by the JDBC CallableStatement interface:

Connection con;

CallableStatement cStmt;
cStmt = con.prepareCall("{call ttXlaSubscribe(user.table, mybookmark)}");

Use ttXlaUnsubscribe to unsubscribe from the table during shutdown. For more information, see "Unsubscribing from a table".

The application can verify table subscriptions by checking the SYS.XLASUBSCRIPTIONS system table.

For more information about using TimesTen built-in procedures in a Java application, see "Using CALL to execute procedures and functions".

Receiving and processing updates

You can receive XLA updates either synchronously or asynchronously.

To receive and process updates for a topic synchronously, perform the following tasks.

  1. Create a durable TopicSubscriber instance to subscribe to a topic.

  2. Call receive() or receiveNoWait() on your subscriber to get the next available update.

  3. Process the returned MapMessage instance.

To receive and process updates for a topic asynchronously, perform the following tasks.

  1. Create a MessageListener instance to process the updates.

  2. Create a durable TopicSubscriber instance to subscribe to a topic.

  3. Register the MessageListener with the TopicSubscriber.

  4. Start the connection.


    You may miss messages if you do not register the MessageListener before you start the connection. If the connection is already started, stop the connection, register the MessageListener, then start the connection.
  5. Wait for messages to arrive. You can call the Object method wait() to wait for messages if your application does not have to do anything else in its main thread.

When an update is published, the MessageListener method onMessage() is called and the message is passed in as a MapMessage instance.

The application can verify table subscriptions by checking the SYS.XLASUBSCRIPTIONS system table.

Example 3-6, from the asyncJMS Quick Start demo, uses a listener to process updates asynchronously.

Example 3-6 Using a listener to process updates asynchronously

MyListener myListener = new MyListener(outStream);

outStream.println("Creating consumer for topic " + topic);
Topic xlaTopic = session.createTopic(topic);
bookmark = "bookmark";
TopicSubscriber subscriber = session.createDurableSubscriber(xlaTopic, bookmark);

// After setMessageListener() has been called, myListener's onMessage
// method will be called for each message received.

Note that bookmark must already exist. You can use JDBC and the ttXlaBookmarkCreate built-in procedure to create a bookmark. Also, the TopicSubscriber must be a durable subscriber. XLA connections are designed to be durable. XLA bookmarks make it possible to disconnect from a topic and then reconnect to start receiving updates where you left off. The string you pass in as the subscription identifier when you create a durable subscriber is used as the XLA bookmark name.

You can call unsubscribe() on the JMS TopicSession to delete the XLA bookmark used by the subscriber when the application shuts down. This causes a new bookmark to be created when the application is restarted.

When you receive an update, you can use the MapMessage getter methods to extract information from the message and then perform whatever processing your application requires. The TimesTen XlaConstants class defines constants for the update types and special message fields for use in processing XLA update messages.

The first step is typically to determine what type of update the message contains. You can use the MapMessage method getInt() to get the contents of the __TYPE field, and compare the value against the numeric constants defined in the XlaConstants class.

In Example 3-7, from the asyncJMS Quick Start demo, the method onMessage() extracts the update type from the MapMessage object and displays the action that the update signifies.

Example 3-7 Determining the update type

public void onMessage(Message message)
  MapMessage mapMessage = (MapMessage)message;
  String messageType = null;
  /** Standard output stream */
  private static PrintStream outStream = System.out;
  if (message == null)
    errStream.println("MyListener: update message is null");
    return ;
    outStream.println("onMessage: got a " + mapMessage.getJMSType() + " message");
    // Get the type of event (insert, update, delete, drop table, etc.).
    int type = mapMessage.getInt(XlaConstants.TYPE_FIELD);
    if (type == XlaConstants.INSERT)
      outStream.println("A row was inserted.");
    else if (type == XlaConstants.UPDATE)
      outStream.println("A row was updated.");
    else if (type == XlaConstants.DELETE)
      outStream.println("A row was deleted.");
      // Messages are also received for DDL events such as CREATE TABLE.
      // This program processes INSERT, UPDATE, and DELETE events,
      // and ignores the DDL events.
      return ;

When you know what type of message you have received, you can process the message according to the application's needs. To get a list of all of the fields in a message, you can call the MapMessage method getMapNames(). You can retrieve individual fields from the message by name.

Example 3-8, from the asyncJMS Quick Start demo, extracts the column values from insert, update, and delete messages using the column names.

Example 3-8 Extracting column values

/** Standard output stream */
private static PrintStream outStream = System.out;
if (type == XlaConstants.INSERT 
 || type == XlaConstants.UPDATE 
 || type == XlaConstants.DELETE)
  // Get the column values from the message.
  int cust_num = mapMessage.getInt("cust_num");
  String region = mapMessage.getString("region");
  String name = mapMessage.getString("name");
  String address = mapMessage.getString("address");
  outStream.println("New Column Values:");
  outStream.println("cust_num=" + cust_num);
  outStream.println("region=" + region);
  outStream.println("name=" + name);
  outStream.println("address=" + address);

For detailed information about the contents of XLA update messages, see "JMS/XLA MapMessage contents". For information about how TimesTen column types map to JMS data types and the getter methods used to retrieve the column values, see "Data type support".

Terminating a JMS/XLA application

When the XLA application has finished reading from the transaction log, it should gracefully exit by closing the XLA connection, deleting any unneeded bookmarks, and unsubscribing from any tables to which you explicitly subscribed.

Closing the connection

To close the connection to XLA, call close() on the Connection object.

After a connection has been closed, any attempt to use it, its sessions, or its subscribers will throw an IllegalStateException. You can continue to use messages received through the connection, but you cannot call the acknowledge() method on the received message after the connection is closed.

Deleting bookmarks

Deleting XLA bookmarks during shutdown is optional. Deleting a bookmark enables the disk space associated with any unread update records in the transaction log to be freed.

If you do not delete the bookmark, it can be reused by a durable subscriber. If the bookmark is available when a durable subscriber reconnects, the subscriber will receive all unacknowledged updates published since the previous connection was terminated. Keep in mind that when a bookmark exists with no application reading from it, the transaction log will continue to grow and the amount of disk space consumed by your database will increase.

To delete a bookmark, you can simply call unsubscribe on the JMS Session, which invokes the ttXlaBookmarkDelete built-in procedure to remove the XLA bookmark.


You cannot delete replicated bookmarks while the replication agent is running.

Unsubscribing from a table

To turn off XLA publishing for a table, use the ttXlaUnsubscribe built-in procedure. If you use ttXlaSubscribe to enable XLA publishing for a table, you should use ttXlaUnsubscribe to unsubscribe from the table when shutting down your application.


If you want to drop a table, you must unsubscribe from it first.

When you unsubscribe from a table, specify the name of the table and the name of the bookmark used to track the table:

ttXlaUnsubscribe(user.table, mybookmark)

The following example calls ttXlaUnSubscribe through a CallableStatement object.

Example 3-9 Unsubscribing from a table

Connection con;

CallableStatement cStmt;
cStmt = con.prepareCall("{call ttXlaUnSubscribe(user.table, mybookmark)}");

For more information about using TimesTen built-in procedures in a Java application, see "Using CALL to execute procedures and functions".

Using JMS/XLA as a replication mechanism

If the TimesTen replication solutions described in Oracle TimesTen In-Memory Database TimesTen to TimesTen Replication Guide do not meet your needs, you can use JMS/XLA to replicate updates from a source database to a target database.

Applying JMS/XLA messages to a target database

The source database generates JMS/XLA messages. To apply the messages to a target database, you must extract the XLA descriptor from them. Use the MapMessage interface to extract the update descriptor:

MapMessage message;
 *...other code
try {
catch (JMSException jex){
 *...other code

The target database may reside on a different system from the source database. The update descriptor is returned as a byte array and can be serialized for network transmission.

You must create a target database object that represents the target database so you can apply the objects from the source database. You can create a target database object named myTargetDataStore as an instance of the TargetDataStoreImpl class. For example:

TargetDataStore myTargetDataStore=
   new TargetDataStoreImpl("DSN=sampleDSN");

Apply messages to myTargetDataStore by using the TargetDataStore method apply(). For example:


By default, TimesTen checks for conflicts on the target database before applying the update. If the target database has information that is later than the update, TargetDataStore throws an exception. If you do not want TimesTen to check for conflicts, use the TargetDataStore method setUpdateConflictCheckFlag() to change the behavior.

By default, TimesTen commits the update to the database based on commit flags and transaction boundaries contained in the update descriptor. If you want the application to perform manual commits instead, use the setAutoCommitFlag() method to change the autocommit flag. To perform a manual commit on myTargetDataStore, use the following command:


You can perform a rollback if errors occur during the application of the update. Use the following command for myTargetDataStore:


Close myTargetDataStore by using the following command:


See "JMS/XLA replication API" for more information about the TargetDataStore interface.

TargetDataStore error recovery

Invoking TargetDataStore can yield transient and permanent errors.

TargetDataStore methods return a nonzero value when transient errors occur. The application can retry the operation and is responsible for monitoring update descriptors that must be reapplied. For more information about transient XLA errors, see "Handling XLA errors" in Oracle TimesTen In-Memory Database C Developer's Guide.

TargetDataStore methods return a JMSException object for permanent errors. If the application receives a permanent error, it should verify that the database is valid. If the database is invalid, the target database object should be closed and a new one should be created. Other types of permanent errors may require manual intervention.

The following example shows how to recover errors from a TargetDataStore object.

Example 3-10 Recovering errors

TargetDataStore theTargetDataStore;
byte[] updateDescriptor;
int rc;

// Other code
try {
  if ( (rc = theTargetDataStore.apply(updateDescriptor) ) == 0 ) {
    // apply successful
  else {
    // Transient error. Retry later.
catch (JMSException jex) {
  if (theTargetDataStore.isDataStoreValid() ) {
    // Database valid; permanent error that may need Administrator intervention.
  else {
    try {
  catch (JMSException closeEx) {
    // Close errors are not usual. This may need Administrator intervention.