jsr343-experts@jms-spec.java.net

[jsr343-experts] Re: (JMS_SPEC-40) Allow multiple consumers to be created on the same topic subscription

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Wed, 14 Nov 2012 14:47:25 +0000

My last email on this topic raised more comments than I expected, specifically from colleagues concerned about backwards
compatibility. Oleg raised a similar point on this list. So although I had hoped we had put this issue to rest, I think
we need to go back and discuss the issue of backwards compatibility. And, unfortunately, I need to re-open JMS_SPEC-40.

I think there are two aspects in which the current proposals for durable subscriptions break backwards compatibility. In
both cases, the behaviour of Session.createDurableSubscription has changed:

Incompatibility 1. (This is the case I mentioned in my last email)

According to JMS 1.1 section 6.11.1: "Only one session at a time can have a TopicSubscriber for a particular durable
subscription.". The spec and API docs do not explicitly state that an attempt to create two TopicSubscribers on the same
durable subscription should throw an exception, but I think this is implied, at least for the case where different
sessions are used.

In JMS 2.0 we are proposing to remove this restriction and allow multiple TopicSubscribers (and MessageConsumers) to be
created on the same durable subscription.

Incompatibility 2. (I didn't mention this before but we need to consider it for the sake of completeness).

According to JMS 1.1 section 6.11.1: "Sessions with durable subscribers must always provide the same client
identifier." The spec and API docs do not explicitly state that clientId must be set when calling
createDurableSubscription, and that an exception must be thrown if it is not set, but again I think this is is implied.

In JMS 2.0 we are proposing to remove this restriction and allow clientId to be either set or unset when
Session.createDurableSubscription is called. If clientId is set then the combination of clientId and subscription name
will be used to identify the durable subscription. If clientId is not set then the subscription name will be used to
identify the durable subscription.
--------------------------------------------------------------------------------------------------------------------

The feedback I have received so far (internally within Oracle) has focussed on (1). A hypothetical application might use
multiple sessions in separate threads which concurrently attempt to create a consumer on the same durable subscription,
and rely on the JMS provider to ensure that only one of these threads succeeds at any given time.

The feedback I have received so far on (2) has indicated that it this might possibly be an acceptable change, though
there is no doubt that it would still be a break in compatibility.

The Java EE rules on backwards compatibility are here:
http://java.net/projects/javaee-spec/pages/CompatibilityRequirements
If we follow these rules strictly, then neither (1) not (2) are allowed. I think the simplest and safest thing to do is
to avoid breaking compatibility completely by leaving the behaviour of createDurableSubscriber unchanged and to move the
new behaviour to a new method createSharedDurableConsumer.

This gives us the following methods for creating shared and unshared durable subscriptions:

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

Methods on Session: (JMS 1.1/JMS 2.0)

TopicSubscriber createDurableSubscriber(Topic topic, String name) (JMS 1.1)
TopicSubscriber createDurableSubscriber(Topic topic, String name, String messageSelector, boolean noLocal) (JMS 1.1)

MessageConsumer createDurableConsumer(Topic topic, String name) (JMS 2.0)
MessageConsumer createDurableConsumer(Topic topic, String name, String messageSelector, boolean noLocal) (JMS 2.0)

(Remember that we added these last two methods to allow applications to avoid using the semi-deprecated TopicSubscriber
interface).

Methods on JMSContext: (JMS 2.0)

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

NOTE: Will only allow a single consumer on a durable subscription
NOTE: clientId MUST be set
NOTE: Session method createDurableSubscriber remains compatible with JMS 1.1
NOTE: noLocal option available, defined in terms of clientId

Shared durable subscriptions
----------------------------

Methods on Session: (JMS 2.0)

MessageConsumer createSharedDurableConsumer(Topic topic, String name)
MessageConsumer createSharedDurableConsumer(Topic topic, String name, String messageSelector, boolean noLocal)

Methods on JMSContext: (JMS 2.0)

JMSConsumer createSharedDurableConsumer(Topic topic, String name)
JMSConsumer createSharedDurableConsumer(Topic topic, String name, String messageSelector, boolean noLocal)

NOTE: Will only allow a single consumer on a durable subscription
NOTE: clientId may or may not be set
NOTE: All methods new in JMS 2.0 so no need for compatibility with JMS 1.1
NOTE: noLocal option available, defined in terms of clientId
NOTE: Consistent with createSharedConsumer for non-durable subscriptions.

These methods have a handy side-effect in allowing JMS implementations to know in advance whether the subscription needs
to be able to handle multiple consumers. This may allow more efficient code.

Please let me know your views on this.

Here are a couple of related issues:

Namespace
---------

I have been wondering whether non-shared and shared durable subscriptions should use the same or different namespaces.
That is, whether we should allow a non-shared durable subscription and a shared durable subscription to have the same name.

I think it would be simpler, and less likely to cause confusion, if they shared the same namespace, but we did not allow
non-shared and shared consumers to be used with the same subscription name. This would avoid an application accidentally
creating a non-shared and a shared durable subscription with the same name when it actually meant to use the same shared
durable subscription.

One possible additional change
------------------------------

I have received one further suggestion which we might want to consider: This is to require clientId to be UNSET when
calling createSharedDurableConsumer.

I am not yet convinced of this. I think the thinking is that is clientId is set then the createSharedDurableConsumer
method is not very useful as all consumers would need to use the same connection. However I think this is a reasonable
use case, and one which might be useful for resource adapters to use to implement multi-threaded processing of messages
from a durable subscription.

If we did adopt this change I think we should apply the same restriction to createSharedConsumer.

Since we have already defined noLocal to be allowed only if clientId was set, then if we required clientId to be UNSET
when calling createSharedDurableConsumer (and createSharedConsumer) then we could simply omit the noLocal parameters
completely from these methods.

I'm not currently proposing this, but I'd welcome comments on this possible additional change.

Comments please
---------------

Please give your comments on these three issues

1. My proposal to keep the existing behaviour of createDurableSubscription and define completely new methods to create
shared durable subscriptions.

2. My proposal that non-shared and shared durable subscriptions should use the same namespace. This would mean that if
you called createDurableConsumer to create a non-shared durable subscription you couldn't subsequently call
createSharedDurableConsumer with the same subscription name. (and vice versa).

3. The suggestion (not yet a proposal) to forbid the use of clientId with shared durable (and non-durable) subscriptions
(and in consequence drop support for noLocal from both).


Nigel