7.4. JMS Applications

In the preceding sections, you deployed a JMS Server, and then JMS resources including a connection factory and destinations. To use these from an application module, the module needs to map references to the resources in its deployment information, and then the module's code needs to look up the resources in JNDI.

[Note]Note

The procedure described here uses J2EE 1.4 deployment descriptor syntax. The same mapping could be done with earlier versions, but the deployment descriptor file format would be somewhat different.

7.4.1. Updating the Module's Deployment Information

Once the JMS resources have been deployed, application modules can refer to them using the names specified in the JMS Resource deployment plan. ConnectionFactories are mapped by the name specified in the outbound-resourceadapter block (for example, MyConnectionFactory in Example 7.1, “JMS Resource Group Deployment Plan”), while destinations are mapped by the message-destination-name specified in the adminobject block (for example, MyQueue and MyTopic in Example 7.1, “JMS Resource Group Deployment Plan”).

To map a connection factory, the application module first declares a resource-ref with a type of javax.jms.ConnectionFactory in its standard J2EE deployment descriptor. To map a destination, the module declares a message-destination-ref with a type of javax.jms.Queue or javax.jms.Topic and links it to a message-destination with the same message-destination-name as we used for the adminobjects in the JMS resource deployment plan. For example, a web application could do one of each like this:

WEB-INF/web.xml

<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
         http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">
  ...
  <resource-ref>
    <res-ref-name>jms/AConnectionFactory</res-ref-name>
    <res-type>javax.jms.ConnectionFactory</res-type>
    <res-auth>Container</res-auth>
    <res-sharing-scope>Shareable</res-sharing-scope>
  </resource-ref>
  <message-destination-ref>
    <message-destination-ref-name>
      jms/ATopic
    </message-destination-ref-name>
    <message-destination-type>
      javax.jms.Topic
    </message-destination-type>
    <message-destination-usage>
      Consumes
    </message-destination-usage>
    <message-destination-link>MyTopic</message-destination-link>
  </message-destination-ref>
  <message-destination-ref>
    <message-destination-ref-name>
      jms/AQueue
    </message-destination-ref-name>
    <message-destination-type>
      javax.jms.Queue
    </message-destination-type>
    <message-destination-usage>
      Produces
    </message-destination-usage>
    <message-destination-link>MyQueue</message-destination-link>
  </message-destination-ref>
  <message-destination>
    <message-destination-name>MyTopic</message-destination-name>
  </message-destination>
  <message-destination>
    <message-destination-name>MyQueue</message-destination-name>
  </message-destination>
</web-app>

The important elements here are:

resource-ref

Declares a connection factory reference

res-ref-name

The partial JNDI name where the ConnectionFactory will appear. In this case, the ConnectionFactory will appear in JNDI at java:comp/env/jms/AConnectionFactory for the web application.

res-sharing-scope

When set to Shareable (the default), allows more than one application component in the same transaction to use the same ConnectionFactory. Should be set to Unshareable if a component will make changes to the ConnectionFactory that should be invisible to other components even within the same transaction (in which case each will get a different ConnectionFactory).

message-destination-ref

Declares a message destination reference, which may be a topic or a queue.

message-destination-ref-name

The partial JNDI name where the Topic or Queue will appear. In this case, the topic will appear in JNDI at java:comp/env/jms/ATopic, and a Queue will appear at java:comp/env/jms/AQueue.

message-destination-type

Should be either javax.jms.Topic or javax.jms.Queue

message-destination-link

Must match the message-destination-name of a message-destination declared later in the same file, and also the message-destination-name for an adminobject declared in the JMS resource deployment plan.

message-destination

There should be a message-destination block for every destination used in this configuration file.

message-destination-name

Matches the message-destination-link of a message-destination-ref declared elsewhere in the same file, and also the message-destination-name for an adminobject declared in the JMS resource deployment plan.

Because of the mapping done between the message-destination-name here and the message-destination-name in the adminobject, no further configuration is required for message destinations. However, the mapping for the connection factory is not yet complete.

In the Geronimo deployment plan for that module, you'll specify which JMS connection factory in the server will satisfy the connection factory reference declared by the web module. A deployment plan that maps the reference above to the connection factory configured in Example 7.1, “JMS Resource Group Deployment Plan” would look like this:

WEB-INF/geronimo-web.xml

<web-app
    xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-1.0"
    xmlns:naming="http://geronimo.apache.org/xml/ns/naming-1.0"
    configId="MyWebApp">
    ...
    <naming:resource-ref>
        <naming:ref-name>
          jms/AConnectionFactory
        </naming:ref-name>
        <naming:resource-link>
          MyConnectionFactory
        </naming:resource-link>
    </naming:resource-ref>
</web-app>

The important elements here are:

resource-ref

Holds the Geronimo information mapping a resource reference to a specific connection factory that's available to the module

ref-name

Matches the res-ref-name in the J2EE deployment descriptor, and identifies which reference this configuration block applies to

resource-link

Matches the name specified for the connection factory in the JMS resource deployment information. For server-wide or application-scoped connection pools, the name is located in the deployment plan used for the ActiveMQ connector. For module-scoped connection pools, the name is located in the configuration block in a resource element appearing later in this same deployment plan.

With the configuration above, if a servlet or other component of the web application looks in JNDI under java:comp/env/jms/AConnectionFactory, then it will find a javax.jms.ConnectionFactory that connects to the JMS Server we configured. If the component looks under java:comp/env/jms/AQueue or java:comp/env/jms/ATopic, it will find a javax.jms.Queue or javax.jms.Topic, which can be used in conjunction with the ConnectionFactory to communicate with a specific JMS topic or queue.

[Tip]Tip

This section did not cover all the options available in Geronimo deployment plans for the different application modules. For full details on customizing application modules, see Chapter 11, Web Applications (WARs) [DRAFT (1.0)], Chapter 12, Enterprise Java Beans (EJB JARs) [DRAFT (1.0)], and Chapter 14, Client Applications (Client JARs) [IN PROGRESS].

7.4.2. Application Code

The application code necessary to use a JMS destination looks like this:

InitialContext ctx = new InitialContext();
TopicConnectionFactory tcf =
       ctx.lookup("java:comp/env/jms/AConnectionFactory");
TopicConnection connection = tcf.createTopicConnection();
Topic topic = ctx.lookup("java:comp/env/jms/ATopic");
connection.start();
TopicSession session = connection.createTopicSession(false,
                                       Session.AUTO_ACKNOWLEDGE);
TopicPublisher publisher = session.createPublisher(topic);
Message message = ...;
publisher.publish(message);

This example looked up the connection factory and topic at the JNDI locations defined by the references in Section 7.4.1, “Updating the Module's Deployment Information”.