Subscriber options

There are a number of different ways to use JMS subscribers. This section describes some examples of their use.

JMS provides two types of subscribers:

Non-durable subscribers
These subscribers receive messages on their chosen topic, only if the messages are published while the subscriber is active.
Durable subscribers
These subscribers receive all the messages published on a topic, including those that are published while the subscriber is inactive.

Creating non-durable subscribers

The subscriber created in Create consumers and producers of publications is non-durable and is created with the following code:

// Create a subscriber, subscribing on the given topic
 TopicSubscriber sub = session.createSubscriber( topic );

Creating durable subscribers

Durable subscribers cannot be configured with a direct connection to a broker.

Creating a durable subscriber is similar to creating a non-durable subscriber, but you must also provide a name that uniquely identifies the subscriber:

// Create a durable subscriber, supplying a uniquely-identifying name
TopicSubscriber sub = session.createDurableSubscriber( topic, "D_SUB_000001" );

Non-durable subscribers automatically deregister themselves when their close() method is called (or when they fall out of scope). However, if you want to terminate a durable subscription, you must explicitly notify the system. To do this, use the session's unsubscribe() method and pass in the unique name that created the subscriber:

// Unsubscribe the durable subscriber created above
session.unsubscribe( "D_SUB_000001" );

A durable subscriber is created at the queue manager specified in the MQTopicConnectionFactory queue manager parameter. If there is a subsequent attempt to create a durable subscriber with the same name at a different queue manager, a new and completely independent durable subscriber is returned.

Using message selectors

You can use message selectors to filter out messages that do not satisfy given criteria. For details about message selectors, see Message selectors. Message selectors are associated with a subscriber as follows:

// Associate a message selector with a non-durable subscriber
String selector = "company = 'IBM'";
TopicSubscriber sub = session.createSubscriber( topic, selector, false );

You can control whether the JMS client or the broker performs message filtering by setting the MessageSelection property on the TopicConnectionFactory. If the broker is capable of performing message selection, it is generally preferable to let the broker do it because it reduces the number of messages sent to your client. However, if the broker is very heavily loaded, it might be preferable to let the client perform message selection instead.

Suppressing local publications

You can create a subscriber that ignores publications that are published on the subscriber's own connection. Set the third parameter of the createSubscriber call to true, as follows:

// Create a non-durable subscriber with the noLocal option set
TopicSubscriber sub = session.createSubscriber( topic, null, true );

Combining the subscriber options

You can combine the subscriber variations, so that you can create a durable subscriber that applies a selector and ignores local publications. The following code fragment shows the use of the combined options:

// Create a durable, noLocal subscriber with a selector applied
String selector = "company = 'IBM'";
TopicSubscriber sub = session.createDurableSubscriber( topic, "D_SUB_000001",
                                                      selector, true );

Configuring the base subscriber queue

Subscriber queues cannot be configured for a direct connection to a broker.

There are two ways in which you can configure subscribers:

You can choose which approach to use, and configure which queues to use.

In general, the shared queue approach gives a modest performance advantage. For systems with a high throughput, there are also large architectural and administrative advantages, because of the significant reduction in the number of queues required.

In some situations, there are still good reasons for using the multiple queue approach:

Default configuration

The default configuration uses the following shared subscription queues:

These are created for you when you run the MQJMS_PSQ.MQSC script.

If required, you can specify alternative physical queues. You can also change the configuration to use the multiple queue approach.

Configuring non-durable subscribers

You can set the non-durable subscriber queue name property in either of the following ways:

For non-durable subscriptions, the queue name you provide should start with the following characters:

To select a shared queue approach, specify an explicit queue name, where the named queue is the one to use for the shared queue. The queue that you specify must already physically exist before you create the subscription.

To select the multiple queue approach, specify a queue name that ends with the * character. Subsequently, each subscriber that is created with this queue name creates an appropriate dynamic queue, for exclusive use by that particular subscriber. MQ JMS uses its own internal model queue to create such queues. Therefore, with the multiple queue approach, all required queues are created dynamically.

When you use the multiple queue approach, you cannot specify an explicit queue name. However, you can specify the queue prefix. This enables you to create different subscriber queue domains. For example, you could use:

The characters that precede the * character are used as the prefix, so that all dynamic queues that are associated with this subscription have queue names that start with SYSTEM.JMS.ND.MYDOMAIN.

Configuring durable subscribers

As discussed earlier, there might still be good reasons to use the multiple queue approach for durable subscriptions. Durable subscriptions are likely to have a longer life span, so it is possible that a large number of unretrieved messages could accumulate on the queue.

Therefore, the durable subscriber queue name property is set in the Topic object (that is, at a more manageable level than TopicConnectionFactory). This enables you to specify a number of different subscriber queue names, without needing to re-create multiple objects starting from the TopicConnectionFactory.

You can set the durable subscriber queue name in either of the following ways:

