【问题标题】:Weblogic JMS client - reading from multiple queues in single transactionWeblogic JMS 客户端 - 在单个事务中从多个队列中读取
【发布时间】:2018-08-27 15:15:07
【问题描述】:

使用来自 WebLogic 11g (WebLogic Server 10.3.6.0) 的 WebLogic JMS 客户端 (wlthin3client.jar) 在单个事务中读取来自多个 JMS 队列的消息时遇到问题。我正在尝试从队列 Q1 中读取第一条消息,然后,如果此消息满足某些要求,则从队列 Q2 中读取其他消息(如果当时可用)。

我希望在提交事务后,两条消息都应该从 Q1 和 Q2 消失。在回滚的情况下 - 消息应保留在 Q1 和 Q2 中。

我的第一种方法是使用异步队列接收器从 Q1 读取,然后在需要时从 Q2 同步读取:

void run() throws JMSException, NamingException {
    QueueConnectionFactory cf = (QueueConnectionFactory) ctx.lookup(connectionFactory);

    // create connection and session
    conn = cf.createQueueConnection();
    session = conn.createQueueSession(true, Session.SESSION_TRANSACTED);
    Queue q1 = (Queue) ctx.lookup(queue1);

    // setup async receiver for Q1
    QueueReceiver q1Receiver = session.createReceiver(q1 );
    q1Receiver.setMessageListener(this);

    conn.start();

    // ...
    // after messages are processed
    conn.close();
}

@Override
public void onMessage(Message q1msg) {
    try {
        QueueReceiver q2receiver = session.createReceiver(queue2);
        if(shouldReadFromQ2(q1msg)){      
           // synchronous receive from Q2
           Message q2msg = q2receiver.receiveNoWait();
           process(q2msg);
        }
        session.commit();
    } catch (JMSException e) {
        e.printStackTrace();
    } finally {
        q2receiver.close();
    }
}

不幸的是,即使我发出session.commit(),来自 Q1 的消息仍未提交。在连接或接收器关闭之前,它处于receive 状态。然后它似乎在获得delayed 状态时被回滚。

其他观察:

  1. 如果 Q2 为空且没有可读取的内容,则正确提交 Q1 消息。
  2. 当我以类似的嵌套方式为 Q1 和 Q2 使用同步 API 时,不会出现此问题。所以如果我使用q1Receiver.receiveNoWait() 一切都很好。
  3. 如果我以类似的嵌套方式对 Q1 和 Q2 使用异步 API,则仅调用 Q1 消息侦听器并且提交在 Q1 上工作。但是 Q2 消息监听器根本没有被调用并且 Q2 没有被提交(消息卡在receive / delayed)。

我是否以某种方式滥用了 API?或者这是一个 WLS JMS 错误?如何将多个队列的读取与异步 API 结合起来?

【问题讨论】:

    标签: java jms weblogic weblogic11g


    【解决方案1】:

    原来这是一个 WLS JMS bug 28637420。 错误状态表明它已修复,但我不会依赖此 - 带有此修复的 WLS 11g 补丁不起作用(请参阅bug 29177370)。

    Oracle 表示,之所以会出现这种情况,是因为两种不同的传递机制(同步消息与异步消息)并非旨在在同一个会话上协同工作。

    解决该问题的最简单方法是在需要在单个会话中处理多个队列的情况下使用同步 API(轮询)。我决定采用这种方法。

    oracle 建议的另一个选项是将 UserTransactions 与两个不同的会话一起使用,一个会话用于异步消费者,另一个会话用于同步消费者。不过我没有测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-06-03
      • 2014-08-03
      • 2018-11-20
      • 2013-10-18
      • 2013-06-21
      • 2013-12-31
      • 2011-10-05
      • 2015-04-02
      相关资源
      最近更新 更多