users@jms-spec.java.net

[jms-spec users] [jsr343-experts] 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: Tue, 01 May 2012 12:20:54 +0100

On 20th April I made a couple of proposals, one for JMS and one for Java EE:

> 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.

John A was concerned about providing an implementation class as part of JMS, which I responded to. John also suggested
we named this QueueReference/TopicReference. Otherwise I haven't received much in the way of feedback on this, as most
comments were on (B) below.

>
> B: Java EE Proposal
> -------------------
>
> 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;
>
>
> 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.


In general the feedback I've received on (B) has been negative. In addition to Rüdiger's comments. I consulted the Java
EE spec leads who confirmed my suspicion that reusing a destination reference name as being the physical destination
name was inappropriate. I was advised that if we want to do something like this we should invent a new annotation rather
than attempt to extend @Resource.

So I'd now like to withdraw proposal (B).

However I'd like to leave proposal (A) on the table. I see providing a portable implementation of Queue and Topic as
essentially a refactoring of the existing JMS API which doesn't introduce any new concepts, and which would be simple to
implement.

It complements JMS_SPEC-89 which provides a portable way to instantiate a connection factory.

Even without (B), this feature still has value. Although applications could use it directly I see the main beneficiaries
as tools, application servers and JMS resource adapters designed to work with any JMS provider, all of will will be able
to instantiate Queue and Topic administered objects in a portable way.

I explained in more detail earlier in this thread why I didn't want to make this dependent on having a ConnectionFactory.

Here is the proposal again (this is essentially unchanged from before).

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 server, tool, resource adapter or 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.