Search code examples
javajmsweblogicweblogic11g

Weblogic JMS client - reading from multiple queues in single transaction


I have a problem when reading messages from multiple JMS Queues in a single transaction using WebLogic JMS client (wlthin3client.jar) from WebLogic 11g (WebLogic Server 10.3.6.0). I am trying to read first one message from queue Q1 and then, if this message satisfy some requirements, read other message (if available at that time) from queue Q2.

I expect that after committing the transaction both messages should disappear from Q1 and Q2. In case of rollback - messages should remain in both Q1 and Q2.

My first approach was to use an asynchronous queue receiver to read from Q1 and then synchronously read from Q2 when it is needed:

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();
    }
}

Unfortunately even though I issue a session.commit() the message from Q1 remains uncommitted. It is in receive state until the connection or receiver is closed. Then is seems to be rolled back as it gets delayed state.

Other observations:

  1. Q1 message is correctly committed if Q2 is empty and there is nothing to read from it.
  2. The problem does not occur when I am using synchronous API in similar, nested way for both Q1 and Q2. So if I use q1Receiver.receiveNoWait() everything is fine.
  3. If I use asynchronous API in similar, nested way for Q1 and Q2, then only Q1 message listener is called and commit works on Q1. But Q2 message listener is not called at all and Q2 is not committed (message stuck in receive / delayed).

Am I misusing the API somehow? Or is this a WLS JMS bug? How to combine reading from multiple queues with asynchronous API?


Solution

  • It turns out this is an WLS JMS bug 28637420. The bug status says it is fixed, but I wouldn't rely on this - a WLS 11g patch with this fix doesn't work (see bug 29177370).

    Oracle says that this happens because two different delivery mechanisms (synchronous messages vs asynchronous messages) were not designed to work together on the same session.

    Simplest way to work around the problem is just use synchronous API (polling) for cases when you need to work on multiple queues in a single session. I decided on this approach.

    Another option suggested by oracle is to to use UserTransactions with two different sessions, one session for the async consumer and another session for the synchronous consumer. I didn't test that though.