users@jms-spec.java.net

[jms-spec users] JMS_SPEC-116: JMS MDB improvements: simplifying the annotations

From: Nigel Deakin <nigel.deakin_at_oracle.com>
Date: Thu, 10 Sep 2015 17:21:09 +0100

I'm continuing to work through some of the issues raised on my proposals to improve JMS MDBs at
https://java.net/projects/jms-spec/pages/JMSListener2. To help readers I'm starting a new thread for each issue.

I'd like to review the proposed new method annotations for JMS MDBs in a bit more detail. These are the annotations that
would (1) specify that a method was a callback method and (2) specify which messages should be delivered to it.

Recap of current proposal
-------------------------

The following example illustrates the annotations currently proposed:

    @JMSListener(lookup="java:global/java:global/Trades",type=JMSListener.Type.TOPIC )
    @JMSConnectionFactory("java:global/MyCF")
    @SubscriptionDurability(SubscriptionDurability.Mode.DURABLE)
    @ClientId("myClientID1")
    @SubscriptionName("mySubName1")
    @MessageSelector("ticker='ORCL'")
    @JMSListenerProperty(name="foo1", value="bar1")
    @JMSListenerProperty(name="foo2", value="bar2")
    @Acknowledge(Acknowledge.Mode.DUPS_OK_ACKNOWLEDGE)
    public void giveMeAMessage(Message message) {
      ...
    }

Obviously, this is an extreme example which demonstrates the use of every annotation. I'm including the new
@JMSListenerProperty annotation I proposed a few days ago.

@JMSListener is always required: this is the annotation that signifies that this is a callback method. That's why the
name is "JMSListener" rather than "JMSDestination", despite its role being to specify the queue or topic.

In @JMSListener, the lookup attribute can be omitted. This was to allow the MDB to use "legacy" ways to define the queue
or topic, such as using the MessageDriven's mappedName attribute. This would also allow an additional attribute such as
"name" to be added in the future which allows the queue or topic's "non-portable" name to be specified.

However in @JMSListener, the type attribute would always be required. I proposed this because the spec does not define a
default value and it seemed useful to allow the app server/resource adapter to know what type of destination was expected.

Otherwise, there is a separate annotation corresponding to each of the standard activation properties.

Discussion
----------

There are a number of things we should review here. I think the main thing we need to consider is which is better:

    a. to have lots of separate annotations, almost all of which have a single attribute, or

    b. to have a smaller number of annotations, each of which set multiple attributes.

An alternative proposal
-----------------------

I'd like to suggest an alternative set of annotations:

One for queues:

    @JMSQueueListener(destinationLookup="java:global/java:global/Trades",
       connectionFactoryLookup="java:global/MyCF",
       messageSelector=""ticker='ORCL'",
       acknowledge=JMSQueueListener.Mode.DUPS_OK_ACKNOWLEDGE)
    @JMSListenerProperty(name="foo1", value="bar1")
    @JMSListenerProperty(name="foo2", value="bar2")
    public void giveMeAMessage(Message message) {
       ...
    }

One for durable topic subscriptions:

    @JMSDurableTopicListener(destinationLookup="java:global/java:global/Trades",
       connectionFactoryLookup="java:global/MyCF",
       clientId="myClientID1",
       subscriptionName="mySubName1",
       messageSelector=""ticker='ORCL'",
       acknowledge=JMSQueueListener.Mode.DUPS_OK_ACKNOWLEDGE)
    @JMSListenerProperty(name="foo1", value="bar1")
    @JMSListenerProperty(name="foo2", value="bar2")
    public void giveMeAMessage(Message message) {
       ...
    }


One for nondurable topic subscriptions:

    @JMSNonDurableTopicListener(destinationLookup="java:global/java:global/Trades",
       connectionFactoryLookup="java:global/MyCF",
       messageSelector=""ticker='ORCL'",
       acknowledge=JMSQueueListener.Mode.DUPS_OK_ACKNOWLEDGE)
    @JMSListenerProperty(name="foo1", value="bar1")
    @JMSListenerProperty(name="foo2", value="bar2")
    public void giveMeAMessage(Message message) {
       ...
    }

Some of these attributes would need to be specified, others would be optional.

Having separate annotations for queues, durable subscriptions and non-durable subscriptions would remove the need for
the user to specify destinationType or subscriptionDurability as attributes.

Possible further option
-----------------------

In addition to the alternative above, we could also offer a completely generic annotation, though this would strictly be
unnecessary:

    @JMSDestinationListener(destinationLookup="java:global/java:global/Trades",
       type=JMSListener.DestinationType.TOPIC,
       connectionFactoryLookup="java:global/MyCF",
       clientId="myClientID1",
       subscriptionDurability=JMSListener.SubscriptionDurability.DURABLE
       subscriptionName="mySubName1",
       messageSelector=""ticker='ORCL'",
       acknowledge=JMSQueueListener.Mode.DUPS_OK_ACKNOWLEDGE)
    @JMSListenerProperty(name="foo1", value="bar1")
    @JMSListenerProperty(name="foo2", value="bar2")
    public void giveMeAMessage(Message message) {
       ...
    }

This generic annotation would need to allow destinationType and subscriptionDurability to be specified.

What do you think?
------------------

What do you think? Do you prefer:

A. One annotation @JMSListener to define the callback method and the destination
    One small annotation for every other activation property
    (the original proposals)

B. One big annotation JMSQueueListener for queues,
    One big annotation JMSDurableTopicListener for durable topic subscriptions,
    One big annotation JMSNonDurableTopicListener for nondurable topic subscriptions,
    One small annotation JMSListenerProperty for each non-standard activation property
    (the alternative proposals above).

C The same as B plus
    The generic JMSDestinationListener annotation

D. The generic JMSDestinationListener annotation (only)
    One small annotation JMSListenerProperty for each non-standard activation property

I don't have a strong view on which is better: it's mainly a matter of style. One advantage of having annotations with
multiple attributes is that once the user has decided which annotation to use, the IDE would offer hints as to which
attributes to set.

Nigel