For durable subscriptions, the queue name you provide must start with the following characters:

To select a shared queue approach, specify an explicit queue name, where the named queue is the one to use for the shared queue. The queue that you specify must already physically exist before you create the subscription.

To select the multiple queue approach, specify a queue name that ends with the * character. Subsequently, each subscriber that is created with this queue name creates an appropriate dynamic queue, for exclusive use by that subscriber. MQ JMS uses its own internal model queue to create such queues. Therefore, with the multiple queue approach, all required queues are created dynamically.

When you use the multiple queue approach, you cannot specify an explicit queue name. However, you can specify the queue prefix. This enables you to create different subscriber queue domains. For example, you could use:

The characters that precede the * character are used as the prefix, so that all dynamic queues that are associated with this subscription have queue names that start with SYSTEM.JMS.D.MYDOMAIN.

You cannot change the queue used by a durable subscriber. To do so, for example to move from the multiple queue approach to the single queue approach, first delete the old subscriber (using the unsubscribe() method) and create the subscription again from new. This removes any unconsumed messages on the durable subscription.

Subscription stores

There is no subscription store with a direct connection to a broker.

WebSphere MQ JMS maintains a persistent store of subscription information, used to resume durable subscriptions and cleanup after failed non-durable subscribers. This information can be managed by the publish/subscribe broker.

The choice of subscription store is based on the SUBSTORE property of the TopicConnectionFactory. This takes one of three values: QUEUE, BROKER, or MIGRATE.

SUBSTORE(QUEUE)
Subscription information is stored on SYSTEM.JMS.ADMIN.QUEUE and SYSTEM.JMS.PS.STATUS.QUEUE on the local queue manager.

WebSphere MQ JMS maintains an extra connection for a long-running transaction used to detect failed subscribers. There is a connection to each queue manager in use. In a busy system, this might cause the queue manager logs to fill up, resulting in errors from both the queue manager and its applications.

If you experience these problems, the system administrator can add extra log files or datasets to the queue manager. Alternatively, reduce the STATREFRESHINT property on the TopicConnectionFactory. This causes the long-running transaction to be refreshed more frequently, allowing the logs to reset themselves.

After a non-durable subscriber has failed:

SUBSTORE(QUEUE) is provided for compatibility with versions of MQSeries JMS.

SUBSTORE(BROKER)
Subscription information is stored by the publish/subscribe broker used by the application. This option is designed to provide improved resilience.

When a non-durable subscriber fails, the subscription is deregistered from the broker as soon as possible. The broker adds a response to this deregistration onto the SYSTEM.JMS.REPORT.QUEUE, which is used to clean up after the failed subscriber. With SUBSTORE(BROKER), a separate cleanup thread is run regularly in the background of each JMS publish/subscribe application.

Cleanup is run once every 10 minutes by default, but you can change this using the CLEANUPINT property on the TopicConnectionFactory. To customize the actions performed by cleanup, use the CLEANUP property on the TopicConnectionFactory.

See Subscriber cleanup utility for more information about the different behaviors of cleanup with SUBSTORE(BROKER).

SUBSTORE(MIGRATE)
MIGRATE is the default value for SUBSTORE.

This option dynamically selects the queue-based or broker-based subscription store based on the levels of queue manager and publish/subscribe broker installed. If both queue manager and broker are capable of supporting SUBSTORE(BROKER), this behaves as SUBSTORE(BROKER); otherwise it behaves as SUBSTORE(QUEUE). Additionally, SUBSTORE(MIGRATE) transfers durable subscription information from the queue-based subscription store to the broker-based store.

This provides an easy migration path from older versions of WebSphere MQ JMS, WebSphere(R) MQ, and publish/subscribe broker. This migration occurs the first time the durable subscription is opened when both queue manager and broker are capable of supporting the broker-based subscription store. Only information relating to the subscription being opened is migrated; information relating to other subscriptions is left in the queue-based subscription store.

Migration and coexistence considerations

Except when SUBSTORE(MIGRATE) is used, the two subscription stores are entirely independent.

A durable subscription is created in the store specified by the TopicConnectionFactory. If there is a subsequent attempt to create a durable subscriber with the same name and ClientID but with the other subscription store, a new durable subscription is created.

When a connection uses SUBSTORE(MIGRATE), subscription information is automatically transferred from the queue-based subscription store to the broker-based subscription store when createDurableSubscriber() is called. If a durable subscription with matching name and ClientID already exists in the broker-based subscription store, this migration cannot complete and an exception is thrown from createDurableSubscriber().

Once a subscription has been migrated, it is important not to access the subscription from an application using an older version of WebSphere MQ JMS, or an application running with SUBSTORE(QUEUE). This would create a subscription in the queue-based subscription store, and prevent an application running with SUBSTORE(MIGRATE) from using the subscription.

To recover from this situation, either use SUBSTORE(BROKER) from your application or unsubscribe from the subscription with SUBSTORE(QUEUE).