For some testing- and debug scenarios I had the need to store all messages passing the ActiveMQ Broker to the local file system. This enables me to analyse the messages after they were fetched by the consumers. ActiveMQ provides Camel-Support. Camel is a „framework“ for Enterprise Integration Patterns. I struggled a bit with that word, so here just a few capabilities of what camel is and what it supports:
- Forwarding Messages
- Multicast Messages (forward messages from one queue to several queues / topics / etc.)
- Transform Messages
- Routing
- Piping and Filtering of Messages
- Dead Letter
- Message Bus
- find more on: http://camel.apache.org/enterprise-integration-patterns.html
Ok, now how to configure Camel in ActiveMQ:
In the conf/activemq.xml you have to import the camel.xml file:
<import resource="jetty.xml"/> <import resource="camel.xml"/>
After that, configure the broker in conf/camel.xml. At the end of the file there is a bean id=activemq. Set your broker config there.
I had to change the brokerURL:
<bean id="activemq" class="org.apache.activemq.camel.component.ActiveMQComponent" > <property name="connectionFactory"> <bean class="org.apache.activemq.ActiveMQConnectionFactory"> <property name="brokerURL" value="vm://localhost?broker.persistent=false"/> <property name="userName" value="${activemq.username}"/> <property name="password" value="${activemq.password}"/> </bean> </property> </bean>
Now have a look at the sample route in camel.xml:
<camelContext id="camel" xmlns="http://camel.apache.org/schema/spring"> <!-- You can use Spring XML syntax to define the routes here using the <route> element --> <route> <description>Example Camel Route</description> <from uri="activemq:example.A"/> <to uri="activemq:example.B"/> </route> </camelContext>
This route forwards a message from Queue example.A to example.B. Now add a multicast Route:
<route> <from uri="activemq:queue:a"/> <multicast> <to uri="activemq:queue:b"/> <to uri="activemq:queue:c"/> <to uri="activemq:queue:d"/> </multicast> </route>
Let’s assume you would like to store Messages as File:
<route> <from uri="activemq:queue:a"/> <multicast> <to uri="activemq:queue:b"/> <to uri="activemq:queue:c"/> <to uri="activemq:queue:d"/> <to uri="file://C:java/apache-activemq-5.8.0/writeMsgToFile?autoCreate=true"/> </multicast> </route>
The <to uri> expression creates a copy of the message as file in the defined directory. The autoCreate=true parameter creates the directory if it is not already there.
Lets assume you would like to set the file name for each message based on Header Parameters or the date when the message is processed:
<route> <from uri="activemq:queue:a"/> <multicast> <to uri="activemq:queue:b"/> <to uri="activemq:queue:c"/> <to uri="activemq:queue:d"/> <to uri="file://C:java/apache-activemq-5.8.0/writeMsgToFile?fileName=${date:now:yyyyMMdd}backup-${in.header.OrderType}-${date:now:hh.mm.ss.SSS}.txt"/> </multicast> </route>
The ${date:now:yyyyMMdd} creates a new directory every day. The expression ${in.header.<CustomProperty>} allows you to use some custom JMS Property. In my case I have a custom property called „OrderType“. So I know by looking the filename which kind of message is stored. The last expression ${date:now:hh.mm.ss.SSS} inserts a timestamd in every filename. This is necessary if it can happen, that severel messages arrive the broker at the same time. If you do add milliseconds (SSS) to the filename, the old file will be overwritten by the new one which arrives the broker at the same second.
That’s a first, simple introduction on camel and ActiveMQ.