1
votes

I am trying to pick up a message off an ActiveMQ Queue and pass it to a Websphere MQ Queue.

I'm using WSO2 as eventually we will want to use all the capabilities it gives us.

The problem seems to be that WSO2 attempts to pass the ActiveMQ MessageId directly to Websphere MQ as the Correlation Id - which is in the wrong format.

I have tried to remove the TRANSPORT_HEADERS but I must be doing something wrong.

I added a dummy property JMS_CORRELATION_ID (as per this post) to the inSequence to see if I could verify this but Websphere MQ does not recognise this header it seems.

Happily enough passing a message from Websphere MQ to ActiveMQ works fine in another Proxy service I have created. In that case The Websphere MQ Message Id gets passed to the Active MQ correlation id.

This is the exception

[2013-03-08 12:18:23,414] ERROR - JMSSender Error creating a JMS message from the message context
com.ibm.msg.client.jms.DetailedJMSException: JMSCMQ1044: String is not a valid hexadecimal number - 'dolguldur-51590-1362693989456-3:4:1:1:4'.
Either an attempt was made to specify a group ID or correlation ID which starts with the prefix ID but is not followed by a well-formed hexadecimal value, or an attempt was made to receive a message w
hich contains an MQRFH2 property of type bin.hex that does not have a well-formed hexadecimal value.
Ensure that a valid hexadecimal value always follows the ID prefix when setting group ID or correlation ID values. Ensure that any MQRFH2 headers generated by non-JMS applications are well-formed.
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at com.ibm.msg.client.commonservices.j2se.NLSServices.createException(NLSServices.java:319)
        at com.ibm.msg.client.commonservices.nls.NLSServices.createException(NLSServices.java:233)
        at com.ibm.msg.client.wmq.common.internal.WMQUtils.hexToBin(WMQUtils.java:414)
        at com.ibm.msg.client.wmq.common.internal.WMQUtils.stringToId(WMQUtils.java:496)
        at com.ibm.msg.client.wmq.common.internal.messages.WMQMessageHeader.setJMSCorrelationID(WMQMessageHeader.java:314)
        at com.ibm.msg.client.jms.internal.JmsMessageImpl.setJMSCorrelationID(JmsMessageImpl.java:610)
        at com.ibm.jms.JMSMessage.setJMSCorrelationID(JMSMessage.java:1133)
        at org.apache.axis2.transport.jms.JMSSender.createJMSMessage(JMSSender.java:428)
        at org.apache.axis2.transport.jms.JMSSender.sendOverJMS(JMSSender.java:172)
        at org.apache.axis2.transport.jms.JMSSender.sendMessage(JMSSender.java:154)
        at org.apache.axis2.transport.base.AbstractTransportSender.invoke(AbstractTransportSender.java:112)
        at org.apache.axis2.engine.AxisEngine$TransportNonBlockingInvocationWorker.run(AxisEngine.java:626)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
[2013-03-08 12:18:23,417]  INFO - AxisEngine [MessageContext: logID=a7a3184cd19f3b5ab7a012af40cd7840329dd8fc40d0e9c3] Error creating a JMS message from the message context

WSO2 Proxy Service Configuration

<proxy xmlns="http://ws.apache.org/ns/synapse" name="TestService" transports="jms" statistics="disable" trace="disable" startOnLoad="true">
   <target>
      <inSequence>
         <property name="TRANSPORT_HEADERS" scope="transport" action="remove"/>
         <property name="OUT_ONLY" value="true"/>
         <log level="full"/>
      </inSequence>
      <endpoint>
         <address uri="jms:/QUEUE.OUT?transport.jms.ConnectionFactory=ibmMQQueueConnectionFactory"/>
      </endpoint>
   </target>
   <parameter name="transport.jms.ConnectionFactory">activeMQQueueConnectionFactory</parameter>
   <parameter name="transport.jms.Destination">TESTJMS.IN</parameter>
   <description></description>
</proxy>

axis2.xml transport receiver

  <transportReceiver name="jms" class="org.apache.axis2.transport.jms.JMSListener">
        <parameter name="activeMQQueueConnectionFactory" locked="false">
            <parameter name="java.naming.factory.initial" locked="false">org.apache.activemq.jndi.ActiveMQInitialContextFactory</parameter>
            <parameter name="java.naming.provider.url" locked="false">tcp://localhost:61616</parameter>
            <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">QueueConnectionFactory</parameter>
            <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
        </parameter>

        <parameter name="ibmMQQueueConnectionFactory" locked="false">
            <parameter name="java.naming.factory.initial" locked="false">com.sun.jndi.fscontext.RefFSContextFactory</parameter>
            <parameter name="java.naming.provider.url" locked="false">file:/E:/work/MQ-JNDI-Directory</parameter>
            <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">ConnectionFactoryTest</parameter>
            <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
        </parameter>

    </transportReceiver>

