简体   繁体   中英

Response getting back from the ibm mq is not match for the request sometimes

I copy the java client code for how to call IBM MQ, and pass the request to the queue, but sometimes I getting the wrong response back from the queue.

For example, if I submit the following request: F LOYFI6331760101046481882

I expect from the response I should get F LOYFA36331760101046481882

But actually I getting F LOYFA36331760101051292448

As you can see the card number is wrong.

Here is the code

import javax.jms.BytesMessage;
import javax.jms.Destination;
import javax.jms.JMSConsumer;
import javax.jms.JMSContext;
import javax.jms.JMSException;
import javax.jms.JMSProducer;
import javax.jms.TextMessage;

import com.ibm.msg.client.jms.JmsConnectionFactory;
import com.ibm.msg.client.jms.JmsFactoryFactory;
import com.ibm.msg.client.wmq.WMQConstants;

public class MQClient {
    // System exit status value (assume unset value to be 1)
    private static int status = 1;

    public static byte[] sendAndReceive(String HOST, Integer PORT, String QMGR, String CHANNEL, String requestQueue, String responseQueue, String payload) {
        // Variables
        JMSContext context = null;
        Destination destination = null;
        JMSProducer producer = null;
        JMSConsumer consumer = null;
        BytesMessage receivedMessage = null;
        byte[] result = null;
        try {
            // Create a connection factory
            JmsFactoryFactory ff = JmsFactoryFactory.getInstance(WMQConstants.WMQ_PROVIDER);
            JmsConnectionFactory cf = ff.createConnectionFactory();

            // Set the properties
            cf.setStringProperty(WMQConstants.WMQ_HOST_NAME, HOST);
            cf.setIntProperty(WMQConstants.WMQ_PORT, PORT);
            cf.setStringProperty(WMQConstants.WMQ_CHANNEL, CHANNEL);
            cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
            cf.setStringProperty(WMQConstants.WMQ_QUEUE_MANAGER, QMGR);
            cf.setStringProperty(WMQConstants.WMQ_APPLICATIONNAME, "JmsPutGet (JMS)");
            cf.setStringProperty(WMQConstants.WMQ_TARGET_CLIENT, "1");
            // Create JMS objects
            context = cf.createContext();
            destination = context.createQueue("queue:///" + requestQueue +"?targetClient=1");

            TextMessage message = context.createTextMessage(payload);

            producer = context.createProducer();
            producer.send(destination, message);
            System.out.println("Sent message:\n" + message);

            destination = context.createQueue("queue:///" + responseQueue + "?targetClient=1");
            consumer = context.createConsumer(destination); // autoclosable
            receivedMessage= (BytesMessage)consumer.receive();
            System.out.println("Receiving message:" + receivedMessage);
            int text_length = new Long(receivedMessage.getBodyLength()).intValue();
            result = new byte[text_length];
            receivedMessage.readBytes(result, text_length);

            System.out.println("\nReceived message:\n" + new String(result));

            recordSuccess();

        } catch (JMSException jmsex) {
            recordFailure(jmsex);
        }finally {
            context.close();
        }

        return result;

    }
}

I have another project to run concurrently to call MQClient.sendAndReceive() method, with same host , port , QMGR , channel , requestQueue and responseQueue , only payload is different.

So how do I fix the code above to make sure I always getting the correct response corresponding to the request?

EDIT: 1. For JoshMac questions, app means the IBM MQ one? Or the app that will call my sendAndReceive function?

  1. Here is the flow I have, I using mule flow take the request from the POS, process the request, which need to call IBM MQ (which sit on AS400), to get the response back from MQ, and send back to POS. (In this example, I need to submit my request to INQ1 and get the response from INQR1 ). Based on the answer below, it seems like the sendAndReceive function is treat as Requester , I need another flow to call the Responder to handle the response, so receivedMessage= (BytesMessage)consumer.receive(); will not getting stuck? Correct me if I am wrong

Can you use different topic to differentiate?

That's a bad idea when you are doing point-to-point messaging.

destination = context.createQueue("queue:///" + responseQueue + "?targetClient=1");

It sounds like your responseQueue is shared between multiple consumers. You have 2 options:

  1. Create your own temporary dynamic queue and set it as the "Reply-To" queue

ie

Queue replyQ = session.createTemporaryQueue();
  1. Use MsgId / CorrelId request-reply messaging pattern.

ie Follow the suggestions on this page: Not able to get response from IBM MQ using JMS application

It looks like all responses are being sent to INQR1. To help your app identify which of the responses are for it and which it can ignore, you can make use of a selector, and normally the selector is by correlation id, though you could use other fields.

Essentially you are using a request / response pattern for which there are JMS samples - https://github.com/ibm-messaging/mq-dev-patterns/tree/master/JMS

Your requester would have logic like:

String correlationID = String.format("%24.24s", UUID.randomUUID().toString());
message.setJMSCorrelationIDAsBytes(b);

to generate a correlation id, and add it to the message.

Your requester would then create a correlation id based selector to filter the response queue:

try {
      b = correlationID.getBytes();
      selector = "JMSCorrelationID='ID:" + getHexString(b) + "'";
    } catch (Exception e) {
       ...
    }

which you use to construct your message consumer:

JMSConsumer consumer = context.createConsumer(requestQueue, selector);
Message receivedMessage = consumer.receive();

When your responder receives the initial request, it can get hold of the correlation id:

String correlationID = receivedMessage.getJMSCorrelationID();

and use it to set the correlation id for the response:

message.setJMSCorrelationID(correlationID);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM