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:
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 );
Durable subscribers cannot be configured with a direct connection to WebSphere MQ Event Broker.
Creating a durable subscriber is very 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 wish 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.
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 );
It is possible to 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 );
You can combine the subscriber variations, so that you can create a durable subscriber that applies a selector and ignores local publications, if you wish to. 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 );
Subscriber queues cannot be configured for a direct connection to WebSphere MQ Event Broker.
With WebSphere MQ JMS from V5.2, there are two ways in which you can configure subscribers:
Each subscriber has an exclusive queue assigned to it, from which it retrieves all its messages. JMS creates a new queue for each subscriber. This is the only approach available with WebSphere MQ JMS V1.1.
A subscriber uses a shared queue, from which it, and other subscribers, retrieve their messages. This approach requires only one queue to serve multiple subscribers. This is the default approach used with WebSphere MQ JMS from V5.2.
From WebSphere MQ JMS V5.2, 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:
A WebSphere MQ queue cannot hold more than 640000 messages, and in the shared queue approach, this must be divided between all the subscribers that share the queue. This issue is more significant for durable subscribers, because the lifetime of a durable subscriber is usually much longer than that of a non-durable subscriber. Therefore, more messages might accumulate for a durable subscriber.
For certain application types, administrators may wish to monitor the state and depth of particular subscriber queues. This task is much simpler when there is one to one mapping between a subscriber and a queue.
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.
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:
SYSTEM.JMS.ND.
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:
SYSTEM.JMS.ND.MYDOMAIN.*
The characters that precede the * character are used as the prefix, so that all dynamic queues that are associated with this subscription will have queue names that start with SYSTEM.JMS.ND.MYDOMAIN.
As discussed earlier, there may 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 un-retrieved 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:
// Set the MQTopic durable subscriber queue name using // the multi-queue approach sportsTopic.setBrokerDurSubQueue("SYSTEM.JMS.D.FOOTBALL.*");
Once the Topic object is initialized, it is passed into the TopicSession createDurableSubscriber() method to create the specified subscription:
// Create a durable subscriber using our earlier Topic TopicSubscriber sub = new session.createDurableSubscriber (sportsTopic, "D_SUB_SPORT_001");
For durable subscriptions, the queue name you provide should start with the following characters:
SYSTEM.JMS.D.
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:
SYSTEM.JMS.D.MYDOMAIN.*
The characters that precede the * character are used as the prefix, so that all dynamic queues that are associated with this subscription will have queue names that start with SYSTEM.JMS.D.MYDOMAIN.
Note that you can not 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, you should first delete the old subscriber (using the unsubscribe() method) and create the subscription again from new. This will remove any unconsumed messages on the durable subscription.
There is no subscription store with a direct connection to WebSphere MQ Event Broker.
WebSphere MQ JMS maintains a persistent store of subscription information, used to resume durable subscriptions and cleanup after failed non-durable subscribers. Before WebSphere MQ JMS 5.2.1, this information was stored using messages on system queues on the application's local queue manager; from WebSphere MQ JMS 5.2.1 this information can be managed by the publish/subscribe broker. This new subscription store requires recent levels of both queue manager and publish/subscribe broker. It is designed to provide improved resilience.
Please see the readme provided with WebSphere MQ JMS for information about suitable levels of queue manager and 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.
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 may cause the queue manager logs to fill up and this will result 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, the STATREFRESHINT property on the TopicConnectionFactory can be reduced. This will cause the long-running transaction to be refreshed more frequently, allowing the logs to reset themselves.
After a non-durable subscriber has failed, information is left on the two SYSTEM.JMS queues which allows a later JMS application to cleanup after the failed subscriber. See Subscriber cleanup utility for more information.
After failure of a non-durable subscriber, messages will continue to be delivered to the subscriber until a later JMS application is executed.
SUBSTORE(QUEUE) is provided for compatibility with versions of WebSphere MQ JMS before 5.2.1.
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 cleanup 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. The actions performed by cleanup can be customised using the CLEANUP property on the TopicConnectionFactory.
See Subscriber cleanup utility for more information about the different behaviours of cleanup with SUBSTORE(BROKER).
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) then this will behave as SUBSTORE(BROKER); otherwise it will behave as SUBSTORE(QUEUE). Additionally, SUBSTORE(MIGRATE) will transfer 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 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.
Except when SUBSTORE(MIGRATE) is used, the two subscription stores are entirely independent.
A durable subscription will be 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 will be created.
When a connection uses SUBSTORE(MIGRATE), subscription information will automatically be 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 will not be able to complete and an exception will be thrown from createDurableSubscriber().
Hence, once a subscription has been migrated, it is important that the subscription is not accessed 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).
In order for SUBSTORE(BROKER) to function, or for SUBSTORE(MIGRATE) to use the broker-based subscription store, suitable versions of both Queue Manager and broker need to be available to WebSphere MQ JMS. Please refer to the readme for information regarding suitable levels.