Whilst working on a POC we noticed some very strange behaviour when working with JMS re-deliveries. We were sending a JMS message through a JMS inbound endpoint and purposely throwing an exception using the Test component. Everything worked fine the first time – an exception was thrown and Mule tried to redeliver the message a number of times before giving up. However, we noticed that the same message was not entering our flow when we attempted to send it again in subsequent tries. Our message was being dropped at the connector level.
Internally, the JMS transport uses an idempotent message filter to discard messages that have already been sent. Messages are filtered based on the payload, which in our case is the contents of the JMS message. Mule keeps a record of each message that is sent by applying a SHA256 hash on the payload and stores the hash in an object store.
This is not what we wanted. We wanted to filter out messages based on the JMS message IDs that the JMS broker sends as a header with the JMS message, not the message content. Our flow looked something like this:
This problem stems from the fact that Mule uses its own redelivery policy to redeliver the JMS message. When you define both a roll-back exception strategy with the “maxRedeliveryAttempts” attribute set and a JMS connector with the maxRedelivery attribute set, these two compete against each other. Both of these attributes expect an integer. Mule decides which redelivery policy to use depending on which value is smallest. Consider a scenario where maxRedeliveryAttempts is set to 3, and maxRedelivery on the JMS connector is set to 5. Mule will use its own redelivery policy in favor of the JMS transport redelivery policy since maxRedeliveryAttempts is smaller. In this case, the following exception is thrown when a message is not delivered successfully after a number of retries:
On the other hand, the following exception is thrown when the redelivery policy available in the JMS transport is used:
The expected behaviour is simple; when a JMS connector is defined, the JMS redelivery policy should override that of Mule. If you’re running into this sort of problem, there is a very simple workaround – change how Mule generates message IDs. You can do this by defining your JMS inbound endpoints as follows:
By default, Mule assigns a message ID by generating a SHA256 hash from the payload. The above will assign the JMSMessageID as the Mule message ID instead.
Thank you!!!! This is very helpfull
Article has no code snippets with it. This is the same for ALL Ricston articles. Please sort it out.
This is helpful and I’m experiencing an issue related to this. I have used the above inbound configuration and one without the idempotent bit, but mule never calls the code defined at the end of the rollback-exception-strategy when retry attempts have succeeded.
I am seeing retry attempts, however. I have played with setting the maxRetries on the connector to -1 as well as leaving that alone and setting various values on the rollback strategy to 0, something less than maxRetries, the same value, or something greater. In no case is the retry exhausted logic being called. I’m about to switch over to an until-successful scope, because I can’t get this to work as expected.
It seems the various forms of the “retry attempts exhausted” exceptions are not made available to the exception strategies defined. The message is moved to a DLQ, so I know these exceptions are being handled. I just don’t get a chance to do anything about it, like send an alert or log the event. Very frustrating, to say the least.
FYI, I have the rollback-exception-strategy tied to java.io.IOException and a catch-exception strategy for all others to end the flow. This is wrapped in a choice-exception-strategy.
Any tips are welcome!
Cheers,
Rich
If you are using Rollback exception strategy with on redelivery exhaust then you should not use idempotent redelivery policy. Use either one of them. If you don’t define idempotent redelivery policy on endpoint, then you should get control in on redelivery exhaust flow of exception strategy.