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?
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:
ie
Queue replyQ = session.createTemporaryQueue();
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.