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

Error Object

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

Error Mule classes
Error Mule classes

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 error namespace and identifier. Let’s see how does Error look for 404 error. 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 description 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.

Errors hierarchy
Errors hierarchy

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 inherits from ANY can be handled in Try Scope. In contract CRITICAL can not be handled. These are exceptions that cause application to stop like storage size has been exceeded or out of memory.

In previous chapter I have written that error has also a namespace. It has not been depicted on diagram as all of these error can occur for different namespaces. Let’s say that we have an HTTP Request Connector. It can have connectivity issues. In such case we should receive HTTP:CONECTIVITY not CONECTIVITY. 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 error and handle it or we can rethrow it. We have also Try Scope to use it with. This scope encapsulate one or more event processors and handle for 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 trueMule engine will log 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 visual editor you can see what condition does error handler expects. Here is exact match of errorType. This strategy will be triggerd only for NOT_FOUND error in HTTP context.

On Error Propagate
On Error Propagate

Below is xml representation of the flow above. Both enableNotification and logException have default value set to true. You can place within on-error-propagte 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" doc:id="9a14dd28-573f-4972-a55b-40a9ea6f96c2" type="HTTP:NOT_FOUND">
    <ee:transform doc:name="Transform Message" doc:id="410f4ed7-2a99-47e8-9225-f71cb08f8ff7" >
      <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="Logger" doc:id="348989ba-d785-4a70-84cd-696c123567f4" />
  </on-error-propagate>
</error-handler>

When the HTTP Request Connector throws Not Found error it will trigger error handler.  Caught exception will be logged and payload would be set to a new value. Then error will be rethrown to the next scope. Like in the diagram below, caught exception 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 error there. If not, error will be treated as an unhandled error caught in main-try-flow.

On Error Propagate example
On Error Propagate 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 trueMule engine will log 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 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 example
On Error Continue example

In this case Try wraps Transform Message. We may expect here errors from MULE namespace due to errors in 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 On Error Continue strategy.  In order to achieve that I set a default payload in error handler. Next mule passes this payload to the next event processors in the main-continue-flow.

Summary

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

Tagged on:         

Leave a Reply

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