In case of every project, the fact about the exceptions is that they are bound to happen. That is why it is important to catch, categorize and handle exceptions so that the system/application is not left in an inconsistent state. There is a default exception strategy which is implicitly applied to all Mule applications. Rollback any pending transaction automatically is the default exception strategy.
Before diving deep into exceptional handling, we should understand what kind of exceptions can occur along with three basic questions that a developer must have while designing exception handlers.
This question has ample relevance before designing exception handlers because all transports do not support transnationality.
File or HTTP does not support transactions. That is why, if an exception occurs in these cases, we must manage it manually.
Databases support transactions. While designing exception handlers in this case, we must keep in mind that database transactions can automatically rollback (if required).
In case of REST APIs, we should keep in mind that they should return the correct HTTP status codes. For example, 404 for a resource not found.
While designing exception handlers, we must take care about Message exchange pattern. There can be synchronous (request-reply) or asynchronous (fire-forget) message pattern.
Synchronous message pattern is based on request-reply format which means this pattern will expect a response and will be blocked until a response is returned or time out happens.
Asynchronous message pattern is based on fire-forget format which means this pattern assumes that the requests will ultimately be processed.
Very simple rule is that you will handle the exception based on its type. It is very important to know whether the exception is caused by a system/technical issue or a business issue?
An exception occurred by system/technical issue (such as network outage) should be automatically handled by a retry mechanism.
On the other hand, an exception occurred by a business issue (such as invalid data) should not be solved by applying retry mechanism because it is not useful to retry without fixing the underlying cause.
As we know that all the exceptions are not same, it is very important to categorize the exceptions. At high level, the exceptions can be classified into the following two types −
The main reasons for the occurrence of business exceptions are incorrect data or incorrect process flow. These kind of exceptions are typically non-retriable in nature and hence it is not good to configure a rollback. Even applying retry mechanism would not make any sense because it is not useful to retry without fixing the underlying cause. In order to handle such exceptions, the processing should stop immediately, and the exception sent back as a response to a dead letter queue. A notification should also send to the operations.
The main reasons for the occurrence of non-business exceptions are system issue or technical issue. These kinds of exceptions are retriable in nature and hence it’s good to configure a retry mechanism in order to solve these exceptions.
Mule has the following five exception handling strategies −
Mule implicitly applies this strategy to the Mule flows. It can handle all the exceptions in our flow, but it can also be overridden by adding a catch, Choice or Rollback exception strategy. This exception strategy will roll back any pending transactions and logs the exceptions too. An important characteristic of this exception strategy is that it will also log the exception if there is no transaction.
As being the default strategy, Mule implements this when any error occurs in the flow. We cannot configure in AnyPoint studio.
Suppose if there is no possible solution to correct the error then what to do? A solution is to use Rollback Exception Strategy which will roll back the transaction along with sending a message to the inbound connector of parent flow to reprocess the message. This strategy is also very useful when we want to reprocess a message.
This strategy can be applied to banking transaction where funds are getting deposited in a checking/savings account. We can configure a rollback exception strategy here because in case if an error occurs during the transaction, this strategy rolls the message back to the beginning to the flow to reattempt processing.
This strategy catches all the exceptions that are thrown within its parent flow. It overrides Mule’s default exception strategy by processing all the exceptions thrown by the parent flow. We can use a catch exception strategy to avoid propagating exceptions to inbound connectors and parent flows as well.
This strategy also ensures that a transaction processed by the flow is not rolled back when an exception occurs.
This strategy can be applied to flight booking system in which we have a flow for processing messages from a queue. A message enricher adds a property on the message for assignment of seat and then sends the message to another queue.
Now if any error occurs in this flow, then the message will throw an exception. Here, our catch exception strategy can add a header with an appropriate message and can push that message out of the flow to the next queue.
In case you want to handle the exception based on the message content, then choice exception strategy would be the best choice. The working of this exception strategy will be as follows −
There would be more than one exception strategy like Catch or Rollback, defined within choice exception strategy. In case there is no strategy defined under this exception strategy, then it will route the message to the default exception strategy. It never performs any commit or rollback or consume activities.
This refers to a common exception strategy that is defined in a separate configuration file. In case when a message throws an exception, this exception strategy will refer to the error handling parameters defined in a global catch, rollback or choice exception strategy. Like choice exception strategy, it never performs any commit or rollback or consume activities also.