jakarta-ee - 即使在 activemq 中队列不为空时,JMS 实现中的 receiveNoWait 也返回 null

标签 jakarta-ee jms activemq

我正在尝试在我的项目中实现 JMS。我使用 active mq 作为提供程序,并使用持久队列。
以下是从事件 mq 中检索元素的代码

            conn = GlobalConfiguration.getJMSConnectionFactory().createConnection();
            conn.start();
            session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
            MessageConsumer consumer = session.createConsumer(queue);
            ObjectMessage obj = (ObjectMessage) consumer.receiveNoWait();

此代码有时会返回数据,有时会返回 null,即使我可以在事件的 mq 管理控制台中看到待处理消息的数量为非零。
我读了一堆文章,很少有人提到 JMS api 没有强制要求您每次都获取元素,您必须相应地编码。
由于在我的场景中,我依赖于队列,一旦队列返回空值,我就会终止进程,因此我按以下方式修改了代码

我没有调用receiveNoWait,而是在通过队列浏览器检查队列中是否存在元素后开始使用receive。以下是修改后的代码
public static <T> T retrieveObjectFromQueue(Queue queue, Class<T> clazz) {
synchronized (queue) {
    if(!queueHasMoreElements(queue))
        return null;
    Connection conn = null;
    Session session = null;
    try {
        conn = GlobalConfiguration.getJMSConnectionFactory().createConnection();
        conn.start();
        session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageConsumer consumer = session.createConsumer(queue);
        ObjectMessage obj = (ObjectMessage) consumer.receive();
        return clazz.cast(obj.getObject());
    } catch(Exception e) {
        throw new RuntimeException(e);
    }finally {
        closeSessionAndConnection(session, conn);
    }
}


public static boolean queueHasMoreElements(Queue queue) {
Connection conn = null;
Session session = null;
try {
    conn = GlobalConfiguration.getJMSConnectionFactory().createConnection();
    conn.start();
    session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
    QueueBrowser browser = session.createBrowser(queue);
    Enumeration enumeration = browser.getEnumeration();
    return enumeration.hasMoreElements();
} catch(Exception e) {
    throw new RuntimeException(e);
}finally {
    closeSessionAndConnection(session, conn);
}

现在我的代码在处理了大约 20-30 个元素后卡住了,而且我可以在管理控制台中看到待处理的元素。
当我尝试使用 Debug模式时,我意识到,在检索 20-30 个元素后,我的代码卡在 consumer.receive() 处,这是在队列为空的情况下预期的,但是当我检查我的管理控制台时,它显示了很多队列中的元素。

我使用 jdbc(mysql) 作为 activemq 的持久存储。我使用的配置 xml 在 activemq 配置示例 (activemq/examples/conf/activemq-jdbc-performance.xml) 中给出

我使用 tcp://localhost:61616?jms.prefetchPolicy.queuePrefetch=1 作为 activemq url。

请让我知道我做错了什么。我正在使用 java8 和 apache activeMq 5.13.1

谢谢

最佳答案

JMS 规范也没有强制要求 QueueBrowser 将返回队列中的所有消息,您可能只能根据很多因素在它启动时获得其中内容的快照。

您试图在 JMS 上强加它不能保证的语义。您可以尝试将预取设置为零,这将导致客户端轮询代理以获取消息并等待代理告知存在或不存在消息。如果轮询时消息尚未到达队列,您可能仍然什么也得不到,这只是您需要处理的事情。

您还可以使用定时接收方法并在返回和终止应用程序之前设置您愿意等待的超时时间。

关于jakarta-ee - 即使在 activemq 中队列不为空时,JMS 实现中的 receiveNoWait 也返回 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35422551/

相关文章:

java - onCompletion() 顺序在 Camel DSL 中是否重要?

activemq - "Enqueued"中的 "Dequeued"和 "DLQ"消息的含义是什么?

java - 我可以在 MDB 中获取源 JMS session 吗?

java - SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,了解在 '? AND password=?' 附近使用的正确语法

java - javax javaee-api 6.0 的 Maven 源代码

java - 通过管理控制台将消息发送到 JBoss 6 中的队列

java - 在 GWT 应用程序中捕获 ctrl-z(撤消)和 ctrl-y(重做)

jms - WS02 Websphere MQ 的 JMS 传输

java - MessageConsumer.receive() 不删除消息

ruby - 为什么 STOMP、ActiveMQ 和 Vagrant 不能在我的系统上运行?