Back to Blog Archive

Mule 4 error handling – a review

Posted on: October 29, 2020
Author:
Noel

Introduction

In Mule 3, during design time of a Mule application, it was not easy to determine the exceptions that may be thrown by the flow components. This has been improved in Mule 4 with the use of Error Types which can be seen as metadata for Java exceptions. An Error Type is composed of two main parts, the namespace and an identifier separated by a colon (e.g. MULE:VALIDATION where MULE is the namespace and VALIDATION is the identifier).

Error Handling Overview

As depicted in the following image, Mule 4 Error Types have a tree structure, where the root node can either be ANY – for business errors/errors that can be handled (i.e. messaging errors – when Mule events/flows are involved) – or CRITICAL – for system errors/errors that cannot be handled (i.e. system errors – when no Mule events/flows are involved).

The Mule 4 Error Types structure. Source: https://docs.mulesoft.com/mule-runtime/4.3/intro-error-handlers

Since critical/system errors cannot be handled, during this post we will mainly focus on Mule 4 messaging errors (which are Error Types that extend from ANY).

The Mule Error Structure

In a Mule application, when an error is raised from a component inside a Mule flow (in this case a <validation:is-not-blank-string /> component), an error object containing the following information is created:

Where:

  • #[error.description] is the error description;
  • #[error.detailedDescription] may provide more information on the error;
  • #[error.errorType] contains the namespace and identifier definition of the current error and its parent Error Types up to the MULE:ANY Error Type;
  • #[error.errors] contains any nested errors such as when using the Scatter-Gather router (similar result when using the DataWeave expression #[error.childErrors]);
  • #[error.exception] contains the respective Java exception object (similar result when using the DataWeave expression #[error.cause]), and
  • #[error.errorMessage] may contain a Mule message returned by the respective component (e.g. #[error.errorMessage.payload] is used to retrieve the payload, #[error.errorMessage.attributes] is used to retrieve the attributes, while #[error.errorMessage.attributes.statusCode] is used to retrieve the status code of an HTTP request).

When taking a more in-depth look at the error object (which is a type of ErrorImplementation), we can see that it has the following structure:

This shows that VALIDATION:BLANK_STRING is the child of VALIDATION:VALIDATION, which is the child of the MULE:VALIDATION Error Type. MULE:VALIDATION is the child of MULE:ANY – the root Error Type (i.e. the parentErrorType value is null). Therefore, when using an error handler (see Error Handling Components Review section), through inheritance, a parent Error Type can be used to handle all the child Error Types without the need of defining each child Error Type. In this case, if the error handler is configured to handle errors of type MULE:VALIDATION, then all the validation child error types would be handled, hence improving code reusability.

Mule 4 Error Types Mappings

