jsr343-experts@jms-spec.java.net

[jsr343-experts] Re: Why are Destinations resources and not Strings?

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Tue, 27 Mar 2012 14:28:31 +0100

Rüdiger,

On 23/03/2012 07:43, Rüdiger zu Dohna wrote:
> Nigel,
>
> On 2012-03-22, at 19:20, Nigel Deakin wrote:
>> (Note that I'm treating this as a general discussion rather than a specific proposal)
>>
>> On 22/03/2012 16:37, Rüdiger zu Dohna wrote:
>>> On 2012-03-22, at 16:50, Nigel Deakin wrote:
>>>> On 21/03/2012 18:20, Rüdiger zu Dohna wrote:
>>>>> According to the JMS spec, chapter 4.2, Destinations are administered objects, i.e. type-safe resources that "live"
>>>>> in JNDI. The reasoning behind that is absolutely conclusive for connection factories: Decouple the client code from
>>>>> the specific, readily configured implementation. But I wonder, is that also true for the Destinations?
>>>>>
>>>>> Destinations are a named indirection to the actual addressing scheme used by the provider internally. They have to be
>>>>> configured, of course, but the clients only address them by their name and do nothing else with them but pass them
>>>>> into JMS methods. Connection factories are used to create connections, but Destinations are only passed back to the
>>>>> JMS provider.
>>>>>
>>>>> I think it would be sufficient to only pass the destination name into those methods, instead of Destination objects
>>>>> that have to be looked up first. That would further reduce the amount of code required and lessen the mental burden
>>>>> of JMS.
>>>>>
>>>>> Interestingly, this would also permit you to use the same destination name for different JMS providers, which would
>>>>> be very helpful for messaging bridges. Currently you can only pass a Destination to the same JMS provider that the
>>>>> Destination was configured for; you'll have to use some naming scheme to bridge from one JMS provider's destination
>>>>> to another one's.
>>>>>
>>>>> What do you all think? If I just missed an essential use case, please tell me so!
>>>> The use of administered objects avoids the need for the application to hard-code information which may not be known
>>>> until the application is deployed. This applies to destinations as well as connection factories, since the actual
>>>> destination name may not be known until deployment time.
>>> I mostly see that happen the other way around: The code has a fixed destination name, and the admin configures it at deployment time. But even if it's done as you describe, it would be enough to just inject the String, wouldn't it?
>> I almost forgot. The other important piece of information contained in a Destination is whether it is a queue or topic
>> The JMS provider needs to know which you're using (either because the name is scoped to the "messaging domain",
> JNDI names don't have a scope, do they? When you do a lookup, you'll have to cast the result, so JNDI doesn't know about the type, does it?

The real issue is whether we want to (or can) decouple the name of a destination from the information about whether it
is a queue or a topic. This is partly a question of scope ( I don't know whether we can rely on JMS providers forbidding
a queue and a topic from having the name) and partly a question of auto-creation, which some JMS providers do offer as a
feature and which I wouldn't want to break.

>
>> or because it needs to create the queue or topic lazily). Note that there's no Session.createDestination() method to force names to be unique across both queues and topics.
> The createQueue/Topic methods don't really create a destination, they are only a different means for lookup, aren't they? That's only needed for the temporary queues/topics.

In GlassFish Message Queue (in which I declare an interest) and Apache ActiveMQ these methods may create the queue or
topic automatically. I don't know about other JMS providers, though I note that Clebert (of HornetQ) has logged
http://java.net/jira/browse/JMS_SPEC-31 to request that the javadoc explicitly mention this possibility).

