JBoss JMS MessageConsumer无限期地等待响应消息



我正在尝试在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();

最新更新