viernes, 7 de marzo de 2014

Using JMS message selectors in a message consumer using an Oracle AQ (exception) queue

I was testing JMS selectors in a Message Consumer based on an Oracle AQ (exception) queue; I needed to dequeue only the messages with certain message ID's; at first, I tried with this syntax, but found an unexpected behavior:

"JMSMessageID='ID:XXX' OR JMSMessageID='ID:YYY'"

For example, let's say we have this messages in the queue (this specific messages are in the queue's default exception queue):


If I use the following selector,

String selector = 
  "JMSMessageID='ID:4A3966F3C0604B6DAED6D6E7FC62705A' OR 
   JMSMessageID='ID:01AF9624372C4D8A88CFAFD37D4395E7' OR
   JMSMessageID='ID:42C32FA9BBCB48ABA074EB69C94D1A82' OR
   JMSMessageID='ID:4973147F8AC54BD1A5DA2CE81F9622CD'";

the first receive() works OK, returning one of the matching messages (consistently, the first in the selector):

[TestServlet][doGet]selector=JMSMessageID='ID:4A3966F3C0604B6DAED6D6E7FC62705A' OR JMSMessageID='ID:01AF9624372C4D8A88CFAFD37D4395E7' OR JMSMessageID='ID:42C32FA9BBCB48ABA074EB69C94D1A82' OR JMSMessageID='ID:4973147F8AC54BD1A5DA2CE81F9622CD
[TestServlet][doGet]messageID=ID:4A3966F3C0604B6DAED6D6E7FC62705A

But, from the second, and so on, the receive() method behaves as if there aren't messages matching the selector. In the end, just one message got processed:


I enabled the jdbc and jms debug on the managed server (I'm working on Weblogic 12c), and found this, starting from the second receive(): "java.sql.SQLException: ORA-25263: no message in queue PRUEBAS.AQ$_MYQUEUETABLE_E with message ID 4A3966F3C0604B6DAED6D6E7FC62705A".

[[oracle.jdbc.driver.T4CXAConnection@29cccbf, owner=[weblogic.jdbc.wrapper.JTAConnection_weblogic_jdbc_wrapper_XAConnection_oracle_jdbc_driver_LogicalConnection-myQueuePruebas_DS-17, oracle.jdbc.driver.LogicalConnection@29d1486], rmConn=oracle.jdbc.driver.LogicalConnection@29d1486]] dequeue(unknown) throws: java.sql.SQLException: ORA-25263: no message in queue PRUEBAS.AQ$_MYQUEUETABLE_E with message ID 4A3966F3C0604B6DAED6D6E7FC62705A
        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445)
        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:389)
        at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:382)
        at oracle.jdbc.driver.T4Caqdq.processError(T4Caqdq.java:488)
        at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450)
        at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192)
        at oracle.jdbc.driver.T4Caqdq.doOAQDQ(T4Caqdq.java:180)
        at oracle.jdbc.driver.T4CConnection.doDequeue(T4CConnection.java:3976)
        at oracle.jdbc.driver.PhysicalConnection.dequeue(PhysicalConnection.java:10106)
        at oracle.jdbc.driver.PhysicalConnection.dequeue(PhysicalConnection.java:10153)
        at oracle.jdbc.OracleConnectionWrapper.dequeue(OracleConnectionWrapper.java:1525)
        at weblogic.jdbc.wrapper.XAConnection_oracle_jdbc_driver_LogicalConnection.dequeue(Unknown Source)
        at weblogic.jdbc.wrapper.JTAConnection_weblogic_jdbc_wrapper_XAConnection_oracle_jdbc_driver_LogicalConnection.dequeue(Unknown Source)
        at oracle.jms.AQjmsConsumer.jdbcConnectionDequeueCheck25242(AQjmsConsumer.java:1713)
        at oracle.jms.AQjmsConsumer.jdbcDequeue(AQjmsConsumer.java:1295)
        at oracle.jms.AQjmsConsumer.receiveFromAQ(AQjmsConsumer.java:1035)
        at oracle.jms.AQjmsConsumer.receiveFromAQ(AQjmsConsumer.java:960)
        at oracle.jms.AQjmsConsumer.receiveFromAQ(AQjmsConsumer.java:938)
        at oracle.jms.AQjmsConsumer.receive(AQjmsConsumer.java:790)
        at test.PruebaConsumerSelectorServlet.doGet(PruebaConsumerSelectorServlet.java:55)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:731)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:844)
        at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:242)
        at weblogic.servlet.internal.StubSecurityHelper$ServletServiceAction.run(StubSecurityHelper.java:216)
        at weblogic.servlet.internal.StubSecurityHelper.invokeServlet(StubSecurityHelper.java:132)
        at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:338)
        at weblogic.servlet.internal.ServletStubImpl.execute(ServletStubImpl.java:221)
        at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.wrapRun(WebAppServletContext.java:3284)
        at weblogic.servlet.internal.WebAppServletContext$ServletInvocationAction.run(WebAppServletContext.java:3254)
        at weblogic.security.acl.internal.AuthenticatedSubject.doAs(AuthenticatedSubject.java:321)
        at weblogic.security.service.SecurityManager.runAs(SecurityManager.java:120)
        at weblogic.servlet.provider.WlsSubjectHandle.run(WlsSubjectHandle.java:57)
        at weblogic.servlet.internal.WebAppServletContext.doSecuredExecute(WebAppServletContext.java:2163)
        at weblogic.servlet.internal.WebAppServletContext.securedExecute(WebAppServletContext.java:2089)
        at weblogic.servlet.internal.WebAppServletContext.execute(WebAppServletContext.java:2074)
        at weblogic.servlet.internal.ServletRequestImpl.run(ServletRequestImpl.java:1513)
        at weblogic.servlet.provider.ContainerSupportProviderImpl$WlsRequestExecutor.run(ContainerSupportProviderImpl.java:254)
        at weblogic.work.ExecuteThread.execute(ExecuteThread.java:256)
        at weblogic.work.ExecuteThread.run(ExecuteThread.java:221)