axis2.xml transport sender

org.apache.activemq.jndi.ActiveMQInitialContextFactory tcp://localhost:61616 QueueConnectionFactory queue

<parameter name="ibmMQQueueConnectionFactory" locked="false">
    <parameter name="java.naming.factory.initial" locked="false">com.sun.jndi.fscontext.RefFSContextFactory</parameter>
    <parameter name="java.naming.provider.url" locked="false">file:/E:/work/MQ-JNDI-Directory</parameter>
    <parameter name="transport.jms.ConnectionFactoryJNDIName" locked="false">ConnectionFactoryTest</parameter>
    <parameter name="transport.jms.ConnectionFactoryType" locked="false">queue</parameter>
</parameter>

Cheers, Steve

11/3 More information

So it looks like when I put a correlation ID such as a simple string in the ActiveMQ message I do not get the error 'JMSCMQ1044: String is not a valid hexadecimal number'.

So the mapping from active MQ to Websphere MQ correlation Id is problematic.

But this is the error I get now - looks like the class org.apache.axis2.transport.jms.JMSUtils is trying to set a JMS_DESTINATION header and Websphere MQ does not allow this?

I've verified this by writing a simple java client and tried to set the header JMS_DESTINATION, I get the same error from Websphere MQ.

Can I make Websphere MQ handle these headers? or get the JMSSender to post messages in a different way? or does the org.apache.axis2.transport.jms.JMSSender just not work with Websphere MQ at all?

Incidentally I'm using the latest Websphere MQ 7.5.

[2013-03-11 09:33:20,378] DEBUG - JMSMessageReceiver Received new JMS message for service :TestService
Destination    : queue://TESTJMS.IN
Message ID     : ID:dolguldur-50398-1362951749472-3:2:1:1:24
Correlation ID : NONE
ReplyTo        : null
Redelivery ?   : false
Priority       : 0
Expiration     : 0
Timestamp      : 1362958400374
Message Type   :
Persistent ?   : false
[2013-03-11 09:33:20,380] TRACE - JMSMessageReceiver
Message : Enter some text here for the message body...
[2013-03-11 09:33:20,381]  INFO - LogMediator To: , WSAction: urn:mediate, SOAPAction: urn:mediate, MessageID: ID:dolguldur-50398-1362951749472-3:2:1:1:24, Direction: request, Envelope: <?xml version=
'1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Body><axis2ns5:text xmlns:axis2ns5="http://ws.apache.org/commons/ns/payload">Enter some tex
t here for the message body...</axis2ns5:text></soapenv:Body></soapenv:Envelope>
[2013-03-11 09:33:20,388] DEBUG - JMSConnectionFactory Creating a new JMS Session from JMS CF : ibmMQQueueConnectionFactory
[2013-03-11 09:33:20,392] DEBUG - JMSConnectionFactory Creating a new JMS MessageProducer from JMS CF : ibmMQQueueConnectionFactory
[2013-03-11 09:33:20,393] ERROR - JMSSender Error creating a JMS message from the message context
com.ibm.msg.client.jms.DetailedMessageFormatException: JMSCC0050: The property name 'JMS_DESTINATION' is reserved and cannot be set.
The supplied property name begins with the JMS prefix, but is not one of the supported, settable properties.
Check the property name and correct errors.
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at com.ibm.msg.client.commonservices.j2se.NLSServices.createException(NLSServices.java:319)
        at com.ibm.msg.client.commonservices.nls.NLSServices.createException(NLSServices.java:233)
        at com.ibm.msg.client.jms.internal.JmsErrorUtils.createException(JmsErrorUtils.java:109)
        at com.ibm.msg.client.jms.internal.JmsMessageImpl.checkSettablePropertyName(JmsMessageImpl.java:2125)
        at com.ibm.msg.client.jms.internal.JmsMessageImpl.setStringProperty(JmsMessageImpl.java:1560)
        at com.ibm.jms.JMSMessage.setStringProperty(JMSMessage.java:1496)
        at org.apache.axis2.transport.jms.JMSUtils.setTransportHeaders(JMSUtils.java:278)
        at org.apache.axis2.transport.jms.JMSSender.createJMSMessage(JMSSender.java:441)
        at org.apache.axis2.transport.jms.JMSSender.sendOverJMS(JMSSender.java:172)
        at org.apache.axis2.transport.jms.JMSSender.sendMessage(JMSSender.java:154)
        at org.apache.axis2.transport.base.AbstractTransportSender.invoke(AbstractTransportSender.java:112)
        at org.apache.axis2.engine.AxisEngine$TransportNonBlockingInvocationWorker.run(AxisEngine.java:626)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
