Клиент Weblogic JMS - чтение из нескольких очередей за одну транзакцию - PullRequest
0 голосов
/ 27 августа 2018

У меня проблема при чтении сообщений из нескольких очередей JMS в одной транзакции с использованием клиента WebLogic JMS (wlthin3client.jar) из WebLogic 11g (WebLogic Server 10.3.6.0). Я пытаюсь прочитать сначала одно сообщение из очереди 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. Сообщение Q1 корректно фиксируется, если Q2 пусто и нечего с него читать.
  2. Проблема не возникает, когда я использую синхронный API похожим, вложенным способом для Q1 и Q2. Так что, если я использую q1Receiver.receiveNoWait() все в порядке.
  3. Если я использую асинхронный API похожим, вложенным способом для Q1 и Q2, то вызывается только прослушиватель сообщений Q1, а коммит работает в Q1. Но приемник сообщений Q2 вообще не вызывается, а Q2 не фиксируется (сообщение застряло в receive / delayed).

Я как-то неправильно использую API? Или это ошибка WLS JMS? Как совместить чтение из нескольких очередей с асинхронным API?

1 Ответ

0 голосов
/ 18 июня 2019

Оказывается, это WLS JMS ошибка 28637420 . Состояние ошибки говорит о том, что оно исправлено, но я бы не стал на это полагаться - патч WLS 11g с этим исправлением не работает (см. ошибка 29177370 ).

Oracle говорит, что это происходит из-за того, что два разных механизма доставки (синхронные сообщения и асинхронные сообщения) не были предназначены для совместной работы в одном сеансе.

Самый простой способ обойти эту проблему - просто использовать синхронный API (опрос) для случаев, когда вам нужно работать с несколькими очередями в одном сеансе. Я выбрал этот подход.

Другой вариант, предложенный oracle, заключается в использовании UserTransactions с двумя различными сеансами: один сеанс для асинхронного потребителя и другой сеанс для синхронного потребителя. Я не проверял это все же.

...