Reading Time: 14 minutes

Welcome to this series of “HowTos” covering exceptions in MuleSoft Anypoint Platform. We will be covering many topics specifically with exceptions and exception/error handling in Mule flows.

The exception handling is demonstrated using a simple use-case. The example Mule project is available in Anypoint Exchange.

Integration projects are complex, and exceptions are bound to happen. It is important that we have the ability to catch, categorize and handle exceptions so that we do not leave the system/application/data in an inconsistent state.

Mule applications have a default exception strategy which is implicitly applied to all Mule applications. The default behavior is to rollback any pending transactions (if any) automatically and to log the exception. This default exception strategy can be can be overridden by implementing a catch, rollback or choice exception strategy to the flow.

What kind of exception is it?

To implement successful exception handling we have to understand what kind of exceptions can occur and are some questions that we typically ask ourselves when designing exception handlers.

Questions Details
What is the transport being used? Knowing what transport is important because not all transports support transactionality. For example
  • File or HTTP transports do not support transactions, therefore if an exception occurs after you have written out a file or sent an HTTP request, you have to manually compensate.
  • Databases usually support transactions and can automatically rollback if required.
  • REST APIs should return the correct HTTP status codes. i.e. 404 for a resource not found.
What message exchange pattern is used? Is it synchronous (request-reply) or asynchronous (fire-forget) messaging pattern?
  • Synchronous message patterns will expect a response and will be blocked until a response is returned or timed out.
  • Asynchronous messaging patterns assume that the requests will ultimately be processed.
What type of exception is it? Is the exception cause by a system/technical issue (such as network outage) or is it a business issue (such as invalid data). How you handle the exception will depend on the type. For example:
  • An exception caused by a system outage should automatically be handled by a retry mechanism in the the outage is resolved.
  • An exception caused by a data issue should not be retried as it is unlikely retrying without fixing the underlying cause will be successful.

Why is it important to be able to categorize exceptions?

It is important to be able to categorize exceptions because not all exceptions are the same. At a very high level, we can classify exceptions into “Business” or “Non-Business” exceptions. Within these two classes, there can be any number of types of Business and Non-Business exceptions.

Business exceptions are typically due to incorrect data or incorrect process flow. Due to the nature of a business exception, it is typically non-retriable and therefore would not make sense to configure a rollback and retry. Instead, processing should stop immediately, and the exception sent back as a response or message routed to a dead letter queue and a notification sent to operations.

Example:

An integration use case where there is a need to consume messages from a JMS queue. Message processing then typically follows the VETO or VETRO pattern (Validate, Enrich, Transform, Route and Operate). An exception can happen at any part of this pattern. For example:

  • As a part of the validate process, it might be required to check some piece of data in the payload is valid according to some business rule (against another service, database or a simpler data check like is email formatted correctly).
  • As a part of the transformation process, it might be required to change the format of the payload.
  • In the context of the route process, the data might be inserted into a database table.

The sample Mule project will be used to demonstrate how we can catch and handle specific exceptions. This example project is configured to consume a JMS message from ActiveMQ. The payload used is as below.

{

“type” : “system/business”,

“email” : “howto@mulesoftcom”

}

In the example flow, I've used a “Choice” component so that we can test different scenarios based on the input payload.

Type Subflow Description
System Database-Unavailable This subflow is configured to try and insert into a database which does not exist or is experiencing network connectivity issues.
Business Validation-Exception This subflow is configured to validate the email field that is incorrect.

picture1

picture2

For clarity, I've separated out the exception handling into a separate Mule configuration file and utilized the “Reference Exception Strategy” component to refer to this exception handler. The benefit of extracting the exception handler is that it can then be reused in other Mule flows.

picture3

Here we use the Choice Exception Strategy component. A choice exception strategy catches all exceptions thrown within its parent flow and allows the developer to examine message contents and exception type and then finally route the message to the appropriate exception strategy for processing. In our ‘HowTo” example, we configured two “Choice Exception Strategy,” a “Rollback Exception Strategy” and a default catch all “Choice Exception Strategy.”

Catch Exception Strategy

So let's take a closer look at one of the Catch Exception Strategy exception handling flows.

picture4

picture5

Here we can see that this exception handler is configured when the exception is caused by a Mule exception “org.mule.extension.validation.api.ValidationException”. This exception is thrown when we use the Mule Validation module. We can also use standard boolean operators such as && (AND) or || (OR) along with standard Mule Expression Language (MEL) to build complex criterion. In the example project, we use the following.

#[exception.causedBy(org.mule.extension.validation.api.ValidationException)

For more examples see MuleSoft documentation.

The exception flow handler itself would then route the original message payload to a dead letter queue with some additional metadata (such as exception message, exception type, unique identifier, etc.exchange  here) to help root cause analysis. No retries are configured as retrying would only cause the same exception to be raised.

{
“type” : “business”,
“email” : “howto@mulesoftcomm”
}

Using the payload above we can see the log output and the exception thrown. The exact exception thrown is the “org.mule.extension.validation.api.ValidationException” because the email we specific in the payload is in an incorrect format. This is the exception that we have configured to the captured and processed.

picture6

picture6b

And finally the original message is routed to a dead letter queue, we can also see we have added some additional metadata to help with root cause analysis.

picture6c

Rollback Exception Strategy

Now let's look at the Rollback Exception Strategy exception handling flow.

picture7

Here we immediately see some differences when compared to the exception strategy discussed above. In a Rollback Exception Strategy, we have to configurable paths in the flow itself. One for the standard exception processing and the other for when redelivery has been exhausted.

picture8

For our example project, we configured the standard exception processing to output a simple log and when redelivery has been exhausted the flow would then route the original message payload to a dead letter queue with some additional metadata (such as exception message, exception type, unique identifier, etc.). to help root cause analysis.

{

“type” : “system”,

“email” : “howto@mulesoft.com”

}

Using the payload above we can see the log output and the exception thrown. The exact exception thrown is the “java.sql.SQLException” because the database is unavailable. We can also see in the log output the Mule flow will rollback the transaction and will attempt to redeliver up to the maximum specified in the Rollback Exception Strategy.

picture9

picture10

And finally the original message is routed to a dead letter queue, we can also see we have added some additional metadata to help with root cause analysis.

picture11

Summary

As you can recognize exceptions can happen at any point within an integration flow, and it is important that we handle them accordingly. Exceptions should never be silently discarded unless there is a good reason to do so. How you handle an exception will depend on the transport, message exchange pattern and type of exception raised. It is, therefore, important to be able to identify the exception and categorize them, so we have a consistent way of handling them. Anypoint platform provides a broad range of exception management strategies to do robust error handling.

Project Download

The  Mule project in Anypoint Exchange can be downloaded here.


latest report
Learn why we are the Leaders in API management and