users@jms-spec.java.net

[jms-spec users] [jsr343-experts] Re: (JMS_SPEC-40) Allow multiple threads in same client to consume messages from the same topic subscription

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Tue, 03 Apr 2012 15:57:42 +0100

I'd like to return to this issue, which we last discussed back in August last year:
On 05/08/2011 15:37, Nigel Deakin wrote:
> I have logged this JIRA issue:
> http://java.net/jira/browse/JMS_SPEC-40

I made some detailed proposals at the time, which seemed to be acceptable to this group, though I didn't have time to
take these forward and add them to the Early Draft. I've reviewed these proposals and updated them to reflect the
current state of the simplified API.

Here's the current proposal. To see a formatted version which is somewhat easier to read, please see the JIRA issue. Any
further comments? Do the JMS implementers on this group see any issues with this that I may have missed?

Description
===========

This proposal would allow multiple message consumers to be used to consume messages from the same durable or non-durable
topic subscription. This would increase scalability by allowing messages from a topic to be processed by multiple
consumers in a Java SE environment. Note that the existing JMS 1.1 API already allows this to be achieved for messages
from a queue.

The multiple consumers might be in the same or different JVMs. Within the same JVM, the multiple consumers might use the
same or different sessions and connection. Note, however, that the normal restrictions on the use of a session by
multiple threads would continue to apply.

Durable subscriptions
---------------------

For durable subscriptions, there would be no need to change the existing API. Applications would simply be allowed to
create multiple consumers on the same durable subscription:

This affects the following JMS existing JMS 2.1 methods on Session (and its subtypes QueueSession, TopicSession,
XASession, XAQueueSession and XATopicSession):

    createDurableSubscriber(Topic topic, String name)
    createDurableSubscriber(Topic topic, String name, String messageSelector, boolean noLocal)

It also affects the following JMS new JMS 2.0 methods on Session (and its subtypes QueueSession, TopicSession,
XASession, XAQueueSession and XATopicSession) (added in JIRA issue 51 (http://java.net/jira/browse/JMS_SPEC-51):

    createDurableConsumer(Topic topic, String name)
    createDurableConsumer(Topic topic, String name, String messageSelector, boolean noLocal)


And in the new JMS 2.0 simplified API, it also affects the following method on JMSContext:

    createDurableConsumer(Topic topic, String name)
    createDurableConsumer(Topic topic, String name, String messageSelector, boolean noLocal)

All these methods currently have a restriction "Only one session at a time can have a TopicSubscriber for a particular
durable subscription.". This restriction would be removed.

No change is proposed to the existing JMS requirement that only one connection may have a given clientID. This is
defined in JMS 1.1 Section 4.4.3.2 "Client identifier", which states:

    "By definition, the client state identified by a client identifier can be 'in use' by only one client at a time.
    A JMS provider must prevent concurrently executing clients from using it."

This means that if a durable subscription is created by a connection with clientId set then it will not be possible to
create a second consumer on it using a different connection.

However in JMS 2.0, clientId will become optional when creating a durable subscription (see JIRA issue 39
(http://java.net/jira/browse/JMS_SPEC-39). If a durable subscription is created by a connection with clientId unset then
other connections may freely create further consumers on the same durable subscription.

This means that for two message consumers on different connections to share a durable subscription, clientId would need
to be left unset.

In addition, the effect of using a different topic or message selector than was used when the subscription was first
created needs to be amended. Currently this states (from the javadoc for Session.createDurableSubscriber):

    "A client can change an existing durable subscription by creating a durable TopicSubscriber
    with the same name and a new topic and/or message selector. Changing a durable subscriber
    is equivalent to unsubscribing (deleting) the old one and creating a new one."

This behaviour will continue, but only if there are no other active consumers on the durable subscription. If there is
an active consumer on the durable subscription, and an attempt is made to create an additional consumer with a different
topic or message selector, then a JMSException will be thrown (in the case of JMSContext a JMSRuntimeException will be
thrown).

Non-durable subscriptions
-------------------------

For non-durable subscriptions, the JMS 1.1 specification specifies that if two non-durable TopicSubscribers are created
on the same topic then two independent subscriptions are created: a copy of each message is sent to every consumer on
that topic (with an appropriate message selector).

To allow two consumers to share the same subscription, so that they can share the load of processing messages from that
subscription, then new API is required. To allow the consumers to specify that they wish to use the same non-durable
subscription, they will need to specify the same sharedSubscriptionName.

The following new methods on Session (and its subtypes) are proposed:

    MessageConsumer createSharedConsumer(
       Topic topic, String sharedSubscriptionName);
    MessageConsumer createSharedConsumer(
       Destination destination, String sharedSubscriptionName, String messageSelector)
    MessageConsumer createSharedConsumer(
       Destination destination, String sharedSubscriptionName, String messageSelector, boolean NoLocal)

Note that if these methods were called simply createConsumer there would be a clash with the existing method
{createConsumer(Destination destination, String messageSelector). Note that these methods take a Topic, not a Destination.

In the new simplified API, the following new methods on JMSContext are proposed:

    JMSConsumer createSharedConsumer(
       Topic topic, String sharedSubscriptionName)
    JMSConsumer createSharedConsumer(
       Topic topic, String sharedSubscriptionName, String messageSelector)
    JMSConsumer createSharedConsumer(
       Topic topic, String sharedSubscriptionName, String messageSelector, boolean noLocal)

Note that a given shared subscription does not exist if there are no consumers using it.