Mule 4 components also support mapping the Error Types to custom ones. This might be useful when the same operation is used multiple times in a flow but the same errors should be handled differently. To do so, from the Anypoint Studio’s canvas, the respective operation should be selected and then from the Mule properties view, Error Mapping tab, the mappings should be defined. (Please refer to https://docs.mulesoft.com/mule-runtime/4.3/intro-error-handlers#error-mapping for more information.)

Once this is done, the Error Type object would be different (as can be seen from the image below), since custom Error Types are direct children of the MULE:ANY Error Type.

 

Nested Errors

When using a component such as the Scatter-Gather router, the error object contains information about each error raised from each path. Assume that the following flow is used:

Sample Mule 4 Scatter-Gather router flow
Since both paths throw an error (i.e. in path 1, 1 is divided by 0, while in path 2, the payload is empty), the following error object having Error Type MULE:COMPOSITE_ROUTING would be created. This parent error object, which can be seen as a wrapper, contains nested errors (having the same error structure) that represent the error thrown by each Scatter-Gather router path. To access these nested/inner errors as a list of error objects, the DataWeave expression #[error.errors] or #[error.childErrors] should be used, where the key defines the error path (e.g. 0 for the first path).

(Referring to section Sample Mule Flows, this can be tested by calling the http://localhost:8081/scatter-gather endpoint.)

Error Handling Components Review

The following table provides an overview of the Mule 4 components that can be used to handle errors (i.e. the Error Handler, On Error Continue, and On Error Propagate components) or raise errors (i.e. the Raise Error component).

Mule Palette - Error handler Mule 4 Error Handler component

The Error Handler component is used to handle errors at application level (by adding the Configuration global element <configuration defaultErrorHandler-ref="error-handler" ...) or at flow level by referencing it from the flow error handler (using <error-handler ref="error-handler" />). As can be seen from the image on the left-hand side, the Error Handler component should have at least one On Error Continue or On Error Propagate scopes that define how the errors should be handled.

During application runtime, when more than one error handler (On Error Continue or On Error Propagate) matches an error, the first one would be chosen. Therefore, the child Error Types (e.g. VALIDATION:BLANK_STRING) should be defined first, otherwise, the parent Error Type (e.g. VALIDATION:VALIDATION), error handler would be executed.

Mule Palette - On Error Continue Mule 4 On Error Continue component

The On Error Continue component can be added to a Try/Flow error handler scope or inside the Error Handler component. Once a Mule event containing an error object enters this scope, the error object is not returned/propagated.

Component Configuration:

  • Type: the Error Types that should be handled.
  • When: a DataWeave expression that when evaluates to true the respective scope is chosen (when the type also matches).
  • Enable Notifications: whether a Mule Server notification should be raised.
  • Log Exceptions: whether the errors should be logged.
Mule Palette - On Error Propagate Mule 4 On Error Propagate component

Similar to the On Error Continue, the On Error Propagate component can be added to a Try/Flow error handler scope or inside the Error Handler component. Once a Mule event containing an error object enters this scope, the error object is returned/propagated.

Component Configuration:

  • Type: the Error Types that should be handled.
  • When: a DataWeave expression that when evaluates to true the respective scope is chosen (when the type also matches).
  • Enable Notifications: whether a Mule Server notification should be raised.
  • Log Exceptions: whether the errors should be logged.
Mule Palette - Raise Error Mule 4 Raise Error component

The Raise Error component is used to throw a custom error from within a Mule flow or sub-flow.

Component Configuration:

  • Type: the custom Error Type that should be thrown (composed of a namespace and identifier).
  • Description: the custom error description providing some context about the error.

Error Handling in Mule Flows

The Mule components that support custom error handling logic are:

  1. Application Global Error Handler
  2. Flows
  3. Try Scope

If the errors raised are not handled from within the Mule application code, then the Mule default error handler would be called. As a general rule, when an error occurs inside a scope, the components that are within the same scope which have not yet been processed will be skipped.

Try Scope – On Error Propagate

Mule 4 Try Scope - On Error Propagate, sample flow
Referring to the flow above, once executed, the following would be printed in the console logs. (Referring to section Sample Mule Flows, this can be tested by calling the http://localhost:8081/try-oep endpoint.)

The logs show that once the error is raised, the “TRY END” logger within the Try scope is not processed and the error is logged by the Try scope, On Error Propagate handler (since logExceptions is set to true). Once inside the error handler, the respective components are executed (i.e. the “TRY SCOPE ON ERROR” logger) and since it is a propagate scope, the error object would be re-thrown. Since the Try scope has propagated the error, the “FLOW END” logger would not be processed but the error would be caught by the flow On Error Continue.

Try Scope – On Error Continue

Mule 4 Try Scope - On Error Continue, sample flow
Referring to the flow above, once executed, the following would be printed in the console logs. (Referring to section Sample Mule Flows, this can be tested by calling the http://localhost:8081/try-oec endpoint.)

In this case, the behaviour is very similar to the Try scope, On Error Propagate example, but since the Try scope contains an On Error Continue, the error is handled within the Try scope and the error object is not propagated. Therefore, the “FLOW END” logger is printed.

Flow – On Error Propagate

Mule 4 Flow - On Error Propagate, sample flow
Referring to the flow above, once executed, the following would be printed in the console logs. (Referring to section Sample Mule Flows, this can be tested by calling the http://localhost:8081/flow-oep endpoint.)

In this case, when the error is raised the On Error Propagate error handler would be called and the “FLOW ON ERROR” logger would be executed. Since the “FLOW END” logger is within the same scope, it is not executed. Additionally, since an On Error Propagate is being used the HTTP caller will receive a response status code of 500 – the error is returned.

Referring to the same flow above, if an application global error handler was added to the Mule application having a matching On Error Continue handler (as follows) and referenced using a Configuration global element, the returned status code would still be 500. This is due to the error handler inside the flow, since when a flow error handler is defined (even if the none of the flow error handlers match), the global error handler is ignored.

Mule 4 Global Error Handler

 

Flow – On Error Continue

Mule 4 Flow - On Error Continue, sample flow
Referring to the flow above, once executed, the following would be printed in the console logs. (Referring to section Sample Mule Flows, this can be tested by calling the http://localhost:8081/flow-oec endpoint.)

In this case, the behaviour is very similar to the Flow, On Error Propagate example, but since the flow contains an On Error Continue, the error is handled within the flow and the HTTP response status code is 200 – the error is not returned.

Flow – Application Global Error Handler

Mule 4 Flow - Application Global Error Handler, sample flow Mule 4 Flow - Application Global Error Handler

Referring to the flow and the application global error handler above, once executed, the following would be printed in the console logs. (Referring to section Sample Mule Flows, this can be tested by calling the http://localhost:8081/app-default endpoint.)

As can be seen from the console logs, since there are no error handlers inside the flow, the application global error handler is called and the HTTP response status code is 200 due the On Error Continue not returning the error object. If the application global error handler was not defined/configured correctly using the Configuration global element, the Mule default error handler would be called.

Sample Mule Flows

To test/debug the above scenarios in Anypoint Studio, a Mule XML configuration file containing sample flows can be downloaded from here – error-handling-sample.zip and imported into a Mule 4 application.

(Mule flows logic is based on Mule v4.3.0)

References

Author:
Noel

Comments

Contact Us

Ricston Ltd.
Triq G.F. Agius De Soldanis,
Birkirkara, BKR 4850,
Malta
MT: +356 2133 4457
UK: +44 (0)2071935107

Send our experts a message

Need Help?
Ask our Experts!