Error Handling simplified – Try Scope

Last Updated on 02/05/2021 by Patryk Bandurski

Errors occur all the time. All you can do is implement error handling. In this article, I will describe how to use the introduced layer of abstraction in the exceptions area. Before Mule 4, developers only could access raw Java exceptions as Mule is a Java-based ESB. This lead to a situation where you, as a developer, needed to analyze documentation to find the exact exception that you would like to handle. Now an Error concept was introduced.

Error Object

In the previous version of Mule, the developer needs to operate on a raw Java exception. However, in Mule 4 Error concept has been introduced. Below I have prepared a simple UML diagram depicting this new idea.

The Error class
The Error class

The main Error class has all information about the exception like description and reference to original Java object that inherits from Throwable interface. To differentiate what error we are coupling with we can use errorType field. It contains an error namespace and identifier. Let’s see how does Error looks for 404 error. The representation below is in JSON form.

{
	"description": "HTTP GET on resource 'http://localhost:8091/notfound' failed: not found (404).",
	"detailedDescription": "HTTP GET on resource 'http://localhost:8091/notfound' failed: not found (404).",
	"errorType": {
		"namespace": "HTTP",
		"identifier": "NOT_FOUND"
	},
	"cause": "org.mule.extension.http.api.request.validator.ResponseValidatorTypedException"
}

As you can see errorType holds HTTP:NOT_FOUND type. This informs us that we are handling HTTP error and specifically NOT_FOUND one. We can access meaningful descriptions in description and detailedDescription fields.

The most important question is: how do I access error from dataweave? You do this by using error keyword.

Hierarchy of errors

All errors are in hierarchical structure like below.

Error hierarchy - ANY and CRITICAL roots
Error hierarchy – ANY and CRITICAL roots

We have ANY error that can match any error.  It is the root of the hierarchy. We have one error known as UNKNOWN that is returned in cases when the cause is not known. All errors that inherit from ANY can be handled in Try Scope. In contrast, CRITICAL can not be handled. These are exceptions that cause applications to stop like storage size has been exceeded or out of memory.

In the previous section, I have written that error has also a namespace. It has not been depicted on the diagram as all of these errors can occur for different namespaces. Let’s say that we have an HTTP Request Connector. It can have connectivity issues. In such a case, we should receive HTTP:CONNECTIVITY not CONNECTIVITY. You need to look following pair namespace and identifier as a whole.

Error Handling

We have two strategies. It is much simpler than before. We can catch the error and handle it or we can rethrow it. We have also Try Scope to use it with. This scope encapsulates one or more event processors and handles this piece of flow errors.

On Error Propagate

This strategy you can use when you want to rethrow an error after error handling login have been completed. You can define a couple of properties on this element:

  • enableNotifications – boolean flag, if set to true Mule engine will fire ExceptionNotification,
  • logException – boolean flag, if set to true the Mule engine will log the exception,
  • type – error type (namespace + identifier) linked with error handler,
  • when – complex condition, if evaluated to true Mule engine will handle error in this error handler.

Below you can find a simple Try Scope around Request Listener Connector. In the visual editor, you can see what condition does error handler expects. Here is the exact match of errorType. This strategy will be triggered only for NOT_FOUND error in the HTTP context.

On Error Propagate in the Try Scope
On Error Propagate in the Try Scope

Below is the XML representation of the flow above. Both enableNotification and logException have default values set to true. You can place within on-error-propagate as many event processors as you like. In the given example payload is set and is logged.

<error-handler>
	<on-error-propagate enableNotifications="true" logException="true" doc:name="On Error Propagate" type="HTTP:NOT_FOUND">
		<ee:transform doc:name="Error Response">
			<ee:message>
				<ee:set-payload>
					<![CDATA[%dw 2.0
output application/json
---
{
prop: "Super Value"
}]]>
				</ee:set-payload>
			</ee:message>
		</ee:transform>
		<logger level="INFO" doc:name="Log the Message"/>
	</on-error-propagate>
</error-handler>

When the HTTP Request Connector throws a Not Found error it will trigger the error handler.  The caught exception will be logged and the payload would be set to a new value. Then the error will be rethrown to the next scope. Like in the diagram below, caught exceptions in private-try-flow will be rethrown and sent to main-try-flow. In this case, two possible outcomes are possible. If error handling is in place, Mule will route the error there. If not, the error will be treated as an unhandled error caught in main-try-flow.

On Error Propagate and Try Scope example
On Error Propagate and Try Scope example

On Error Continue

This strategy you can use when you want to handle an error and process further flow as if nothing has happened. You can define a couple of properties on this element:

  • enableNotifications – boolean flag, if set to true Mule engine will fire ExceptionNotification,
  • logException – boolean flag, if set to true the Mule engine will log an exception,
  • type – error type (namespace + identifier) linked with error handler,
  • when – complex condition, if evaluated to true Mule engine will handle error in this error handler.

Below you can find a simple Try Scope around Transform Message. In the visual editor, you can see what condition does error handler expects. This one expects ANY error as nothing more than “On Error Continue” is displayed.

On Error Continue with the Try Scope example
On Error Continue with the Try Scope example

In this case, Try wraps Transform Message. We may expect here errors from the MULE namespace due to errors in the DataWeave engine. For example, if division by zero occurs On Error Continue will handle exception MULE:EXPRESSION. I have decided to continue flow after the error therefore I selected the On Error Continue strategy.  In order to achieve that I set a default payload in the error handler. The next mule passes this payload to the next event processor in the main-continue-flow.

Summary

In my opinion, this is a major improvement. The introduced layer of abstraction on the error level was a good idea. Most noteworthy are two strategies to handle all possible error scenarios. But they can achieve all that was possible in Mule 3.x. While in the previous version errors can be handled on the whole flow/subflow level, now we can handle errors on the event message level as well. Using try scope we can achieve more granular error handling if necessary.

Error Handling simplified – Try Scope

Leave a Reply

Your email address will not be published. Required fields are marked *

Scroll to top