[2013-03-11 09:33:20,399] ERROR - AsyncCallback Error creating a JMS message from the message context
org.apache.axis2.AxisFault: Error creating a JMS message from the message context
        at org.apache.axis2.transport.base.AbstractTransportSender.handleException(AbstractTransportSender.java:226)
        at org.apache.axis2.transport.jms.JMSSender.sendOverJMS(JMSSender.java:174)
        at org.apache.axis2.transport.jms.JMSSender.sendMessage(JMSSender.java:154)
        at org.apache.axis2.transport.base.AbstractTransportSender.invoke(AbstractTransportSender.java:112)
        at org.apache.axis2.engine.AxisEngine$TransportNonBlockingInvocationWorker.run(AxisEngine.java:626)
        at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
        at java.lang.Thread.run(Thread.java:662)
Caused by: com.ibm.msg.client.jms.DetailedMessageFormatException: JMSCC0050: The property name 'JMS_DESTINATION' is reserved and cannot be set.
The supplied property name begins with the JMS prefix, but is not one of the supported, settable properties.
Check the property name and correct errors.
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at com.ibm.msg.client.commonservices.j2se.NLSServices.createException(NLSServices.java:319)
        at com.ibm.msg.client.commonservices.nls.NLSServices.createException(NLSServices.java:233)
        at com.ibm.msg.client.jms.internal.JmsErrorUtils.createException(JmsErrorUtils.java:109)
        at com.ibm.msg.client.jms.internal.JmsMessageImpl.checkSettablePropertyName(JmsMessageImpl.java:2125)
        at com.ibm.msg.client.jms.internal.JmsMessageImpl.setStringProperty(JmsMessageImpl.java:1560)
        at com.ibm.jms.JMSMessage.setStringProperty(JMSMessage.java:1496)
        at org.apache.axis2.transport.jms.JMSUtils.setTransportHeaders(JMSUtils.java:278)
        at org.apache.axis2.transport.jms.JMSSender.createJMSMessage(JMSSender.java:441)
        at org.apache.axis2.transport.jms.JMSSender.sendOverJMS(JMSSender.java:172)
        ... 6 more
1
Thanks for that, so as WSO2 can't actually set the MessageID as per your post it must be setting something else.Steve666

1 Answers

1
votes

This is because WebSphere MQ honors the JMS specification which states that the message ID is always set by the transport provider. Please see the JMS 1.1 specification:


3.4.3 JMSMessageID
The JMSMessageID header field contains a value that uniquely identifies each message sent by a provider.

When a message is sent, JMSMessageID is ignored. When the send method returns, the field contains a provider-assigned value.


This is confirmed in the WMQ Infocenter topic Mapping JMS header fields at send() or publish() which says:

All messages sent from JMS have unique message identifiers assigned by WebSphere® MQ. The value assigned is returned in the MQMD.MessageId field after the MQPUT call, and is passed back to the application in the JMSMessageID field. The WebSphere MQ messageId is a 24-byte binary value, whereas the JMSMessageID is a string. The JMSMessageID is composed of the binary messageId value converted to a sequence of 48 hexadecimal characters, prefixed with the characters ID:. JMS provides a hint that can be set to disable the production of message identifiers. This hint is ignored, and a unique identifier is assigned in all cases. Any value that is set into the JMSMessageId field before a send() is overwritten.

You can either cache the message IDs and correlate them as they pass through the broker, or else it could be done by dropping out of the JMS API and using the Java native API to send the message. Assuming that you are using a modern version of WebSphere MQ, the JMS message no longer requires RFH2 headers and instead carries JMS properties as native WMQ message properties. This means that JMS apps can read native WMQ messages as though they were JMS messages in most cases, assuming the app uses a modern QMgr and modern version of the JMS classes.

The latest WMQ client and JMS classes are at SupportPac MQC75 if you need to update.