Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Error Handling Simplified

DZone's Guide to

Error Handling Simplified

In this article, I will describe how to use an introduced layer of abstraction in an exceptions area.

· Integration Zone ·
Free Resource

The State of API Integration 2018: Get Cloud Elements’ report for the most comprehensive breakdown of the API integration industry’s past, present, and future.

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

Error Object

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

Image title

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 a hierarchical structure like below.

Image title

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 cannot be handled. These are exceptions that cause the application to stop like storage size has been exceeded or out of memory.

In the previous chapter, 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 case, we should receive HTTP:CONNECTIVITY not CONNECTIVITY. You need to look at the following pair namespace and identifier as a whole.

Error Handling

We have two strategies. It is much simpler than before. We can catch an 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 for this piece of flow error.

On Error Propagate

You can use this strategy when you want to rethrow an error after error handling login has 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 the error handler expects. Here is an exact match of errorType. This strategy will be triggerd only for NOT_FOUND error in HTTP context.

Image title

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" 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.

Image title

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 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.

Image title

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

Summary

In my opinion, this is a major improvement. An 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 that was possible in Mule 3.x. While in the 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.

Your API is not enough. Learn why (and how) leading SaaS providers are turning their products into platforms with API integration in the ebook, Build Platforms, Not Products from Cloud Elements.

Topics:
integration

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}