Weblogic JMS客户端-在单个事务中从多个队列读取

时间:2018-08-27 15:15:07

标签: java jms weblogic weblogic11g

使用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从多个队列读取?

1 个答案:

答案 0 :(得分:1)

事实证明,这是WLS JMS bug 28637420。 该错误状态表示已修复,但我不会依靠它-具有此修复程序的WLS 11g补丁不起作用(请参阅bug 29177370)。

Oracle表示,发生这种情况是因为两种不同的传递机制(同步消息与异步消息)并未设计为在同一会话上协同工作。

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

oracle建议的另一种选择是对两个不同的会话使用UserTransactions,一个会话用于异步使用者,另一个会话用于同步使用者。我没测试过。