我正在尝试在JBoss上使用JMS创建一个同步请求
MDB的代码为:
@Resource(mappedName = "java:/ConnectionFactory")
private ConnectionFactory connectionFactory;
@Override
public void onMessage(Message message) {
logger.info("Received message for client call");
if (message instanceof ObjectMessage) {
Connection con = null;
try {
con = connectionFactory.createConnection();
con.start();
Requests requests = (Requests) ((ObjectMessage) message)
.getObject();
String response = getClient().get(getRequest(requests));
con = connectionFactory.createConnection();
Session ses = con.createSession(true, Session.AUTO_ACKNOWLEDGE);
MessageProducer producer = ses.createProducer(message
.getJMSReplyTo());
TextMessage replyMsg = ses.createTextMessage();
replyMsg.setJMSCorrelationID(message.getJMSCorrelationID());
replyMsg.setText(response);
logger.info("Sending reply to client call : " + response );
producer.send(replyMsg);
} catch (JMSException e) {
logger.severe(e.getMessage());
} finally {
if (con != null) {
try {
con.close();
} catch (Exception e2) {
logger.severe(e2.getMessage());
}
}
}
}
}
客户端代码为:
@Resource(mappedName = "java:/ConnectionFactory")
private QueueConnectionFactory queueConnectionFactory;
@Resource(mappedName = "java:/queue/request")
private Queue requestQueue;
@Override
public Responses getResponses(Requests requests) {
QueueConnection connection = null;
try {
connection = queueConnectionFactory.createQueueConnection();
connection.start();
QueueSession session = connection.createQueueSession(false,
Session.AUTO_ACKNOWLEDGE);
MessageProducer messageProducer = session
.createProducer(requestQueue);
ObjectMessage message = session.createObjectMessage();
message.setObject(requests);
TemporaryQueue temp = session.createTemporaryQueue();
MessageConsumer consumer = session.createConsumer(temp);
message.setJMSReplyTo(temp);
messageProducer.send(message);
Message response = consumer.receive();
if (response instanceof TextMessage) {
logger.info("Received response");
return new Responses(null, ((TextMessage) response).getText());
}
} catch (JMSException e) {
logger.severe(e.getMessage());
} finally {
if (connection != null) {
try {
connection.close();
} catch (Exception e2) {
logger.severe(e2.getMessage());
}
}
}
return null;
}
消息在队列中被正常接收,响应消息被创建,MessageProducer发送响应,没有任何问题,没有任何错误。然而,消费者只是坐在那里无限期地等待。我也试过创建一个单独的回复队列,而不是使用临时队列,结果是一样的。
我猜我在这个设置中缺少了一些基本的东西,但是我看不出我做错了什么。
没有其他代码,我读过的可能导致问题的两件事是connection.start()没有被调用或响应将发送到其他不同的接收器,这在这里没有发生(据我所知-在这些类之外的代码中还没有其他消息传递部分)
所以我想我的问题是,上面的代码应该工作还是我错过了JMS流的一些基本理解?
所以…我坚持了下来,成功了。
答案是,当我创建会话时,客户机和MDB中的事务属性必须设置为false:
Session ses = con.createSession(true, Session.AUTO_ACKNOWLEDGE);
必须改为:
Session ses = con.createSession(false, Session.AUTO_ACKNOWLEDGE);
我现在知道为什么了!我正在有效地做下面的事情,这是从Oracle JMS文档中获取的!
如果你尝试使用请求/应答机制,即你发送消息,然后在同一事务中尝试接收对发送消息的回复,程序将挂起,因为在事务提交之前发送不能发生。下面的代码片段说明了这个问题:
// Don’t do this!
outMsg.setJMSReplyTo(replyQueue);
producer.send(outQueue, outMsg);
consumer = session.createConsumer(replyQueue);
inMsg = consumer.receive();
session.commit();