Blog post added by Christian Schneider
Camel has many options for deployment. If I have the freedom of choice I prefer to run Camel on Karaf but the typical case at customers is that they have a certain app server and we have to fit in. In this case the platform was JBoss 5.1. Before Camel 2.8 this was quite complicated as camel tried to scan for typeconverters on the classpath and that part failed because of the JBoss class loader. I used camel 2.8.4 and so this was no issue except for a little problem I will come back to later.
Packaging Camel integrations as a war and using camel-servlet.
The most suitable deployment option on JBoss is to package your integration in a war archive and install it e.g. using the deploy folder. The camel-example-servlet-tomcat is the best starting point for that kind of project. It shows how to create wars using maven and also shows how to start camel from a spring application context in a servlet environment. If you know the older camel servlet examples you will notice that the way camel is started has changed recently. In older versions you had to configure the spring context xml in the camel servlet which is a rather uncommon way to start spring. The current example now shows how to start camel with the default spring context loader listener which is the much better solution.
Installing and using the ActiveMQ connection factory using jndi
The easiest way to install a connection factory for a camel integration is to define the connection factory in your spring context. This has some drawbacks though. One is that you then depend directly on ActiveMQ and can not simply replace it by another broker. The other is that
the developer has access to the password of the connection factory. Of course you can use a property file to extract this still it is not ideal. So the prefered way to find a connection factory in an app server environment is to look it up in jndi. In the spring context this is quite simple using the jee namespace:
<jee:jndi-lookup id="connectionFactory" jndi-name="activemq/XAConnectionFactory" />
A bigger problem is how to install the connection factory in JBoss so it is available in jndi. There are two ways to achieve this. One is to install it as a JEE resource adapter (see http://activemq.apache.org/jboss-integration.html). I don´t like this solution too much as it is quite complicated and requires the special activemq-ra.rar.
After a lot of searching on the net I found a nice solution.
<?xml version="1.0" encoding="UTF-8"?> <deployment xmlns="urn:jboss:bean-deployer:2.0"> <aop:lifecycle-configure xmlns:aop="urn:jboss:aop-beans:1.0" name="DependencyAdvice" class="org.jboss.aop.microcontainer.aspects.jndi.JndiLifecycleCallback" classes="@org.jboss.aop.microcontainer.aspects.jndi.JndiBinding" manager-bean="AspectManager" manager-property="aspectManager"> </aop:lifecycle-configure> <bean name="ActiveMQXAConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory"> <annotation>@org.jboss.aop.microcontainer.aspects.jndi.JndiBinding(name="activemq/XAConnectionFactory", aliases={"java:/activemq/XAConnectionFactory"})</annotation> <property name="brokerURL">tcp://localhost:61616</property> </bean> </deployment>
This JBoss mbean description initializes an ActiveMQXAConnectionFactory and installs it in the jndi context. It obviously needs the activemq-core-5.5.0.jar which I simply installed in the lib dir of the default server. The problem with this is of course that it is then available on the classpath of all wars you also install. So if some activemq specialist knows a better solution to have it only on the classpath for the mbean config I would really like to know how to do this.
When I experimented with this setup I first used the activemq-all-5.5.0.jar. The problem was that it contains an older camel version. So when I installed my camel war it was not able to start
because of problems loading typeconverters from this jar. So remember to only use the core jar.
Example project
To make it easy for you to test this out yourself I have put the code of a simple producer and consumer project on github.
To install do the following steps:
- download activemq-5.5.0, extract and start
- download jboss 5.1 and extract it
- download the example projects and build them using mvn install
- copy the jms-jboss-beans.xml to the default/deploy folder
- copy activemq-5.5.0.jar to the default/lib folder
- checkout or download https://github.com/cschneider/cameljbossha
- Build the example project with mvn clean install
- copy the war files /consumer/target/consumer-1.0.0.war and /producer/target/producer-1.0.0.war to the default/deploy folder
- start jboss
The producer offers a servlet where we can trigger a message. So open a browser and go to http://localhost:8080/producer-1.0.0/camel/tojms . The jboss log will show that the request is handled and a jms message is sent. The consumer will pick up the message and write a log entry "Message received from jms".
Summary
We have seen how to produce war projects with Apache Camel and how the usage of the camel servlet has changed recently. This part is independent from JBoss. Next we have seen that current Camel versions allow to deploy on JBoss without any special tweaks. We learned how to reference a connection factory in jndi and how to install it in JBoss.
The projects producer and consumer will be reused in my next post where I look into concepts for high availability with Camel and ActiveMQ.