Announcement Announcement Module
Collapse
No announcement yet.
Issue with IBM MQ to non-JMS (CICS) client Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Issue with IBM MQ to non-JMS (CICS) client

    I am having a real heck of an issue here. I am sending TextMessages from a Java app (using Spring JMS) to a CICS client (MQ-only). The messages appear garbled on the CICS side (I have no control over that side; I can only see message traces in the log).

    I have come to realize that I must set targetClient to 1 (MQJMS_CLIENT_NONJMS_MQ) to get MQ to take off the header. The problem, which I can deduce from examining the message in BMC's JMS viewer, is that the header is still there, as there are properties like mcd.Msd, mcd.Type, etc., visible in the properties tab.

    (I am replicating the functionality of an existing app that does NOT have this problem. The legacy app does not use Spring JMS. I am trying to setup my connection & queue in identical manner.)

    Here is the config for the QueueConnectionFactory and Queue:

    <bean id="outboundJmsConnectionFactory" class="com.ibm.mq.jms.MQQueueConnectionFactory">
    <property name="transportType">
    <util:constant static-field="com.ibm.mq.jms.JMSC.MQJMS_TP_CLIENT_MQ_TCPI P"/>
    </property>
    <property name="hostName" value="${grs.mq.out.queue.host}"/>
    <property name="port" value="${grs.mq.out.queue.port}"/>
    <property name="queueManager" value="${grs.mq.out.queue.manager}"/>
    <property name="channel" value="${grs.mq.out.queue.channel}"/>
    </bean>

    <bean id="jmsSenderQueue" class="com.ibm.mq.jms.MQQueue">
    <property name="baseQueueManagerName" value="${grs.mq.out.queue.manager}"/>
    <property name="baseQueueName" value="${grs.mq.out.queue.name}"/>
    <property name="targetClient" value="1"/>
    <property name="CCSID" value="${mq.ccsid}"/>
    <property name="persistence" value="2"/>
    </bean>

    It seems that my targetClient must not be "taking" as it is still including that header. In fact, I have tried multiple methods of setting targetClient, but none do the job.

    This is MQ v7.

    Help greatly appreciated - time is very much of the essence here! Thanks.

  • #2
    Just wanted to add my JmsTemplate & Sender config:

    <bean id="jmsQueueTemplate" class="org.springframework.jms.core.JmsTemplate">
    <property name="connectionFactory">
    <ref bean="outboundJmsConnectionFactory"/>
    </property>
    <!--<property name="defaultDestinationName" value="queue:///default?targetClient=1"/>-->
    <property name="defaultDestination">
    <ref bean="jmsSenderQueue"/>
    </property>
    <property name="pubSubDomain">
    <value>false</value>
    </property>
    <property name="receiveTimeout">
    <value>20000</value>
    </property>
    </bean>

    <bean id="jmsMessageSender" class="com.kohls.giftregistry.batch.JMSMessageSend er">
    <constructor-arg type="org.springframework.jms.core.JmsTemplate" ref="jmsQueueTemplate"/>
    </bean>

    Nothing much of interest there.

    You can see (commented-out line) I also tried to set the targetClient using the Template's defaultDestinationName property - that didn't work either.

    Comment


    • #3
      By the way, when I say "header" above of course I mean the MQRFH header. In MQ, non-JMS clients (mainframes generally) cannot have this header present in the message as they don't know how to handle it. (In this case, although I don't have access to the parsing code, I can see that the header data is pushing into where it expects the body to be.)

      Comment


      • #4
        Please use [ code ] ... [ /code ] tags around code/config (no spaces in brackets) it makes it easier to read.

        Is the existing app using JMS or native MQ APIs?

        If native, you need to figure out the magic sauce needed to make it work with JMS - in this context, Spring is simply a convenience layer on top of JMS, making it easier to use, while still allowing access to lower level JMS APIs when necessary (and it may be necessary in this case, I don't know).

        Comment


        • #5
          Gary,

          Sorry about my messy newbie post.

          It's native MQ. Yes, that's the issue here. And I do realize this is primarily an MQ issue (I've posted a message to their forum as well), but I thought that perhaps either someone here might be familiar with the problem, and/or there is indeed a Spring-specific issue (small chance).

          The existing, non-Spring app does nothing other than set targetClient to 1:


          Code:
          writeQueue = this.queueSession.createQueue("queue://" + writeQueueManager + "/" + writeQueue + "?peristence=2&targetClient=1&CCSID=0");
          and it works.

          It would be great if I could step through my sending code but I can't (can't run it locally). Perhaps I need to start making subclasses to facilitate tracing.

          Comment


          • #6
            It's been a (large) number of years since I worked closely with MQ, but I seem to recall that I had (and solved) and similar problem (suppressing all that RFH junk) while using Spring. I just don't recall the details, sorry.

            Comment


            • #7
              I have a bit more information.

              In my code I call JmsTemplate.send() using this string as the destinationName:

              Code:
              GR.GIFT.REGISTRY.LOST.SALES.RESPONSE.Q?persistence=2&targetClient=1&CCSID=0
              After the message is sent, looking at the Properties tab of BMC, the jms.Dst property is this:

              Code:
              queue:///GR.GIFT.REGISTRY.LOST.SALES.RESPONSE.Q
              It seems that something - MQ or Spring - is somehow stripping off the (vital) targetClient parameter, along with the other params.

              Comment


              • #8
                Well, given that you have wired an appropriately configured Destination into your template (jmsSenderQueue) you should not use the form of send() that takes a destinationName. Just use the send() that uses the default destination OR use the send() option that takes a Destination object (not a destinationName).

                The default DestinationResolver creates a simple queue...

                Code:
                return session.createQueue(queueName);
                ... so it won't have the secret sauce to remove the RFH stuff.

                Comment


                • #9
                  Hi Gary,

                  I had just figured it out (really). You are quite right - passing in a dest name ignores any settings on the default dest. In retrospect: duh.

                  (The code I'm using is actually part of an existing framework which serves several types of client.)

                  I owe you a beer next time I'm in Philly.

                  Comment

                  Working...
                  X