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:
- 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:
<> 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"> <> useJmx="true" xmlns="http://activemq.apache.org/schema/core" name="LocalActiveMQBroker" persistent="true"> <>> <> name="defaulttrans" uri="tcp://localhost:61616" discoveryUri="multicast://default"/> > <>> <>> <>> <> queue=">"> <>> <> queuePrefix="DLQ." useQueueForQueueMessages="true" /> > > > > > <>> <> name="default" uri="multicast://default"/> > <>> <> directory="activemq-data" maxFileLength="32mb"/> > > >
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.
- 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:
<> 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" /> <> 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.
- 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 ServletListener, since this guarantees that the consumer will be created when the web application is loaded.