0

I am using Spring JMS and have a @JmsListener annotated method that handles incoming messages and also responds to them.

The issue is that I need to set the delivery mode to NON_PERSISTENT and the default of the used IBM MQ library is PERSISTENT which could only be changed when calling the (internal) send method.

In a different question here on stackoverflow it was mentioned that it is possible to set the delivery mode of a JmsTemplate, but unfortunately the template is not used for @JmsListener annotated method.

After debugging I found the MessagingMessageListenerAdapter that has a postProcessProducer method I can overwrite to manually change the settings of the created MessageProducer. Unfortunately it is quite complicated to extend this class and let spring use it. I got it working, but I doubt this is the best solution and having this in place this will set the delivery mode for all my @JmsListener methods to NON_PERSISTENT (not yet an issue for me, but maybe in the future):

// bean definition in my @Configuration class:

@Bean(name = JmsListenerConfigUtils.JMS_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public JmsListenerAnnotationBeanPostProcessor jmsListenerAnnotationProcessor() {
    return new JmsListenerAnnotationBeanPostProcessor() {
        @Override
        protected MethodJmsListenerEndpoint createMethodJmsListenerEndpoint() {
            return new MethodJmsListenerEndpoint() {

                @Override
                protected MessagingMessageListenerAdapter createMessageListenerInstance() {
                    return new MessagingMessageListenerAdapter() {

                        @Override
                        protected void postProcessProducer(MessageProducer producer, Message response)
                            throws JMSException {
                            super.postProcessProducer(producer, response);

                            producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
                        }

                    };
                }

            };
        }
    };
}

Is there an easier way to set the delivery mode when I am using @JmsListener? I found a lot of classes where I can set the delivery mode, but I haven't found any way to do this on one of the beans I had to define to get my JMS setup running (like the JmsListenerContainerFactory or ConnectionFactory).

EDIT: Unfortunately we are using Spring 4.x and can't update to 5.x

chris922
  • 346
  • 3
  • 9

1 Answers1

1

With Spring 5 (currently 5.0.6), you can now set a QosSettings object in the container factory's responseQosSettings property docs here; scroll down a bit.

Finally if you need to specify some QoS values for the response such as the priority or the time to live, you can configure the JmsListenerContainerFactory accordingly:

public class QosSettings {

    private int deliveryMode;

    private int priority;

    private long timeToLive;

    ...

}
Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Looks nice, but unfortunately we are using Spring 4.x and can't update to 5.x (I missed to mention this). Is there any Spring 4 compatible solution? – chris922 May 25 '18 at 20:28
  • If you can access the queue using a URI format then look at this answer I provided on another SO post: https://stackoverflow.com/questions/50333116/is-there-a-way-to-change-the-delivery-mode-in-publishjms-processor-in-nifi/50333873#50333873 – JoshMc May 25 '18 at 21:12
  • Thanks @JoshMc, good try, but unfortunately it is not working with my use-case. We are using a `CachedMessageProducer` which always calls `send` with the default `persistence` value which is still `2` and thus not the one from the URI. – chris922 Jun 01 '18 at 08:03