Am I doing somethig wrong? is this a bug? my test code is pretty straighfoward; something like this:

String selector = 
  "JMSMessageID='ID:4A3966F3C0604B6DAED6D6E7FC62705A' OR 
   JMSMessageID='ID:01AF9624372C4D8A88CFAFD37D4395E7' OR
   JMSMessageID='ID:42C32FA9BBCB48ABA074EB69C94D1A82' OR
   JMSMessageID='ID:4973147F8AC54BD1A5DA2CE81F9622CD'";
messageConsumer = session.createConsumer(queue, selector);
Message msg = null;
System.out.println("[TestServlet][doGet]selector=" + messageConsumer.getMessageSelector());
while((msg = messageConsumer.receive(10000)) != null) {          
if(msg != null) {
System.out.println("[TestServlet][doGet]messageID=" + msg.getJMSMessageID());
}
}

Fortunately, trying with other selector syntax, the test worked OK. The syntax is:

"JMSMessageID IN ('ID:XXX', 'ID:YYY')"

For example, having this messages in the queue


And this selector

String selector = 
  "JMSMessageID IN (
    'ID:ED976B4A41F241F594F570A8F2250D26'
'ID:724794DE2C4648AF9EF7EB1CE3B0BC22'
'ID:33CF68A695E04F6B89F1024F7DFE5925'
'ID:3E7059E3489C472096C58A833434893C')"

The test works as expected:

[TestServlet][doGet]messageID=ID:724794DE2C4648AF9EF7EB1CE3B0BC22
[TestServlet][doGet]messageID=ID:3E7059E3489C472096C58A833434893C
[TestServlet][doGet]messageID=ID:33CF68A695E04F6B89F1024F7DFE5925
[TestServlet][doGet]messageID=ID:ED976B4A41F241F594F570A8F2250D26

The final result in the table is:


I found some (un)related cases in My Oracle Support.
I found also an Hermes bug report discusing the same case:

No hay comentarios: