4 Replies Latest reply on Feb 27, 2015 4:50 AM by rktozer

    WildFly 8.1.0.Final HornetQ JMS-Bridge issue

    rktozer

      Hi,

       

      I have been trying to set up a JMS-Bridge between some built in HornetQs and some remote Websphere MQs.

      I've added a module with the Websphere MQ libs and I've set up a .bindings file defining the remote queues so I can use the RefFSContextFactory.

      I've got the bridge set up, and can see it connect to the relevant queues.

      But when it tries to pass a message through I'm getting an exception:

      HQ122009: JMS Bridge failed to send + acknowledge batch, closing JMS objects: javax.jms.InvalidDestinationException: Not a HornetQ destination queue: <queue name>

      This seems to be caused by HornetQMessage.setJMSReplyTo passing through the headers from the incoming message, and then checking that the destination queue is a HornetQ which it's not of course because we're bridging to Websphere MQ. This sounds like a bug, as we should be able to use JMS-Bridge to connect two different MQ implementations? Or am I doing something silly somewhere?

      I see HornetQ allows configuring a Transform file in the bridge to modify message header and body, but I can't see a way to configure one in the standalone.xml in WildFly.

       

      Any advice appreciated

       

      Regards

      Richard.

        • 1. Re: WildFly 8.1.0.Final HornetQ JMS-Bridge issue
          jbertram

          Could you cut/paste the actual exception (including stack trace) that you're seeing as well as your server configuration (e.g. standalone-full.xml)?

          • 2. Re: WildFly 8.1.0.Final HornetQ JMS-Bridge issue
            rktozer

            Hi

             

            Thank you for following up.

             

            That is the actual exception, here it is with the full stack trace too:

             

            17:37:21,763 WARN  [org.hornetq.jms.server] (pool-4-thread-2) HQ122009: JMS Bridge failed to send + acknowledge batch, closing JMS objects:

            javax.jms.InvalidDestinationException: Not a HornetQ destination queue: queue://<Websphere queue name>?targetClient=1

              at org.hornetq.jms.client.HornetQMessage.setJMSReplyTo(HornetQMessage.java:446) [hornetq-jms-client-2.4.1.Final.jar:]

              at org.hornetq.jms.client.HornetQMessage.<init>(HornetQMessage.java:311) [hornetq-jms-client-2.4.1.Final.jar:]

              at org.hornetq.jms.client.HornetQTextMessage.<init>(HornetQTextMessage.java:69) [hornetq-jms-client-2.4.1.Final.jar:]

              at org.hornetq.jms.client.HornetQMessageProducer.doSendx(HornetQMessageProducer.java:439) [hornetq-jms-client-2.4.1.Final.jar:]

              at org.hornetq.jms.client.HornetQMessageProducer.send(HornetQMessageProducer.java:211) [hornetq-jms-client-2.4.1.Final.jar:]

              at org.hornetq.jms.bridge.impl.JMSBridgeImpl.sendMessages(JMSBridgeImpl.java:1752) [hornetq-jms-server-2.4.1.Final.jar:]

              at org.hornetq.jms.bridge.impl.JMSBridgeImpl.sendBatchNonTransacted(JMSBridgeImpl.java:1541) [hornetq-jms-server-2.4.1.Final.jar:]

              at org.hornetq.jms.bridge.impl.JMSBridgeImpl.sendBatch(JMSBridgeImpl.java:1508) [hornetq-jms-server-2.4.1.Final.jar:]

              at org.hornetq.jms.bridge.impl.JMSBridgeImpl.access$1400(JMSBridgeImpl.java:76) [hornetq-jms-server-2.4.1.Final.jar:]

              at org.hornetq.jms.bridge.impl.JMSBridgeImpl$SourceReceiver.run(JMSBridgeImpl.java:1969) [hornetq-jms-server-2.4.1.Final.jar:]

              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_65]

              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_65]

              at java.lang.Thread.run(Thread.java:745) [rt.jar:1.7.0_65]

             

            While the exception looks like it is just a bridgeAckError warning, it is actually being thrown when the Websphere MQ remote destination is being passed through to setJMSReplyTo.

             

            There is too much sensitive info in standalone.xml to post the whole thing, but I can post the (redacted) bits you need.

             

            Here's the incoming bridge definition that is throwing that exception:

             

            <subsystem xmlns="urn:jboss:domain:messaging:2.0">

                        <hornetq-server>

                         .

                         . //default stuff plus internal queue destinations in <jms-destinations>

                         .

                        </hornetq-server>

                        <jms-bridge name="incoming queue" module="com.ibm.mq">

                            <source>

                                <connection-factory name="com.ibm.mq.jms.MQQueueConnectionFactory"/>

                                <destination name="<external jndi queue name as defined in .bindings file>"/>

                                <context>

                                    <property key="java.naming.factory.initial" value="com.sun.jndi.fscontext.RefFSContextFactory"/>

                                    <property key="java.naming.provider.url" value="file:/<location of .bindings file>"/>

                                </context>

                            </source>

                            <target>

                                <connection-factory name="java:/ConnectionFactory"/>

                                <destination name="jboss/exported/jms/queue/<internal queue name as defined in <jms-destinations>>"/>

                            </target>

                            <quality-of-service>AT_MOST_ONCE</quality-of-service>

                            <failure-retry-interval>500</failure-retry-interval>

                            <max-retries>1</max-retries>

                            <max-batch-size>1</max-batch-size>

                            <max-batch-time>500</max-batch-time>

                            <add-messageID-in-header>true</add-messageID-in-header>

                        </jms-bridge>

            </subsystem>

             

            And the module.xml for the Websphere MQ stuff, which seems to be ok, since the bridge is connecting to the queue and receiving the message:

             

            <?xml version="1.0" encoding="UTF-8"?>

            <module xmlns="urn:jboss:module:1.1" name="com.ibm.mq">

                <properties>

                    <property name="jboss.api" value="private"/>

                </properties>

                <resources>

                    <resource-root path="com.ibm.mq.connector.jar" />

                    <resource-root path="com.ibm.mq.headers.jar" />

                    <resource-root path="com.ibm.mq.jar" />

                    <resource-root path="com.ibm.mq.jmqi.jar" />

                    <resource-root path="com.ibm.mq.pcf.jar" />

                    <resource-root path="com.ibm.mqjms.jar" />

                    <resource-root path="fscontext.jar" />

                    <resource-root path="providerutil.jar" />

                </resources>

                <dependencies>

                   <module name="javax.api" />

                   <module name="javax.jms.api" />

                   <module name="javax.transaction.api"/>

                   <module name="org.jboss.remote-naming"/>

                   <module name="org.hornetq" />

                </dependencies>

            </module>

             

            See anything wrong with those? What other sections would be helpful?

             

            Regards

            Richard.

            • 3. Re: WildFly 8.1.0.Final HornetQ JMS-Bridge issue
              jbertram

              As far as I can tell everything on the bridge is working as it should.  The problem appears to be with the message itself.

               

              When the bridge moves a message from one provider to another (in your case from WebSphereMQ to HornetQ) it has to convert the JMS message from one implementation (i.e. WebSphereMQ) to another (i.e. HornetQ).  The conversion is a fairly simple process.  The JMS API (implemented by both providers) is used to read and write the data between the two implementations.  However, the JMSReplyTo conversion is brittle because the getJMSReplyTo returns a javax.jms.Destination object rather than a primitive (e.g. int, long, etc.).  Since javax.jms.Destination is just an interface the object that getJMSReplyTo returns is (and always will be) a particular implementation of that interface.  In your case, it's a WebSphereMQ implementation.  HornetQ has no knowledge of this implementation object and therefore cannot convert it to anything meaningful so it throws an exception.

               

              I recommend that you either ensure the messages which the bridge moves do not contain a JMSReplyTo or you use something like Camel which I'm told has the ability to transform the message.

              • 4. Re: WildFly 8.1.0.Final HornetQ JMS-Bridge issue
                rktozer

                Thank you. That is pretty much the conclusion I came to, good to have it confirmed.