javajmsapache-cameladvanced-queuing

Consuming message in the correct order from an Advanced Queue by Camel and JMS


I have a problem by using Apache Camel in combination with Oracle Advanced Queues and JMS.

It's about an application to distribute messages. Messages are received and enqueued in Oracle Advanced Queues with the help of Camel. Then they are consumed with Camel and forwarded to the target system. For the case that the message delivery fails, there is an retry count defined in the Advanced Queue, so that the message delivery is repeated.

If Camel now dequeue a message and sends it to a target system that is not available, either a HttpOperationFailedException or NoSuchEndpointException is thrown. These are caught and there is a rollback performed.

At this point, the expectation is that the message delivery will be retried as often as defined in the Retry Count and then moved to an exception queue. However, what is happening is that the next message in the queue is send.

Because the contents of the messages are partially dependent on each other, they must be processed sequentially.

I think that there is an misconfiguration in the usage of the JMS Library, but I'm not sure and have found nothing I could influence this behavior.

The used JMS library is Oracle AqApi v 11.2.0.3.

Here is the code for the Camel route:

from("jms-camel-component:myComponent.AQ?jmsMessageType=Text").routeId("deliveryToTarget")
        .transacted()                
        .setExchangePattern(ExchangePattern.InOut)                        
        .setHeader(Exchange.HTTP_QUERY, constant("throwExceptionOnFailure=false"))
        .setHeader(Exchange.CONTENT_TYPE, constant("application/xml; charset=UTF-8"))
        .doTry()
            .recipientList(header("endpointTarget"))
            .endDoTry()
            .process(ResponseProzessor.getInstance())
            .log("Message was delivererd.")
        .doCatch(HttpOperationFailedException.class, NoSuchEndpointException.class)    
            .process(ResponseProzessor.getInstance())
            .log("Error occured.")
            .rollback()
        .end();

Here is the JmsComponent configuration:

JmsComponent jmsComponent = new JmsComponent(scc);
jmsComponent.setConnectionFactory(connectionFactory);
jmsComponent.setTransactionManager(tm);
jmsComponent.setMaxConcurrentConsumers(1);            
jmsComponent.setMaxMessagesPerTask(1);                  
jmsComponent.setIncludeSentJMSMessageID(true);

Thank you in advance for your help!

UPDATE

I think, I've found the reason for the described behavior. There is a delay configured on the Advanced Queue. As long as the delay lasts, the next message from the queue is dequeued. The messages are not dequeued randomly, they are dequeued according to the priorities.

I really think this is something that has to be configured on the consumer. Is there any trick to configure the camel-jms-component to consume the first message from queue as long as it's not commited or moved to the exception queue? I didn't find an option to configure it directly on camel...


Solution

  • I'm not a Oracle AQ expert, but as far as I can see this is a setting on the queue, not on the client side.

    The sort_list parameter determines the order in which messages are dequeued. You cannot change the message sort order after you have created the queue table

    from: http://docs.oracle.com/cd/B19306_01/server.102/b14257/aq_admin.htm

    You most likely have ENQ_TIME or COMMIT_TIME set - which might already satisfy your needs.

    And, of course, your consumer must be the only one.