0 Replies Latest reply on Mar 11, 2013 5:07 AM by Tamas Benke

    Camel/Spring integration between JBoss MQ-s

    Tamas Benke Newbie

      Hello 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&amp;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://forum.springsource.org/showthread.php?17491-Failed-to-convert-SpyConnectionFactory-to-ConnectionFactory

      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.stevideter.com/2008/08/25/simplifying-spring%E2%80%99s-jms-configuration-for-jnditemplate/

      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://forum.springsource.org/showthread.php?120990-Error-on-using-Jndi-Template-for-Spring-Integration-amp-MQ-connection

      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://stackoverflow.com/questions/1974883/jboss-4-2-2-to-5-0-1-migrationneeded-jboss-client-jar-files

      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

      https://issues.jboss.org/secure/attachmentzip/unzip/12400214/12330767%5B63%5D/jts-exampleJZ/src/com/arjuna/ats/tools/TxTestJR.java

      http://www.mastertheboss.com/jboss-jms/jboss-jms-configuration/page-2

      http://www.mastertheboss.com/jboss-jms/jboss-jms-queue-example

      http://stackoverflow.com/questions/11471679/spring-configure-the-datasource-through-jndi-having-remote-jboss-server

      http://fusesource.com/forums/thread.jspa?messageID=7828

      https://community.jboss.org/message/439509#439509

      http://docs.jboss.org/jbossmessaging/docs/userguide-1.4.0.SP3/html/installation.html#install.extra-steps

      http://www.tutorials.de/enterprise-java-jee-j2ee-spring-co/355197-invalidmarshallingresource-can-not-find-valid-marshaller-data-type-jms.html

      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://www.tutorials.de/enterprise-java-jee-j2ee-spring-co/355197-invalidmarshallingresource-can-not-find-valid-marshaller-data-type-jms.html

      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