Camel/Spring integration between JBoss MQ-s
tbenke Mar 11, 2013 5:07 AMHello Everybody!
I have worked for a while on a Camel route, between some JBoss MQ-s and other (file, Karaf log) endpoints.
I use Apache ServiceMix 4.4.2 (with Camel 2.8.5 and Spring 3.0.6.RELEASE inside), and JBoss [EAP] 5.1.1, under Microsoft Windows 7 Professional 64-bit SP1.
I had to shift (with +300) the port set of JBoss to avoid interference with ServiceMix and Oracle 11g database, so that I run JBoss with this command:
run.bat -Djboss.service.binding.set=ports-03
I have created two JBoss queue-s by means of the admin console of JBoss, with JNDI names queue/Test1 and queue/Test2.
I collected a set of JBoss dependency JARs, and OSGi-fied them with the BND tool:
concurrent.jar
javassist.jar
jboss-aop-client.jar
jboss-client.jar
jboss-common-core.jar
jboss-ha-client.jar
jboss-ha-legacy-client.jar
jboss-javaee.jar
jboss-logging-spi.jar
jboss-mdr.jar
jboss-messaging-client.jar
jboss-remoting.jar
jboss-security-spi.jar
jboss-serialization.jar
jmx-invoker-adaptor-client.jar
jnp-client.jar
trove.jar
I have used some other JARs as well, but I think, they didn't make any difference:
jbossmq.jar
jbossall-client.jar
jbossmq-client.jar
jboss-jmx.jar
I have used this Spring camel-context.xml (containing 3 route definitions):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:camel="http://camel.apache.org/schema/spring"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring
http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext xmlns="http://camel.apache.org/schema/spring">
<!--route>
<from uri="file:c:/HELLO" />
<convertBodyTo type="String" charset="UTF-8" />
<to uri="jbossjms:queue:Test1" />
</route-->
<!--route>
<from uri="timer://foo?fixedRate=true&period=5s" />
<transform>
<simple>ABCdef</simple>
</transform>
<to uri="jbossjms:queue:Test1" />
</route-->
<route>
<from uri="jbossjms:queue:Test1" />
<to uri="log:Test1" />
</route>
</camelContext>
<bean name="jbossjms" class="org.apache.camel.component.jms.JmsComponent">
<property name="connectionFactory" ref="jbossJmsConnectionFactory"/>
</bean>
<bean name="jbossJmsConnectionFactory" id="jbossJmsConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiTemplate">
<ref bean="jbossJndiTemplate" />
</property>
<property name="jndiName">
<value>ConnectionFactory</value>
</property>
</bean>
<bean id="jbossJndiTemplate" class="org.springframework.jndi.JndiTemplate">
<property name="environment">
<props>
<prop key="java.naming.factory.initial">org.jnp.interfaces.NamingContextFactory</prop>
<prop key="java.naming.provider.url">jnp://localhost:1399</prop>
<prop key="java.naming.factory.url.pkgs">org.jnp.interfaces:org.jboss.naming</prop>
<prop key="java.naming.security.principal">admin</prop>
<prop key="java.naming.security.credentials">admin</prop>
</props>
</property>
</bean>
</beans>
The first (File >> JBoss MQ) and second (Timer >> JBoss MQ) routes are working properly, if I drop the
above mentioned dependencies and the camel-context.xml to ServiceMix's /deploy folder.
The third (JBoss MQ >> Karaf log) route does not process messages, despite the consumer appears on the Test1
JBoss queue, and the bundle/route status is Active/Started.
The automatic OSGi headers of the deployed camel-context.xml are:
Manifest-Version = 2
Spring-Context = *;publish-context:=false;create-asynchronously:=true
Bundle-SymbolicName = test-jms.xml
Bundle-Version = 0.0.0
Bundle-ManifestVersion = 2
DynamicImport-Package =
*
Import-Package =
org.apache.camel.component.jms,
org.springframework.jndi
The imports of this camel-context.xml artifact are:
System Bundle (0): org.osgi.service.packageadmin; version=1.2.0
System Bundle (0): org.xml.sax; version=0.0.0
System Bundle (0): org.apache.xerces.impl.dv.xs; version=2.11.0
System Bundle (0): org.apache.xerces.impl.dv.dtd; version=2.11.0
activemq-core (50): org.apache.activemq; version=5.5.1
activemq-core (50): org.apache.activemq.util; version=5.5.1
Spring Context (65): org.springframework.jndi; version=3.0.6.RELEASE
Spring Beans (66): org.springframework.beans.factory.xml; version=3.0.6.RELEASE
Spring Beans (66): org.springframework.beans.propertyeditors; version=3.0.6.RELEASE
camel-core (91): org.apache.camel.spi; version=2.8.5
camel-core (91): org.apache.camel; version=2.8.5
camel-jms (118): org.apache.camel.component.jms; version=2.8.5
jboss-common-core (463): org.jboss.util.propertyeditor; version=0.0.0
jboss-common-core (463): org.jboss.util.threadpool; version=0.0.0
jnp-client (464): org.jnp.interfaces; version=0.0.0
jboss-remoting (469): org.jboss.remoting; version=0.0.0
jboss-remoting (469): org.jboss.remoting.marshal; version=0.0.0
jboss-messaging-client (476): org.jboss.jms.client; version=0.0.0
jboss-messaging-client (476): org.jboss.jms.client.delegate; version=0.0.0
jboss-messaging-client (476): org.jboss.jms.client.remoting; version=0.0.0
jboss-messaging-client (476): org.jboss.jms.server.remoting; version=0.0.0
jboss-messaging-client (476): org.jboss.messaging.util; version=0.0.0
Of course, there are no exports.
I made a complete OSGi bundle JAR from the mentioned camel-context.xml, with the following MANIFEST.MF:
Manifest-Version: 1.0
DynamicImport-Package: *
Bundle-Version: 1.0.0
Build-Jdk: 1.7.0_17
Built-By: U522971
Tool: Bnd-1.15.0
Bnd-LastModified: 1362746498060
Bundle-Name: A Camel Spring-DM Route
Bundle-ManifestVersion: 2
Created-By: Apache Maven Bundle Plugin
Import-Package: javax.jms,javax.naming,javax.naming.spi,javax.net,org.
apache.activemq,org.apache.camel.component.jms,org.jboss.mq,org.jboss
.mq.referenceable,org.jnp.interfaces,org.springframework.jms.core,org
.springframework.jndi;version="[2.5,4)"
Bundle-SymbolicName: jboss-route
The org.jboss.mq package was missing, so I deployed jboss/jbossmq_3.2.3.jar (downloaded and bundlefied from a local Maven repository).
The bundle was immediately started, and the behavior of the routes was exactly the same as I mentioned above.
It looks wery cool and simple to write down, but in reality, I spent approximately 2.5 months with it,
and after all, I still don't have a Camel/Spring config to consume from a JBoss MQ!
I have read a number of resources (including official JBoss/Camel documentation); for example:
http://www.jboss.org/jbossas/docs
https://issues.jboss.org/browse/JBBOOT-138
http://www.coderanch.com/t/90486/JBoss/Failed-load-users-passwords-role
http://docs.jboss.org/jbossas/getting_started/v5/html/tour.html#d0e569
http://docs.jboss.org/jbossas/jboss4guide/r4/html/ch6.chapt.html
http://www.mastertheboss.com/jboss-jms/jboss-jms-queue-example
http://stackoverflow.com/questions/2478729/jboss-messaging-jms
http://onjava.com/pub/a/onjava/2006/02/22/asynchronous-messaging-with-spring-jms.html?page=1
http://integrationsphere.blogspot.hu/2011/07/camel-and-hornetq-as-jms-provider.html
http://integrationsphere.blogspot.hu/2011/07/camel-and-hornetq-as-jms-provider.html
http://java.dzone.com/articles/camel-and-hornetq-jms-provider
http://www.theserverside.com/discussions/thread.tss?thread_id=9653
https://community.jboss.org/thread/29768
http://stackoverflow.com/questions/5256060/ejb-exception-while-try-to-run-the-client
http://docs.jboss.org/jbossmessaging/docs/userguide-1.4.2.GA/html/installation.html
http://mavenhub.com/c/org/jnp/interfaces/namingcontextfactory/dependency
https://community.jboss.org/thread/154570
https://community.jboss.org/message/207352#207352
https://community.jboss.org/thread/175935
https://community.jboss.org/thread/162575
http://www.javamonamour.org/2011/03/me-jms-hermesjms-and-jboss.html
http://forum.springsource.org/showthread.php?59005-JNDI-connection-factory-config
http://www.mydeveloperconnection.com/html/Spring-JNDI-Datasource..htm
http://forum.springsource.org/showthread.php?60768-Configuring-Initial-Context
http://forum.springsource.org/archive/index.php/t-124901.html
http://java.dzone.com/articles/bridging-between-jms-and
http://mail-archives.apache.org/mod_mbox/camel-users/201111.mbox/%3C1322215472697-5022416.post@n5.nabble.com%3Erg/mod_mbox/camel-users/201111.mbox/%3C1322215472697-5022416.post@n5.nabble.com%3E
http://72.2.112.194/tag/spring
http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch23s04.html
http://www.mentby.com/Group/apache-camel/jms-transaction-in-jboss-camel-is-not-work.html
http://www.torsten-horn.de/techdocs/jee-jndi.htm
http://karaf.922171.n3.nabble.com/Paxexam-karaf-startup-issue-td3914766.html
http://karaf.922171.n3.nabble.com/Paxexam-karaf-startup-issue-td3916549.html
http://www.castor.org/spring-orm-integration.html
http://fusesource.com/docs/esb/3.5/jms/ESBJMSConnectFactoryJNDI.html
http://forum.springsource.org/showthread.php?58223-Using-JNDI-to-configure-a-JndiTemplate
https://community.jboss.org/thread/152456
http://grokbase.com/t/servicemix/users/068yn1azmv/jndi-and-jbossmq
http://docs.oracle.com/javase/jndi/tutorial/TOC.html
http://activemq.2283324.n4.nabble.com/Route-messages-from-HornetQ-to-ActiveMQ-td4435172.html
http://docs.jboss.org/jbossremoting/2.5.4.SP2/userguide/html_single/
http://docs.jboss.org/jbossremoting/2.5.3.SP1/html/
http://stackoverflow.com/questions/8561622/jboss-as-7-simple-hello-world-application
https://community.jboss.org/message/613171
http://www.mastertheboss.com/jboss-configuration/the-jndiproperty-pitfall
http://www.mastertheboss.com/jboss-configuration/jboss-port-configuration
http://www.mastertheboss.com/jboss-jms
http://www.mastertheboss.com/jboss-jms/jboss-jms-configuration/page-2
http://www.mastertheboss.com/jboss-jms/jboss-jms-queue-example
http://www.mastertheboss.com/jboss-jms/jboss-jms-configuration/page-2
http://www.mastertheboss.com/jboss-jms/jboss-jms-queue-example
http://fusesource.com/forums/thread.jspa?messageID=7828
https://community.jboss.org/message/439509#439509
http://integrationsphere.blogspot.hu/2011/07/camel-and-hornetq-as-jms-provider.html
https://community.jboss.org/thread/128897
https://community.jboss.org/thread/1468
http://camel.apache.org/maven/current/camel-jms/apidocs/org/apache/camel/component/jms/JmsComponent.html [JBoss JMS Component Javadoc]
http://docs.jboss.org/jbossas/jboss4guide/r4/html/ch3.chapter.html
http://www.coderanch.com/t/459111/java/java/security-manager-rmi-class-loader
https://community.jboss.org/message/197278
http://s139.codeinspot.com/q/878267
http://forum.springsource.org/showthread.php?90417-Using-JMS-Namespace-Support-to-configure-JBoss
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/jms.html
I had many weird errors as well (later debugged), but I still cannot make my Camel route to consume from JBoss.
I have written three POJO's to send and receive from/to JBoss, as well.
First is Sender.java:
package jBossMain;
import javax.jms.*;
import javax.naming.*;
import java.util.Hashtable;
public class Sender
{
public static final String JNDI_URL = "jnp://localhost:1399";
public static final String JNDI_CONTEXT_FACTORY = "org.jnp.interfaces.NamingContextFactory";
public static final String JMS_USER = null;
public static final String JMS_PASSWORD = null;
public static final String JMS_CONNECTION_FACTORY = "ConnectionFactory";
public static final String QUEUE_JNDI_NAME = "/queue/Test1";
public static void main( String[] args )
{
QueueConnection qConn = null;
QueueSession qSession = null;
QueueSender qSender = null;
try
{
//Context parameters
Hashtable<String, String> env = new Hashtable<String, String>();
env.put( Context.INITIAL_CONTEXT_FACTORY, JNDI_CONTEXT_FACTORY );
env.put( Context.PROVIDER_URL, JNDI_URL );
if( JMS_USER != null )
{
env.put( Context.SECURITY_PRINCIPAL, JMS_USER );
}
if( JMS_PASSWORD != null )
{
env.put( Context.SECURITY_CREDENTIALS, JMS_PASSWORD );
}
//Creating context
Context jndiContext = new InitialContext( env );
//Queue connection factory
QueueConnectionFactory cFactory = (QueueConnectionFactory) jndiContext.lookup(JMS_CONNECTION_FACTORY);
//Create Connection
if( JMS_USER == null || JMS_PASSWORD == null )
{
qConn = cFactory.createQueueConnection();
}
else
{
qConn = cFactory.createQueueConnection( JMS_USER, JMS_PASSWORD );
}
//Create Session
qSession = qConn.createQueueSession( false, Session.AUTO_ACKNOWLEDGE );
//Lookup Queue
Queue queue = (Queue) jndiContext.lookup(QUEUE_JNDI_NAME);
//Create Queue Sender
qSender = qSession.createSender( queue );
//Start receiving messages
qConn.start();
//Close JNDI context
jndiContext.close();
TextMessage msg = qSession.createTextMessage("Hello World!");
qSender.send(msg);
Thread.sleep(2000);
if(qSender != null) qSender.close();
if(qSession != null) qSession.close();
if(qConn != null) qConn.close();
}
catch( Exception e )
{
e.printStackTrace();
}
}
}
Second is SerialReceiver.java, which can consume only 1 message per run:
package jBossMain;
import javax.jms.*;
import javax.naming.*;
import java.util.Hashtable;
public class SerialReceiver
{
public static final String JNDI_URL = "jnp://localhost:1399";
public static final String JNDI_CONTEXT_FACTORY = "org.jnp.interfaces.NamingContextFactory";
public static final String JMS_USER = null;
public static final String JMS_PASSWORD = null;
public static final String JMS_CONNECTION_FACTORY = "ConnectionFactory";
public static final String QUEUE_JNDI_NAME = "/queue/Test1";
public static void main( String[] args )
{
QueueConnection qConn = null;
QueueSession qSession = null;
QueueReceiver qReceiver = null;
try
{
//Context parameters
Hashtable<String, String> env = new Hashtable<String, String>();
env.put( Context.INITIAL_CONTEXT_FACTORY, JNDI_CONTEXT_FACTORY );
env.put( Context.PROVIDER_URL, JNDI_URL );
if( JMS_USER != null )
{
env.put( Context.SECURITY_PRINCIPAL, JMS_USER );
}
if( JMS_PASSWORD != null )
{
env.put( Context.SECURITY_CREDENTIALS, JMS_PASSWORD );
}
//Creating context
Context jndiContext = new InitialContext( env );
//Queue connection factory
QueueConnectionFactory cFactory = (QueueConnectionFactory) jndiContext.lookup(JMS_CONNECTION_FACTORY);
//Create Connection
if( JMS_USER == null || JMS_PASSWORD == null )
{
qConn = cFactory.createQueueConnection();
}
else
{
qConn = cFactory.createQueueConnection( JMS_USER, JMS_PASSWORD );
}
//Create Session
qSession = qConn.createQueueSession( false, Session.AUTO_ACKNOWLEDGE );
//Lookup Queue
Queue queue = (Queue) jndiContext.lookup(QUEUE_JNDI_NAME);
//Create Queue Receiver
qReceiver = qSession.createReceiver( queue );
//Start receiving messages
qConn.start();
//Close JNDI context
jndiContext.close();
//javax.jms.TextMessage object, body can be extracted.
TextMessage msg = (TextMessage) qReceiver.receive();
Thread.sleep(2000);
if(qReceiver != null) qReceiver.close();
if(qSession != null) qSession.close();
if(qConn != null) qConn.close();
System.out.println( msg.toString() );
//Only available if msg is of type TextMessage:
System.out.println( msg.getText() );
}
catch( Exception e )
{
e.printStackTrace();
}
}
}
Third is ContinuousReceiver.java, which will receive all messages from the queue while running:
package jBossMain;
import javax.jms.*;
import javax.naming.*;
import java.util.Hashtable;
public class ContinuousReceiver implements MessageListener
{
public static final String JNDI_URL = "jnp://localhost:1399";
public static final String JNDI_CONTEXT_FACTORY = "org.jnp.interfaces.NamingContextFactory";
public static final String JMS_USER = null;
public static final String JMS_PASSWORD = null;
public static final String JMS_CONNECTION_FACTORY = "ConnectionFactory";
public static final String QUEUE_JNDI_NAME = "/queue/Test1";
public static void main( String[] args )
{
QueueConnection qConn = null;
QueueSession qSession = null;
QueueReceiver qReceiver = null;
try
{
//Context parameters
Hashtable<String, String> env = new Hashtable<String, String>();
env.put( Context.INITIAL_CONTEXT_FACTORY, JNDI_CONTEXT_FACTORY );
env.put( Context.PROVIDER_URL, JNDI_URL );
if( JMS_USER != null )
{
env.put( Context.SECURITY_PRINCIPAL, JMS_USER );
}
if( JMS_PASSWORD != null )
{
env.put( Context.SECURITY_CREDENTIALS, JMS_PASSWORD );
}
//Creating context
Context jndiContext = new InitialContext( env );
//Queue connection factory
QueueConnectionFactory cFactory = (QueueConnectionFactory) jndiContext.lookup(JMS_CONNECTION_FACTORY);
//Create Connection
if( JMS_USER == null || JMS_PASSWORD == null )
{
qConn = cFactory.createQueueConnection();
}
else
{
qConn = cFactory.createQueueConnection( JMS_USER, JMS_PASSWORD );
}
//Create Session
qSession = qConn.createQueueSession( false, Session.AUTO_ACKNOWLEDGE );
//Lookup Queue
Queue queue = (Queue) jndiContext.lookup(QUEUE_JNDI_NAME);
//Create Queue Receiver
qReceiver = qSession.createReceiver( queue );
ContinuousReceiver CR = new ContinuousReceiver();
qReceiver.setMessageListener( CR );
//Start receiving messages
qConn.start();
//Close JNDI context
jndiContext.close();
Thread.sleep(25000);
if(qReceiver != null) qReceiver.close();
if(qSession != null) qSession.close();
if(qConn != null) qConn.close();
}
catch( Exception e )
{
e.printStackTrace();
}
}
public void onMessage( Message message )
{
try
{
System.out.println( "The type of the received message is: " + message.getJMSType() );
if( message instanceof TextMessage )
{
TextMessage textMessage = ( TextMessage ) message;
System.out.println( "The text content: " + textMessage.getText() );
}
else
{
System.out.println( message.toString() );
}
}
catch(JMSException je)
{
je.printStackTrace();
}
}
}
I have tried to embed these POJO-s, as Processor beans, into Camel routes, with no success.
I was not able to run them in ServiceMix. (They were originally running in Eclipse, so I bundlefied and deployed tose JBoss JARs, which were imported automatically by the IDE.)
It is rather funny to me, that only a number of forum topics deal with such a cardinal question: how to make Camel routes between
JBoss MQ-s, and something else. JBoss MQ-s are widely used...
Also, if there is a handful of topics on it, they do not conclude to anything, or they state some wrong,
stupid solutions, that doesn't work.
So I kindly ask, if there is a single man/woman on the Internet, who can solve this problem IN REALITY,
please tell the EXACT solution to me.
I am especially interested in:
- the exact Camel/Spring config,
- the JAr's Import-Package statements,
- and the dependency JARs GAV values.
[Perhaps my JBoss is not configured properly (I don't think so), or I missed some beans from the camel-context.xml...]
With best regards:
Tamás Benke
Junior Java developer, IOCC team
Lufthansa Systems Hungária Kft.
BUD LSYH - Airline Management Solutions
INFOPARK, Building E
Neumann János u. 1./E.
H-1117 Budapest
Hungary
E-mail: tamas.benke.U522971@LHsystems.com
www.LHsystems.com