Home United States USA — software A Look Into Error Handling in Mule 4 Beta A Look Into...

A Look Into Error Handling in Mule 4 Beta A Look Into Error Handling in Mule 4 Beta

134
0
SHARE

This post explains the major changes introduced around error handling in the Mule 4 beta, including easier routing and the introduction of the try scope.
If you ever used Mule 3, then there are probably two things about error handling you already know:
In many ways, Mule can be considered an extremely high-level, domain-specific programming language: you have data types, procedures, flow control mechanisms, and so on. But this analogy doesn’ t quite work for Mule 3, partly because there isn’ t a clearly defined error-handling semantic. We relied on Java Throwables, with no way of communicating what kind of error each component throws. This meant users had to check the source code or force the error to see what happened.
comes closer to the above analogy, particularly when it comes to error handling. Although we’ ve kept Java Throwables available, the main error handling mechanism in is based on the Mule Runtime engine’s own errors: if something goes wrong with a component, you will get a clear error that is typed accordingly, with useful data on the problem. It can then be easily routed to a handler.
More importantly, each component declares the type of errors it may throw, so you’ ll identify potential errors at design time. Let’s take a closer look at the new semantics.
Execution failures are represented with Mule errors that have the following components:
For example, when a request fails with a 401 status code, a Mule Error provides the following information:
In the example above, the error type is HTTP: UNAUTHORIZED, not simply UNAUTHORIZED. This is because error types consist of a namespace and an identifier, allowing you to distinguish the types according to their domain: we have HTTP: NOT_FOUND and FILE: NOT_FOUND, for example. While connectors define their own namespace, core runtime errors have an implicit one: MULE: EXPRESSION and EXPRESSION are interpreted as one.
Another important characteristic of error types is that they may have a parent type. For example, HTTP: UNAUTHORIZED has MULE: CLIENT_SECURITY as the parent, which, in turn, has MULE: SECURITY as the parent. This establishes error types as specifications of more global ones: an HTTP unauthorized error is a kind of client security error, which is a type of a more broad security issue.
These hierarchies mean routing can be more general, since, for example, a handler for MULE: SECURITY will catch HTTP unauthorized errors as well as OAuth errors. Below you can see what the core runtime’s hierarchy looks like:
All errors are either general or CRITICAL, the latter being so severe that they cannot be handled. At the top of the general hierarchy is ANY, which allows matching all types under it. It’s important to note the UNKNOWN type, which is used when no clear reason for the failure is found.
This error can only be handled through the ANY type to allow specifying the unclear errors in the future, without changing existing apps behavior. When it comes to connectors, each connector defines its error type hierarchy considering the core runtime one, though CONNECTIVITY and RETRY_EXHAUSTED types are always present––since they are common to all connectors.
The most important thing about these error types is that they are part of each component’s definition, so during the design process, you will be aware of any failures that could occur.
Mule 4 has redesigned handling errors, by introducing the error-handler component, which can contain any number of internal handlers and can route an error to the first one matching it.
If an error is raised within a flow, its error handler will be executed and the error will be routed to the matching handler. At this point, the error is available for inspection, so the handlers could execute and act accordingly:
Let’s take a look at a few examples to see how this works. First, consider the following application where a listener triggers a flow reference to another flow that performs an HTTP request.
If everything goes right when a message is received (1) the reference is triggered (2) and the request performed (3) , resulting in a successful response (4) .
If the HTTP request fails with a not found error (3) , because of the error handler setup of inner-flow, then the error will be propagated (4) , and the flow reference will fail as well (2) . However, since primary-flow is handling that with an on-error-continue, this will execute (5) and a successful response will be returned (6) .
Should the request fail with an unauthorized error instead (3) , then the inner-flow will handle it with an on-error-continue by retrieving static content from a file (4) . Then, the flow reference will be successful as well (2) and a successful response will be returned (5) .
But what if another error occurred in the HTTP request? Although there are only handlers for “not found” and “unauthorized” errors in the flow, errors are still propagated by default. This means that if no handler matches the error that is raised, then it will be rethrown. For example, if the request fails with a method not allowed error (3) , then it will be propagated causing the flow reference to fail (2) , and that propagation will result in a failure response (4) .
The scenario above could be avoided by making the last handler match ANY, instead of just HTTP: UNAUTHORIZED. Notice how, below, all the possible errors of an HTTP request are suggested:
You can also match errors using an expression. For example, since the Mule Error is available during error handling, we can use it to match all errors whose namespace is HTTP:
One issue we’ ve also addressed in Mule 4 is the need for more fine-grained. For the most part, Mule 3 only allows handling errors at the flow level, forcing you to extract logic to a flow in order to address errors.
The error handler behaves as we have explained earlier. In the example above, any database connection errors will be propagated, causing the try to fail and the flow’s error handler to execute. In this case, any other errors will be handled and the try scope will be considered successful which, in turn, means that the following processor, an HTTP request, will continue executing.
Another way in which we’ ve allowed more fine-grained error handling is by allowing mapping errors to custom ones.

Continue reading...