> The JMSDestinationDefinition annotation would of course specify the destination domain and many other things.
>
>> We may of course find that JMS providers and resource adapters do store other information in Queue or Topic objects.
>>
>> My feeling is that the burden here is in expecting the application to bind objects in JNDI at all, not that they are
>> Queue or Topic rather than String objects.
>>
>>>> Also, since JMS does not define what constitutes a valid destination name (e.g. what characters it may contain) any
>>>> application that uses destination names directly may not be portable between JMS providers (the javadoc for
>>>> Session.createSession(queueName) describes queueName as a "provider-specific name" and warns that "Clients that depend on this ability are not portable".
>>> Okay... we could easily limit the character set for portable code.
>> This might be tricky to apply retrospectively (especially if some providers need to use special characters for special
>> purposes). It may be significant that JMS doesn't define this already. However I can see a benefit in defining how to
>> specify a portable queue and topic name, particularly for use in a a PaaS environment where the queue or topic may be provisioned using some automatic mechanism (as in the Java EE 7 @JMSDestinationDefinition annotation).
> This is a quite soft requirement, isn't it? If some providers need special characters for special purposes, that's okay, only that this name would not be guaranteed to be portable. I understand that the whole purpose of destinations and destination names is to provide an abstraction to the actual address name scheme used by the messaging system internally.
>
>>>> However the fact that a Destination is administered object is not without issues:
>>>>
>>>> 1. A Destination is a little unusual as an administered object: if you think of a destination as something that needs to
>>>> be explicitly created in the JMS provider (the JMS spec states that "the physical creation of topics is an
>>>> administrative task") then a Destination object is not an independent object. It can only be used in conjunction with a
>>>> ConnectionFactory which points to the JMS server which contains the destination. Yet this dependency is not expressed anywhere.
>>>>
>>>> 2. It is also inconsistent with the way that databases are configured in Java EE. A JMS server may be thought of as
>>>> consisting of a number of destinations. In the same way a database may be thought of as consisting of a number of
>>>> tables. Yet a destination is an administered object whilst a table is not. As Rüdiger says, this imposes an extra burden
>>>> when using JMS.
>>>>
>>>> 3. Some applications need to be able to send messages to many thousands of destinations. For example, a market data provider may need to send stock prices to a different topic for every stock ticker code. Having to explicitly create an administered object for every destination is a burden compared with simply calling Session.createQueue(queueName).
>>>>
>>>> I'm not sure what changes, if any, we might we want to make in JMS.
>>> For the simplified API we could:
>>> 1) Use Strings instead of Destinations (or Topics) for all of the send and create(Durable)Consumer methods (BTW: In chapter 11, Destination and it's suptypes are not in the list of types shared between simplified and standard API).
>> I think we would want the simplified API to support existing Destination objects (which aren't going away).
> In both cases, they should show up in the intro to chapter 11
>
>> It could support destination name strings as well (which would simply call createQueue/createTopic internally) but the
>> arguments would also need to also pass in whether the name was a queue or topic. I'm not sure this would be less
>> complicated than simply calling createQueue/createTopic.
> I suppose we could actually go completely without any Destination objects in the simplified API.

I don't want the simplified API to miss out on the benefits of the existing Java EE features for configuring
destinations. I also want it to be easy for applications to be converted to use the simplified API. So I would go the
other way: keep Destinations but consider either (1) alternative ways to create them (2) provide alternatives to
Destination objects. I'm not sure exactly what to propose though.
>
>>> 2) The createQueue/Topic method could simply be dropped... but I'm not sure how to best proceed with createTemporaryQueue/Topic... probably they would return the name that the JMS provider generated for that destination.
>> Indeed.
>>> 3) Message.getJMSReplyTo() should get a new sibling getJMSReplyToDestination() which returns the name only, and the corresponding setJMSReplyToDestination would take a String argument.
>>>
>>> BTW: This would really make the Topic types obsolete, wouldn't it?
>> I don't follow...
> There has been a discussion on this list, if we could remove the destination domains (Topic/Queue) completely. The conclusion was that we'd want to have type safety for the create subscriber methods. But there is not type safety in the lookup of the destination, not with JNDI (where you do a cast or the injection provider does it for you) nor in the createQueue/Topic methods (which also must throw an exception, if you call createQueue for a Topic or vice versa). So: There is not type safety anyway, let's remove this stuff entirely... with the added benefit that you can use the same name for different JMS providers running in the same container.

I agree we're close to that already. But it would force all queues and topics to be created administratively, which I'm
not sure I am in favour of in all cases.

Nigel

>
>> Nigel
>>>> One thing I'm sure of, however, is that we need to recognise that the createQueue and createTopic methods are sometimes more appropriate than looking up an administered object. One idea might be to define a portable format for destination names that would be guaranteed to be valid in any JMS provider (e.g. defining what characters are valid, what the maximum length is, and so on).
>>> Yes... that would be required, too.
>>