我复制了有关如何调用IBM MQ的Java客户端代码,并将请求传递到队列,但是有时我从队列中返回了错误的响应。
例如,如果我提交以下请求:
F LOYFI6331760101046481882
我希望从回复中我会得到
F LOYFA36331760101046481882
但实际上我得到了
F LOYFA36331760101051292448
您会看到卡号错误。
这是代码
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;
}
}
我还有另一个要同时运行的项目,以调用MQClient.sendAndReceive()
,host
,port
,QMGR
,channel
,requestQueue
和responseQueue
,只有payload
不同。
那我该如何修复上面的代码,以确保始终得到与请求相对应的正确响应?
编辑:
1.对于JoshMac问题,app是IBM MQ的意思吗?还是会调用我的sendAndReceive
函数的应用?
INQ1
提交请求,并从INQR1
获取响应)。根据以下答案,似乎sendAndReceive
函数被视为Requester
,我需要另一个流程来调用Responder
来处理响应,因此receivedMessage= (BytesMessage)consumer.receive();
不会卡住了吗?如果我错了请纠正我答案 0 :(得分:0)
您可以使用其他主题进行区分吗?
在进行点对点消息传递时,这是一个坏主意。
destination = context.createQueue("queue:///" + responseQueue + "?targetClient=1");
听起来您的responseQueue在多个使用者之间共享。您有2个选择:
即
Queue replyQ = session.createTemporaryQueue();
即请遵循此页面上的建议:Not able to get response from IBM MQ using JMS application
答案 1 :(得分:0)
似乎所有响应都已发送到INQR1。为了帮助您的应用识别出哪些响应以及哪些响应可以忽略,可以使用选择器,并且通常可以使用相关性ID作为选择器,尽管您可以使用其他字段。
本质上,您使用的是具有JMS示例的请求/响应模式-https://github.com/ibm-messaging/mq-dev-patterns/tree/master/JMS
您的请求者将具有以下逻辑:
String correlationID = String.format("%24.24s", UUID.randomUUID().toString());
message.setJMSCorrelationIDAsBytes(b);
生成相关性ID,并将其添加到消息中。
您的请求者然后将创建一个基于相关ID的选择器来过滤响应队列:
try {
b = correlationID.getBytes();
selector = "JMSCorrelationID='ID:" + getHexString(b) + "'";
} catch (Exception e) {
...
}
您用来构造消息使用者的
JMSConsumer consumer = context.createConsumer(requestQueue, selector);
Message receivedMessage = consumer.receive();
当您的响应者收到初始请求时,它可以保留相关ID:
String correlationID = receivedMessage.getJMSCorrelationID();
并使用它来设置响应的相关ID:
message.setJMSCorrelationID(correlationID);