This post describes how we managed to use standalone ActiveMQ (v5.2.0) as JNDI datasource in our Mule ESB application deployed in Apache Tomcat(v6.0). If you are still with me after reading this first line then I may assume you know your way in this part of the Java open-source world :-)
Here is the situation:
We have deployed a number (about 10) of Mule applications as WAR’s in our Tomcat installation. Each WAR is using the same standalone ActiveMQ instance as JMS provider. We implemented this by defining an ActiveMQ connector in each WAR (actually in a separate JAR that is included in each WAR).
However, recently we defined our database datasource as a JNDI resource in Tomcat. The big advantage is that it is only configured in just one place and maintained by the container instead of each WAR creating its own pool of connections.
So we decided we could do the same for the ActiveMQ datasource (actually I was triggered by this article).
So here are the steps we took to make this work:
- Define a global resource in server.xml of the Tomcat instance:
- Define a global resourceLink in the context.xml of the Tomcat instance:
- Add to necessary libs to your /TOMCAT_HOME/lib directory:
<Resource name="jms/ConnectionFactory" auth="Container" type="org.apache.activemq.ActiveMQConnectionFactory" description="JMS Connection Factory" factory="org.apache.activemq.jndi.JNDIReferenceFactory" brokerURL="tcp://localhost:61616" brokerName="myActiveMQBroker" userName="user" password="password" />
<ResourceLink name="jms/myJMS" global="jms/ConnectionFactory" type="org.apache.activemq.ActiveMQConnectionFactory" />
For your Tomcat instance to be able to work with the standalone ActiveMQ it must have loaded the necessary classes on its classpath. To make this possible you should copy the jar activemq-all-5.2.0.jar into your $TOMCAT_HOME$/lib directory.
These are the steps to setup Tomcat. Now you have to tell your Mule application it has to access this datasource instead creating its own pool. For this add the following to your Mule config:
- Define your (Spring) datasource:
<bean id="activeMqConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:comp/env/jms/shipJMS"/> </bean>
<jms:activemq-connector name="JMSConnector" specification="1.1" dynamicNotification="true" connectionFactory-ref="activeMqConnectionFactory" acknowledgementMode="AUTO_ACKNOWLEDGE" maxRedelivery="3" disableTemporaryReplyToDestinations="true" persistentDelivery="true"> <custom-exception-strategy class="nl.redstream.exceptionhandlers.DefaultConnectorExceptionHandler" enableNotifications="true"> <vm:outbound-endpoint connector-ref="vmConnector" path="error-handler" /> </custom-exception-strategy> <ee:retry-forever-policy frequency="30000"/> </jms:activemq-connector>
In the next post I show how to config your unit tests to work with this configuration