views:

630

answers:

2

Hi,

if I use the DefaultMessageListenerContainer of Spring to recieve JMS messages, I don't get JMS messages redelivered, even if I set sessionAcknowledgeMode to 2.

In case of a RuntimeException within the onMessage() of my JavaBean, the message is not acknowledged within the JMS provider (ActiveMQ), it stays as pending in the queue. But it is never redelivered, which I think is caused by the fact that Spring never calls session.recover(), which according to ActiveMQ's documentation is required to is required for redelivery to happen.

Can anybode give me a hint how I can configure DefaultMessageListenerContainer to call session.recover() in case of RuntimeExceptions?

Best regards,
Martin

A: 

You indicate that you're using sessionAcknowledgeMode 2 which is Session.CLIENT_ACKNOWLEDGE. The following statement is taken directly from the AbstractMessageListenerContainer Javadocs:

  • "CLIENT_ACKNOWLEDGE": Automatic message acknowledgment after successful listener execution; no redelivery in case of exception thrown.

So the problem is not with the Spring DMLC and it's ability to call Session.recover() when a runtime exception is thrown. Is it possible for you to use a try/catch in your listener's onMessage() method to handle runtime exceptions by calling Session.recover() yourself?

Bruce

bsnyder
Thanks, I am aware of this possible solution (sorry, didn't write that), but it adds boiler-plate code to every bean I use, and forces me to use `SessionAwareMessageListener` (which is a Spring dependency) instead of a `javax.jms.MessageListener`. And to be honest, I'd prefer not to directly introduce a Spring dependency into my message processors.
Martin C.
A: 

You make a good point about the boilerplate code. It gets sprinkled in many places and begs to be refactored. Is it not possible for you to abstract such code? This is a common solution. Creating an abstract parent class with a method that contains the try/catch with the appropriate processing should do the trick. Then just extend the parent class to implement as many custom processors as necessary. You can even then wire together the processors in an appropriate manner using your Spring app context.

I've never had a problem adding Spring-specific code to an application because it runs anywhere. This was important for me way back when I began using the Spring. It's not specific to any single app server or servlet container so it's not like I'm coding myself into a corner with Spring the way I am if I import com.ibm or com.oracle into my source code. In fact, I've used the Spring JMS APIs with one MOM and switched to another MOM without changing anything other than the JMS connection factory definition.

Bruce

bsnyder