Part One

What's New in JMS 2.0: Ease of Use - Part 3

 

Easier Resource Configuration in JMS 2.0

JMS 2.0 enables easier resource configuration in several ways.

Default Connection Factory in Java EE

Java EE 7 introduces a platform default JMS connection factory. This is a built-in connection factory that connects to the application server's built-in JMS provider.

Applications can obtain this connection factory by performing a JNDI lookup using the namejava:comp:DefaultJMSConnectionFactory without the need to previously create the connection factory using administrative tools:

 

@Resource(lookup="java:comp/DefaultJMSConnectionFactory") ConnectionFactory cf

 

This connection factory is intended for use by the many applications that use the built-in JMS provider and don't need to add any application-specific configuration.

When injecting a JMSContext into an application, the JMSConnectionFactory annotation is used to specify the connection factory to be used:

 

@Inject @JMSConnectionFactory("
  jms/connectionFactory") JMSContext context1;

 

If this annotation is omitted, the default connection factory will be used:

 

@Inject JMSContext context2; // uses the platform default connection factory

 

JMS Resource Definition Annotations in Java EE

Every JMS application starts with a connection factory (an object that implements javax.jms.ConnectionFactory) and at least one destination (an object that implements either javax.jms.Queue or javax.jms.Topic). The ConnectionFactory is the object that in JMS is used to create the connection to the JMS provider, and the Queue or Topic is the object that identifies the physical queue or topic that messages are being sent to or received from.

The way in which these objects are created, and the way in which they are configured, varies from one JMS provider to another. That's why JMS recommends that you use a separate, provider-specific tool to create, configure, and bind into a JNDI store the connection factories and destinations that your application needs. Your application can then use JNDI to look up these objects without needing to use any nonstandard code. In addition to keeping your application code portable, this also means you can write your code without needing to know details about how it will be deployed.

When configuring a ConnectionFactory, it is often necessary to know things such as the host name and port of the JMS server. When configuring a Queue or Topic object, it is usually necessary to know the physical name of the queue or topic. Creating yourConnectionFactory, Queue, and Topic objects separately from the application and storing them in JNDI allows these details to be defined by the deployer or administrator, not the developer.

Although this separation of code from configuration is essential in many enterprise environments, it can be an unwanted burden in simpler environments. In addition, if the application is being deployed into an automated platform as a service (PaaS) system, it might be desirable to automate the provisioning of the ConnectionFactory, Queue, and Topic objects required by the application.

In many Java EE applications, the default JMS connection factory that is now available in any Java EE 7 application server (which was described in the previous section) removes the need for any connection factories to be configured at all. However, for those cases when a specially configured connection factory is needed—and for queues and topics—Java EE 7 offers another new feature that allows these objects to be created using either annotations in the code, XML elements in the deployment descriptor, or a combination of both.

The main new annotations are javax.jms.JMSConnectionFactoryDefinition and javax.jms.JMSDestinationDefinition. These can be defined in any Java EE component class such as an EJB bean or servlet, as shown in Listing 8:

Listing 8

 

@JMSConnectionFactoryDefinition(
    name="java:global/jms/MyConnectionFactory",
    maxPoolSize = 30,
    minPoolSize= 20,
    properties = {
        "addressList=mq://localhost:7676",
        "reconnectEnabled=true"
    }
) 
@JMSDestinationDefinition(
    name = "java:global/jms/DemoQueue",
    interfaceName = "javax.jms.Queue",
    destinationName = "demoQueue"
  )
public class NewServlet extends HttpServlet {
  ...

 

If more than one connection factory or destination needs to be defined, these annotations need to be enclosed within aJMSConnectionFactoryDefinitions or JMSDestinationDefinitions annotation, as shown in Listing 9:

Listing 9

 

@JMSConnectionFactoryDefinitions({
    @JMSConnectionFactoryDefinition(
       name="java:global/jms/MyConnectionFactory1",
       maxPoolSize = 30,
       minPoolSize= 20,       
       properties = {
          "addressList=mq://localhost:7676",
          "reconnectEnabled=true"
       }
    ),
    @JMSConnectionFactoryDefinition(
       name="java:global/jms/MyConnectionFactory2",
       maxPoolSize = 30,
       minPoolSize= 20,
       properties = {
          "addressList=mq://localhost:7677",
          "reconnectEnabled=true"
       }
    ) 
})
@JMSDestinationDefinitions({
    @JMSDestinationDefinition(
       name="java:global/jms/DemoQueue1",
       interfaceName = "javax.jms.Queue",
       destinationName = "demoQueue1"
    ),
    @JMSDestinationDefinition(
       name="java:global/jms/DemoQueue2",
       interfaceName = "javax.jms.Queue",
       destinationName = "demoQueue2"
    ) 
})
public class NewServlet extends HttpServlet {
  ...


 

The JMSConnectionFactoryDefinition annotation defines a number of standard attributes that can be specified including name(which is the JNDI name), clientId, user, password, maxPoolSize, and minPoolSize. In addition, the properties attribute can be used to specify additional nonstandard properties that the application server might support. In Listing 8 and Listing 9, addressList andreconnectEnabled are examples of such nonstandard properties.

The JMSConnectionFactoryDefinition annotation defines a smaller number of standard attributes that can be specified includingname (which is the JNDI name) and destinationName (which is the provider-specific queue or topic name), as well as allowing the properties attribute to be used to specify additional nonstandard properties.

Connection factories and destinations defined in this way must be in the java:comp, java:module, java:app, or java:globalnamespaces, and they typically exist for as long as the application that defines them is deployed.

It is also possible to specify these definitions in the deployment descriptor file (for example, web.xml or ejb-jar.xml), as shown in Listing 10:

Listing 10

 

<jms-connection-factory>
   <name>java:global/jms/MyConnectionFactory</name>
   <max-pool-size>30</max-pool-size>
   <min-pool-size>20</min-pool-size>
   <property>
      <name>addressList</name>
      <value>mq://localhost:7676</value>
   </property>
   <property>
      <name>reconnectEnabled</name>
      <value>true</value>
   </property>    
</jms-connection-factory>


<jms-destination>
   <name>java:global/jms/DemoQueue</name>
   <interfaceName>javax.jms.Queue</interfaceName>
   <destinationName>demoQueue</destinationName> 
</jms-destination>

 

If desired, the developer can specify some of the required attributes in the annotation, with the deployer specifying the remaining attributes in the deployment descriptor. This can be useful in the case of attributes whose values are not known until deployment time.

In all the examples above, the application server is responsible for "provisioning" the JNDI resources that are defined in the annotations or deployment descriptor. However, it remains the responsibility of the deployer to ensure that the JMS server to which the connection factory refers is installed and available, and that the physical queues and topics themselves have been created.

Conclusion

In this article, we covered the ease-of-use features added to JMS 2.0, which enable developers to write significantly fewer lines of code. In Part Two, we will look at the new messaging features in JMS 2.0.

See Also

Author Bio: Nigel Deakin, a Principal Member of Technical Staff at Oracle, was Specification Lead for JSR 343, Java Message Service 2.0. In addition to his responsibilities for leading the next versions of the JMS specification, he is a member of Oracle's JMS development team, working on Open Message Queue and the GlassFish application server. He has spoken recently at JavaOne in San Francisco, US, and at Devoxx in Antwerp, Belgium, and he is based in Cambridge, UK.

Reprinted with permission from the Oracle Technology Network, Oracle Corporation.

Pages

Chris Mayer

What do you think?

JAX Magazine - 2014 - 05 Exclucively for iPad users JAX Magazine on Android

Comments

Latest opinions