users@jms-spec.java.net

[jms-spec users] [jsr343-experts] Re: Re: (JMS_SPEC-90) Provide simpler mechanism to refer to queues and topics in a portable way

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Fri, 20 Apr 2012 16:21:39 +0100

John,

Thanks for the quick response.

The aim of this feature is to avoid the need to use vendor-specific code (such as a connection factory) to create a
Queue or Topic object., given that it is really nothing more than a wrapper around a provider-specific queue or topic name.

An alternative would be to use just String objects (as suggested by Rüdiger in his email "Why are Destinations resources
and not Strings?") However, we still need to support the idea of administered objects, bound into JNDI, allow the
deployer to configure or override the specific destination used by the application. Although it would be possible to
bind String objects into JNDI instead of Queue or Topic objects these don't contain quite enough information as they
don't specify the destination type. In any case, we're stuck with Queue and Topic as administered objects forever and
I'd rather focus on making them easier to create and use.

I gave some other reasons for not wanting a method on connection factory (e.g. assisting the development of generic JMS
resource adapters) in a previous email on this his thread. But the proposal for B (allowing Queue or Topic objects to be
generated automatically by the Java EE container) introduces a new reason, since since they require the container to be
able to create Queue and Topic objects without using any provider-implemented code (and without knowing what JMS
provider would be used).

I agree that defining an implementation in an API definition is a bit unusual - though it wouldn't be the first such
class in JMS.

The QueueImpl/TopicImpl proposal is ultimately a way to achieve a portable javax.jms.Queue or javax.jms.Topic without
breaking existing non-portable implementations of those interfaces. There might be other ways to achieve this, but I
can't think of one as simple as this. Suggestions welcome.

Nigel

On 20/04/2012 14:46, John D. Ament wrote:
> Nigel,
>
> I'm not a fan of either approach (EE is maybe doable). Defining a standard implementation as a part of the JMS API
> seems awkward. You're forcing the implementers to write code in a fashion that is mandated by JMS.
>
> I'm not sure I follow why keying it off connection factory is poor, or even having a static method available in some
> class?
>
> John
>
> On Fri, Apr 20, 2012 at 9:16 AM, Nigel Deakin <nigel.deakin_at_oracle.com <mailto:nigel.deakin_at_oracle.com>> wrote:
>
> My earlier proposals for some new API to create Queue and Topic objects didn't gain much support from this EG.
> I've thought about this more, discussed it with colleagues, and come up with a new proposal.
>
> What am I trying to achieve here is to allow any application (including Java SE or Java EE applications, a Java EE
> container, a resource adapter, and tools) to create a Queue or Topic object in a portable way without the need to
> obtain a connection factory, connection or session first.
>
> I did consider adding new API to connection factory, but this introduces a dependency on a vendor's JMS
> implementation which is actually not necessary. JMS already defines a Queue or Topic object to be simply a wrapper
> around a provider-specific queue or topic name, and I think we should keep it as that.
>
> I also considered whether we should make the use of Queue and Topic objects unnecessary by adding new methods to
> JMS which simply took a String name instead of a Queue and Topic. I decided this was undesirable for two reasons:
> it would bloat the API with yet more methods, but more importantly because the concept of a Queue and Topic object
> remains a useful one in JMS (and Java EE) because by allowing Queue and Topic objects to be bound in JNDI it
> allows application code to be separated from queue and topic names.
>
> Below are two separate proposals: a new feature in JMS, and a tentative proposal for Java EE which exploits this
> feature. (We would need to discuss the latter in detail with the Java EE platform spec EG).
>
> Please give your comments or questions on both (A) and (B).
>
> A: JMS Proposal
> ---------------
>
> I propose that JMS defines two classes: javax.jms.QueueImpl (which implements the javax.jms.Queue interface) and
> javax.jms.TopicImpl (which implements the javax.jms.Topic interface). These are classes, whose implementation is
> provided by JMS.
>
> Here is what javax.jms.QueueImpl would look like:
>
> public final class QueueImpl implements Queue {
> String queueName;
> public QueueImpl(String queueName) {
> this.queueName = queueName;
> }
> public String getQueueName() throws JMSException {
> return queueName;
> }
> }
>
> javax.jms.TopicImpl would be similar.
>
> So an application could create a Queue by calling
>
> Queue queue = new QueueImpl("myQueue");
>
> We would then define that any existing JMS API call which accepted a javax.jms.Destination must be able to accept
> a QueueImpl or TopicImpl, any existing JMS API call which accepted a javax.jms.Queue must be able to accept a
> QueueImpl, and any existing JMS API call which accepted a javax.jms.Topic must be able to accept a TopicImpl.
>
> This would be very simple for vendors to implement, since they can simply use the existing createQueue/createTopic
> methods on Session (which they already implement) to convert the queue or topic name to whatever provider-specific
> class they currently use to implement Queue and Topic.
>
> For example, the implementation of Session.createConsumer would need to be modified as follows:
>
> Existing implementation:
>
> public MessageConsumer createConsumer(Destination destination) throws JMSException {
> return someProprietaryCodeToCreateConsumer(destination);
> }
>
> New implementation:
>
> public MessageConsumer createConsumer(Destination destination) throws JMSException {
> if (destination instanceof QueueImpl){
> return someProprietaryCodeToCreateConsumer(createQueue(destination.getQueueName());
> } else if (destination instanceof TopicImpl){
> return someProprietaryCodeToCreateConsumer(createTopic(destination.getTopicName());
> } else {
> return someProprietaryCodeToCreateConsumer(destination);
> }
> }
>
> Some minor details:
>
> * We would need to define that it was valid to pass a QueueImpl or TopicImpl into Message.setJMSReplyTo, though
> Message.getJMSReplyTo would be free to return a proprietary implementation.
>
> * We would clarify that implementations of Session.createQueue/createTopic and Message.getJMSReployTo would be
> free to return a proprietary implementation of Queue or Topic in all cases, or they could return a QueueImpl or
> TopicImpl.
>
> B: Java EE Proposal
> -------------------
>
> The above change would make it possible to consider some new features for Java EE. This is because for the first
> time it would be possible for a Java EE container to inject a Queue or Topic object without the need to use JMS
> provider code.
>
> It is proposed that we define some default behaviour when injecting a Queue or Topic object into a Java EE
> application.
>
> An application can currently inject a Queue object as follows:
>
> @Resource(name="myQueueName")
> Queue myQueue;
>
> Java EE states that the name attribute is used to specify a "destination reference name". The application deployer
> is responsible for creating a Queue object, binding it to some location of JNDI, and providing a
> <message-destination-ref> element which maps the specified name to the JNDI name of the Queue object. If there is
> no such mapping, or if there is no such JNDI object, a deployment error occurs.
>
> We could propose that if the specified destination reference name is not mapped to a JNDI name then the container
> will automatically instantiate a QueueImpl, using the specified destination reference name as the queue name, and
> inject it into the application.
>
> This would offer a much simpler way to configure destinations for applications, whilst leaving unchanged the
> ability of a deployer to override this behaviour by defining a <message-destination-ref> element in the normal way.
>
> Note that the Java EE 7 Early Draft already proposes a way for a container to inject a "platform default
> connection factory". These two features together will significantly simply the use of JMS for smaller or less
> complex applications.
>
> There are a few details related to this Java EE proposal that would need to be considered:
>
> * We may want to define some similar default behaviour for MDBs.
>
> * We would need to check whether there were any restrictions on valid characters in @Resource(name="..."), since
> this would limit the queue or topic names that could be specified in this way.
>
> * This wouldn't be possible the application injected a Destination rather than a Queue or Topic, since the
> container wouldn't know whether to create a QueueImpl or a TopicImpl.
>
> Nigel
>
>