1

我正在尝试为用于将 JMS 消息发送到 ActiveMQ 的类编写测试。我想要完成的是在被测类中获取一个方法,将消息发送到本地主机中的 ActiveMQ 实例,然后在测试中选择消息并验证它是否正确。

我选择了这个作为我的代理 url: vm://localhost?broker.persistent=true,这意味着将创建一个本地 ActiveMQ 实例,并将消息存储在 KahaDB 中(它也是创建的。)(我尝试使用broker.persistent=false,但由于被测方法有一个finally-clause关闭连接,然后内存中的消息会在我检索它们之前丢失。)

为了检索消息并验证它,我有以下代码:

    //call method under test to send a message
    //create a ConnectionFactory with url vm://localhost?broker.persistent=true
    final Connection connection = connectionFactory.createConnection();
    connection.start();

    final Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
    final Destination dest = session.createQueue("my.queue");

    final MessageConsumer messageConsumer = session.createConsumer(dest);
    Message message = messageConsumer.receive(1000);

    messageConsumer.close();
    session.close();
    connection.close();

我的问题是,在运行此代码时,消息并未从 KahaDb 中删除!在多次测试运行后,第一次添加的消息将被反复阅读。我在这里遗漏了什么,或者这是 KahaDB/ActiveMQ 中的错误?我正在使用 ActiveMQ 5.7.0。

4

2 回答 2

2

您已经创建了一个事务会话,但从未调用过提交。在这种情况下,当调用 close 方法时,正在进行的事务将回滚,因此您收到的消息将放回队列中,并将重新传递给另一个消费者。您可以通过查询消息上的重新传递计数来测试这一点,并查看它每次都增加。session.commit()在关闭会话之前 使用消息调用。

于 2013-07-26T13:56:46.810 回答
2

尝试

final Session session = 
  connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

否则你会得到一个“交易”的会话。


否则,如果你真的想有一个“交易”的会话,你必须打电话

// 2nd parameter is ignored, if the session is transacted
final Session session = 
  connection.createSession(true, -1);

// Read messages

session.commit();
messageConsumer.close();
session.close();
connection.close();

为了删除您在此会话期间阅读的所有消息。


供您参考,Javaworld 提供了关于JMS 中的事务和重新交付的出色概述。它还涵盖了其他可能性(Session.CLIENT_ACKNOWLEDGE例如,用于单独确认消息)。

于 2013-07-26T14:00:14.143 回答