With the JMS 2.0 final release imminent, I have been trying to minimise the changes that we make to the API. The only
changes I think we should make at this stage are corrections to new features.
There is one new feature that unfortunately I think we need to change. This is the new Java EE connection factory and
destination definition annotations and the corresponding deployment descriptor elements.
As I've explained before I see this as essentially a Java EE feature since they are defined in the Java EE platform spec
(section EE.5.19 "Resource Definition and Configuration" rather than in the JMS spec. However since the annotations are
defined as part of the JMS API this expert group is involved. (I think this unclear responsibility is why we're only
spotting bugs in the spec at this late stage),
Here's a brief summary:
Following recent feedback from the JCA spec lead and others I have discovered that we need to change the
JMSConnectionFactoryDefinition and JMSDestinationDefinition annotations to allow the interface name to be specified as
well as the implementation class name. Instead of defining an additional attribute interfaceName which can be set to
javax.jms.Queue, javax.jms.QueueConnectionFactory etc I propose we replace these two annotations with five new
annotations, one for each interface.
Here's a more detailed description. Let's consider the two existing annotations in turn:
JMSConnectionFactoryDefinition
------------------------------
This annotation is used by the application to define a connection factory resource that will be created by the
container. The current javadoc is here:
http://jms-spec.java.net/2.0-SNAPSHOT/apidocs/javax/jms/JMSConnectionFactoryDefinition.html
This currently has a "required" attribute "className" which is defined as "JMS connection factory implementation class
name which implements: javax.jms.ConnectionFactory or javax.jms.QueueConnectionFactory or javax.jms.TopicConnectionFactory"
However if a resource adapter is being used then the implementation class is not needed. All that is needed is the
interface it implements (javax.jms.ConnectionFactory or javax.jms.QueueConnectionFactory or
javax.jms.TopicConnectionFactory). The container can simply lookup the implementation class from the resource adapter's
ra.xml. Obviously this is preferable since it keeps implementation classes out of the application code.
If a resource adapter is not being used, but the resource being created is for the application server's built-in JMS
provider, then the implementation class is also not needed. In this case the application server will decide what
implementation class is needed. Again this is preferable since it keeps implementation classes out of the application code.
However if a resource adapter is not being used, and an implementation class is required which is not the application
server's default, then a className is needed.
I think to model this correctly we need to allow the application to specify two separate pieces of information:
interfaceName and className:
* interfaceName is always required
* className is only required if a resource adapter is not being used and a class other than the application server's
default (for the specified interface) is required.
We already have a className attribute, so we need to provide a way for the interfaceName to be specified. Instead of
adding a new attribute interfaceName which needs to be set to javax.jms.ConnectionFactory or
javax.jms.QueueConnectionFactory or javax.jms.TopicConnectionFactory I propose we define three annotations, each of
which implies the corresponding interfacename:
javax.jms.JMSConnectionFactoryDefinition
javax.jms.JMSQueueConnectionFactoryDefinition
javax.jms.JMSTopicConnectionFactoryDefinition
If we also allow the resourceAdapter attribute to be left unset (in which case it allows the application server to
define the default resource adapter or implementation classes) this allows the application to define annotations such as:
@JMSConnectionFactoryDefinition(
name="java:global/jms/demoConnectionFactory",
description="ConnectionFactory to use in demonstration"
)
Previously (in the RI) this would have been:
@JMSConnectionFactoryDefinition(
name="java:global/jms/demoConnectionFactory",
resourceAdapter= "jmsra",
className= "javax.jms.ConnectionFactory",
description="ConnectionFactory to use in demonstration"
)
I think this is a significant improvement for users, whilst still allowing className to be specified if needed.
JMSDestinationDefinition
------------------------
This currently has a "required" attribute "className" which is defined as "JMS destination implementation class name
which implements: javax.jms.Queue or javax.jms.Topic".
Again, if a resource adapter is being used then the implementation is not needed in most (but not all) cases. All that
is (usually) needed is the interface it represents (javax.jms.Queue or javax.jms.Topic). The container can (usually)
simply lookup the implementation class from the resource adapter's ra.xml. Obviously this is preferable since it keeps
implementation classes out of the application code.
If a resource adapter is being used, and the resource adapter's ra.xml's defines two or more implementation classes for
a given interface, then the implementation class is also needed to disambiguate between the two. (Specifying className
on its own may not be enough - this is because only the interfaceName/className combination is unique in ra.xml. But to
avoid making this too complicated I won't go into that unless anyone asks)
If a resource adapter is not being used, but the resource being created is for the application server's built-in JMS
provider, then the implementation class is not needed. In this case the application server will decide what
implementation class is needed. Again this is preferable since it keeps implementation classes out of the application code.
However if a resource adapter is not being used, and an implementation class is required which is not the application
server's default, then a className is needed.
Again, I think to model this correctly and clearly we need to allow the application to specify two separate pieces of
information, interfaceName and className.
* interfaceName is always required
* className is only required if a resource adapter is being used and it is needed to disambiguate between multiple
entries (for the specified interface) in ra.xml, or if a resource adapter is not being used and a class other than the
application server's default (for the specified interface) is required.
As explained above, we already have a className attribute, so we need to provide a way for the interfaceName to be
specified. Instead of adding a new attribute interfaceName which needs to be set to javax.jms.Queue or javax.jms.Topic I
propose we replace the existing annotation javax.jms.JMSDestinationDefinition with two annotations, each of which
implies the corresponding interfacename:
javax.jms.JMSQueueDefinition
javax.jms.JMSTopicDefinition
If we also allow the resourceAdapter attribute to be left unset (in which case it allows the application server to
define the default resource adapter or implementation classes) this allows the application to define annotations such as:
@JMSQueueDefinition(
name = "java:global/jms/demoQueue",
description = "Queue to use in demonstration",
destinationName="demoQueue")
Previously (in the RI) this would have been
@JMSDestinationDefinition(
name = "java:global/jms/demoQueue",
resourceAdapter= "jmsra",
description = "Queue to use in demonstration",
className = "javax.jms.Queue",
destinationName="demoQueue")
I think this is a significant improvement for users, whilst still allowing className to be specified if needed.
I'll be proposing corresponding changes to the deployment descriptor elements to the the Java EE spec lead.
I hope you think this is a reasonable improvement. If you have any questions or comments please make them by Friday 13
March.
Nigel