Tomcat and JMS

Sep 15 2009

Tomcat, being a Servlet/JSP container, allows for the deployment of simple java based web applications. Recently I was required to add asynchronous functionality to an application deployed in Tomcat. Upgrading to a full blown container, such as Glassfish, was cost prohibitive. Based on this I started researching for a third party JMS provider. I narrowed my search to OpenJMS, JBoss Messaging and ActiveMQ. I choose the latter since it is a mature apache project product and provided a feature that the others didn’t: the ability to run embedded within the same JVM. Having an already very fragmented architecture this was a big selling point. The steps for this configuration are as follows,

 

1.       First you will need to download the ActiveMQ distribution from http://activemq.apache.org. Unzipping the file will gave you the whole installation, however for using the embedded option you only need the following jars:

 

/activemq-all-5.2.0.jar

/lib/optional/spring-beans-2.5.5.jar

/lib/optional/spring-context-2.5.5.jar

/lib/optional/spring-core-2.5.5.jar

/lib/optional/xbean-spring-3.4.jar

 

You will also need a configuration file called activemq.xml with the following contents:

 

<beans

  xmlns="http://www.springframework.org/schema/beans"

  xmlns:amq="http://activemq.apache.org/schema/core"

  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

  xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd

  http://activemq.apache.org/schema/core http://activemq.apache.org/schema/core/activemq-core.xsd

  http://activemq.apache.org/camel/schema/spring http://activemq.apache.org/camel/schema/spring/camel-spring.xsd">

 

      <broker useJmx="true" xmlns="http://activemq.apache.org/schema/core" name="LocalActiveMQBroker" persistent="true">

            <transportConnectors>

                  <transportConnector name="defaulttrans" uri="tcp://localhost:61616" discoveryUri="multicast://default"/>

            </transportConnectors>

           

            <destinationPolicy>

            <policyMap>

                <policyEntries>

                        <!-- Set the following policy on all queues using the '>' wildcard -->

                  <policyEntry queue=">"> 

                        <deadLetterStrategy> 

                                        <!-- Use the prefix 'DLQ.' for the destination name, and make the DLQ a queue rather than a topic -->

                              <individualDeadLetterStrategy queuePrefix="DLQ." useQueueForQueueMessages="true" /> 

                        </deadLetterStrategy> 

                  </policyEntry>

 

                </policyEntries>

            </policyMap>

        </destinationPolicy>

           

            <networkConnectors>

            <!-- by default just auto discover the other brokers -->

            <networkConnector name="default" uri="multicast://default"/>

            <!--

            <networkConnector name="host1 and host2" uri="static://(tcp://host1:61616,tcp://host2:61616)" failover="true"/>

            -->

          </networkConnectors>

     

            <persistenceAdapter>

                  <amqPersistenceAdapter directory="activemq-data" maxFileLength="32mb"/>

            </persistenceAdapter>

      </broker>

</beans>

 

This will configure a broker listening in the following host and port: localhost: 6161. It will also setup a dead letter strategy for queues and specify the data persistence for messages.You will need to put these jars and configuration file on the correct classpath. For JMS to be available to all the web applications in the Tomcat instance place the jars in the /common/lib directory and the configuration file in the /common/classes directory.

 

2.       Now that you have the necessary infrastructure, you must configure your web application(s) to start and access the ActiveMQ JMS broker. This is done by creating the JNDI entries in the corresponding Tomcat context files. Here is an example:

 

<Resource auth="Container" description="JMS Connection Factory" name="jms/ConnectionFactory" type="org.apache.activemq.ActiveMQConnectionFactory" password="activemq" userName="activemq" useEmbeddedBroker="true" brokerURL="vm://localhost?brokerConfig=xbean:activemq.xml" clientID="TomcatClientID" factory="org.apache.activemq.jndi.JNDIReferenceFactory" brokerName="LocalActiveMQBroker"/>

 

<Resource auth="Container" description="JMS Queue" name="jms/queue" type="org.apache.activemq.command.ActiveMQQueue" physicalName="QUEUE" factory="org.apache.activemq.jndi.JNDIReferenceFactory"/>

 

Note that if you need two web applications to access the same resources you have to use the same client Id in the configuration for the connection factory.

 

3.       At this point your web application in Tomcat should be able to access the JMS resources specified in the context file by using JNDI calls such as:

 

connectionFactory = (ActiveMQConnectionFactory) init.lookup("java:comp/env/jms/ConnectionFactory);

 

For this setup is recommended that you create your consumers of topics/queues using a Servlet  Listener, since this guarantees that the consumer will be created when the web application is loaded.

 

Tagged: activemq, tomcat

About the Author

Mr. Vazquez has over 10 years of experience in the development life cycle of JEE applications for web environments. He has assisted clients in the design, implementation and testing of high performance web applications. Mr. Vazquez has assisted organizations in the creation of roles and best practices for the development of product-based applications. He has worked with clients to document development best practices, existing architectures and knowledge transfer sessions. Mr. Vazquez has extensive experience in Java development including web application security, complex asynchronous processing, server side design patterns, JDO, Spring and other frameworks.

Disclaimer

The words and opinions expressed here are those of each article's respective author, and do not necessarily represent the views of CapTech Ventures.