javaspring-bootspring-jmsoracle19coracle-aq

Oracle AQ - Multiple JMS Listeners to dequeue a specific custom 'message type'- is this possible?


I have an Oracle 19 Database in which I planned to leverage Oracle AQ for its queueing capabilities.

During a flow, a message will be created. Messages can be either of "type A" or "type B".

I had planned to have a separate application (Java) with a connection to the shared DB with JMS Listeners. The intention was for the JMS Listener to use a selector to only dequeue a message of type 'A' and another JMS Listener to dequeue type 'B'.

Each listener would then transform the message and make a HTTP request to a 3rd party system (different systems for A/B with different API specifications).

All messages must remain in sequence within a specific message type, so this is a single JMS listener per type.

Is it possible to enqueue multiple message types to a single queue, using an attribute to put them in to 'types'?

I have tried using a message selector on the JMS listener and having no luck so far.

I have explored the following two possibilities when enqueuing the message:

message_payload.set_string_property('type', 'A')

or using the custom user_property of message_properties_t with no luck.

Any advice appreciated. Thanks


Solution

  • If I understood you correct, you are on the right way to implement it, so by enqueuing you can set some custom property to the message, and by dequeueing you can use selector. Here is an example:

        import org.springframework.jms.core.JmsTemplate;
        import org.springframework.stereotype.Component;
        
        @Component
        public class MessageProducer {
        
            private final JmsTemplate jmsTemplate;
        
            public MessageProducer(JmsTemplate jmsTemplate) {
                this.jmsTemplate = jmsTemplate;
            }
        
            public void sendMessage(String type, SomeDto someDto) {
                jmsTemplate.convertAndSend(
                        "test_queue",
                        someDto,
                        message -> {
                            message.setStringProperty("my_message_type", type); // typeA, typeB
                            // message.setJMSCorrelationID(type);
                            return message;
                        }
                );
            }
        }
    

    Also as you can see in the code sample above, you could also use correlation id instead of setting my_message_type custom property. (then you will see your type value in queue table in column CORRID)

    And JmsListeners will look as follows:

    import jakarta.jms.Message;
    import lombok.extern.log4j.Log4j2;
    import org.springframework.jms.annotation.JmsListener;
    import org.springframework.stereotype.Component;
    
    @Component
    @Log4j2
    public class MessageConsumer {
    
        @JmsListener(
                destination = "test_queue",
                selector = "my_message_type = 'typeA'"
                // if correlationId is used:
                // selector = "JMSCorrelationID = 'typeA'"
        )
        public void listenTypeA(Message message) {
           log.info("Message with typeA" + message);
           // further processing
        }
    
        @JmsListener(
            destination = "test_queue",
            selector = "my_message_type = 'typeB'"
            // if correlationId is used:
            // selector = "JMSCorrelationID = 'typeB'"
        )
        public void listenTypeB(Message message) {
           log.info("Message with typeB" + message);
           // further processing
        }
    }