Rollback Exception Strategy Documentation
Rollback Exception Strategy For Unhandled exceptions
Rollback exception strategy should be used when is not possible to perform corrective actions due to a failure during a message processing. In case the flow exchange pattern is one-way then it will allow the inbound endpoint transport to execute any corrective action. For request-response flows you can change the payload returned to the customer.
Rollback Exception Strategy vs Default Exception Strategy
Since mule 3.3 default exception strategy can be replaced by Rollback Exception Strategy. The main difference is the composition of the message being routed inside the exception strategy and the resulting message after the exception strategy execution.
With default exception strategy you will get:
- Exception information in the payload
- Null in exceptionPayload attribute
- NullPayload as payload - FIXED you can't modify it
- Exception information in exceptionPayload attribute - FIXED you can't modify it
With rollback exception strategy:
- Payload will continue being the same at the time of the exception
- Exception information in exceptionPayload attribute
- The result of the processing of the message during the exception strategy execution
- Exception information in the exceptionPayload.
The message routed in rollback exception strategy is mucho more convenient for error handling compared to default exception strategy. With rollback exception strategy you can easily send the message to a dead letter queue or notify somebody about the failure. Also, now it's possible to change the result of the flow execution in case an error.
Rollback Exception Strategy For Message Redelivery
Rollback exception strategy allows to prevent mule from consuming inbound message so it can be processed again in case of an exception. There are mainly two types of transport that are suitable to have a rollback-exception-strategy if used:
- Transactional transports: VM, JMS and JDBC. Consuming messages within a transaction and doing rollback if an exception is thrown allows to reprocess the inbound message
- Reliable transports: JMS, FTP, FILE and IMAP. These transports allows avoiding inbound message consumption in case of an exception
- JMS inbound endpoint, if an exception is thrown, will recover the session used to consume inbound message
- FTP and FIL inbound endpoints, if an exception is thrown, will not remove source file
- IMAP endpoint, if an exception is thrown, will not remove read messages
Reliable transports to avoid consuming inbound message must be aware of the exception thrown by the flow. So it's required that flow processing strategy be synchronous.
Example 1: message is consumed from orderEndpoint JMS queue, if ProcessOrder throws an exception rollback-exception-strategy will cause JMS inbound endpoint to recover session thus restoring message in orderEndpoint queue so it can be processed again
Message redelivery handling
If message processing keeps failing over and over again then message processing is in an infinite loop.
To break infinite loop a maximum redelivery times must be configured. If this maximum redelivery threshold is exceeded then message will be consumed. Max redelivery threshold can be configured using maxRedeliveryAttempts attribute.
Example 2: message is consumed from orderEndpoint JMS queue, if ProcessOrder throws an exception rollback-exception-strategy will cause JMS inbound endpoint to recover session thus restoring message in orderEndpoint queue so it can be processed again. If message is redelivered more than 3 times then message processing will fail as soon as it reaches inbound endpoint and rollback-exception-strategy will cause message consumption
Poison messages handling
A message that has exceeded the maximum number of delivery attempts to the application it's called poison message. Inside rollback-exception-strategy a on-redelivery-attempts-exceeded element can be configured and inside a set of message processors to handle poison messages. Usually poison messages can be sent to a dead letter queue to avoid lossing the message or to analyze it later.
Example 3: In case inbound message was redelivered more than 3 times it will be sent to a JMS dead letter queue names dlq joining the transaction in which the message was received and then rollback-exception-strategy will commit the transaction.
Example 4: In case inbound message was redelivered more than 2 times the current date is append at the end of the payload content and it's written to an error file on disk.
Support for message redelivery recognition is accomplish by using a Redelivery Policy. Default redelivery policy generates a unique id for each message and uses it as a key to hold a reference to a counter with the number of times a message has been redelivered. Default message id is generated by creating a digest of the payload content. This way of generating message id can't perform good for big payloads or, for instance, if streaming is used. For those cases, an idempotent-redelivery-policy can be configured in the inbound endpoint in order to customize it and improve performance. idempotent-redelivery-policy customization supports configuration of the digest algorithm or use an mule expression instead to generate the id. For instance, using a file transport an id can be create using the expression #OUTBOUND:originalFilename.
Example 5: In the inbound endpoint redelivery policy has been redefined to use the file name as the key for the counter.
Redelivery policy and JMS Redelivery handler
JMS built-in redelivery checking can perform better than the underlaying mechanism used by mule for every transport so support for it is still provided. Configuring maxRedelivery attribute in JMS connector and a rollback-exception-strategy without maxRedeliveryAttempts will provide same functionality as in the previous example
Example 6: In case inbound message is redelivered more than 3 times then JMS message will be sent to a dead letter queue named dlq and transaction will be commit.
In case that you want to use default redelivery policy instead of JMS redelivery handler you must configure jms connector with maxRedelivery attribute equals -1
Rollback Exception Strategy detailed behavior
Advance users can take advantage knowing deeply what happens behind the scenes. So here is a detailed explanation.
Redelivery Policy: When a flow is configured to use rollback-exception-strategy with maxRedeliveryAttempts attribute a redelivery policy is created for each inbound endpoint. This redelivery policy will keep track of message failures. In case that a message is exceeding configured redelivery attempts then instead continue message processing it fails fast throwing a org.mule.api.exception.MessageRedeliveredException.
Message processing failure: Once rollback-exception-strategy receives an exception, if it's not a org.mule.api.exception.MessageRedeliveredException then regular exception handling must be done:
- If a transaction is available, rollback transaction
- Route message through configured rollback-exception-strategy child message processors and, if exchange pattern is request-response, return to the caller the result message
- Do not process any reply to property
- Propagate exception to inbound endpoint
Redelivery attempts exceeded: In case the exception type is org.mule.api.exception.MessageRedeliveredException rollback-exception-strategy notice that redelivery attempts are exceeded and will consume inbound message:
- Child message processors of on-redelivery-attempts-exceeded element will be executed, if exchange pattern is request-response, return to the caller the result message.
- Process reply to property
- Commit any available transaction
- Do not propagates exception to inbound endpoint so message is consumed