Introduction to error handling using Anypoint Studio (Mule 4)
- August 11, 2021
Error handling refers to the anticipation, detection and resolution of programming, application and communications errors.
There are different types of errors such as syntax error, logical error and runtime error.
In programming, a development error is one that can be prevented. Such an error can occur in syntax or logic. Syntax errors, which are typographical mistakes or improper use of special characters, are handled by rigorous proofreading. Logic errors, also called bugs, occur when executed code doesn’t produce the expected or desired result. Logic errors are best handled by meticulous program debugging. This can be an ongoing process that involves beta testing prior to the official release and customer feedback after the official release, in addition to the traditional debugging routine.
A runtime error takes place during the execution of a program and usually happens because of adverse system parameters or invalid input data. An example is the lack of sufficient memory to run an application or a memory conflict with another program. On the Internet, runtime errors can result from electrical noise, various forms of malware or an exceptionally heavy demand on a server. Runtime errors can be resolved, or their impact minimized, by the use of error handler programs, by vigilance on the part of network and server administrators and by reasonable security countermeasures on the part of Internet users.
In this article, we’ll focus on handling runtime errors through different levels of error handlers. In Anypoint Studio, the following are different levels of error handler:
- Mule default error handler
- Global error handler (custom)
- Flow level error handler
- Scope level error handler
Mule default error handler
If no error handler is defined, all runtime errors are handled by a Mule default error handler. Mule default error handler handles all messaging errors thrown in the Mule application implicitly and globally. It stops the execution of the flow and logs the information about the error. Mule default error handler acts the same for all the applications and cannot be configured manually.
When an error is thrown, an error object is created and added to the Mule event. It has many properties, but the following two are the most important ones.
- error.description — a string
- error.errorType — an object giving the lineage of the error
Error types are identified by a namespace and an identifier. e.g. HTTP:UNAUTHORIZED, HTTP:CONNECTIVITY, etc. Error types are hierarchical in nature, which allows for a different level of granularity for catching errors. This gives the flexibility to configure an error scope for a specific namespace and identifier or any identifier in the namespace. Every error type has a parent error type. ANY is the most general parent i.e. it doesn’t have a parent. All levels can be general or critical as shown in the following exhibit.
Critical errors are so severe they can’t be handled. ANY is at the top level in general errors. The UNKNOWN type is used when no clear reason for the error is found. This error can only be handled by ANY type. This allows specifying unclear errors in the future without changing the existing App’s behavior.
Let’s understand this better with an error handling scenario.
Error handling scenario 1
In this scenario, there’s no error handler at the flow level. As the flow is executing, the error occurs at the event processor labeled E. Because of this, processor P and any subsequent processors will never be executed as shown in the exhibit below.
Since there’s no error handler defined, the event will be passed to the Mule default error handler. The Mule default error handler logs the error information and returns the event with the error object because it uses an on error propagate scope. This is called rethrowing the error and since this is the calling flow, it returns an error response to the HTTP listener. This is shown in the following exhibit.
Let’s see this scenario with a working example.
The XML of the above flow is as follows.
<?xml version=”1.0" encoding=”UTF-8"?>
<mule xmlns:validation=”http://www.mulesoft.org/schema/mule/validation" xmlns:http=”http://www.mulesoft.org/schema/mule/http"
xmlns=”http://www.mulesoft.org/schema/mule/core"
xmlns:doc=”http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=”http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd
http://www.mulesoft.org/schema/mule/validation http://www.mulesoft.org/schema/mule/validation/current/mule-validation.xsd">
<flow name=”Scenario-1" doc:id=”80927bef-8f52–4240–9b27–3465f7034c28" >
<http:listener doc:name=”Listener” doc:id=”d89fdc6d-2729–4ff0–87ae-b860c312a2af” config-ref=”HTTP_Listener_config” path=”/base”/>
<set-payload value=’”Max Mule”’ doc:name=’Payload = “Max Mule”’ doc:id=”3a9e238a-e476–4944-a49e-7e678850660c” />
<validation:is-null doc:name=”Is null” doc:id=”2443d2ba-8d82–4c70-bde2–79c600534f85" value=’#[“Payload is not null”]’/>
<set-payload doc:name=’payload = “modified payload”’ doc:id=”970eb6f6-f2db-4a67–904c-b5e28964f682" value=’”modified payload”’/>
<logger level=”INFO” doc:name=”Logger” doc:id=”1767a7bc-58f7–40fe-bd70-bc359850c1a6" message=”#[payload]”/>
</flow>
</mule>
Debug the application to understand how the error is handled.
Once your application is successfully deployed, go to Postman or Advance rest-client and send a request to the API. As seen in the exhibit below, the payload isn’t set yet.
Moving one step forward, the payload is set to “Max Mule”. (exhibit below)
When another step is taken, the error is thrown by the “is null” validation processor. As this flow doesn’t have any scope level, flow level or global error handler, the Mule event goes to the Mule default error handler. (exhibit below)
When we step further, the error is rethrown and an error response is recorded as Mule default error handler uses on error propagate scope. (exhibit below)
We get the following response in Postman.
Global error handler
Though one can’t modify the Mule default error handler, we can create a global (application level) error handler. When we define error handler, the first thing to do is to add a scope that’s used to organize the event processors as much as a flow does. There are two types of error handling scopes:
- On Error Propagate
- On Error Continue
Let’s look at each one in detail.
On Error Propagate
All event processors in the error handling scope are executed. At the end end of the scope:
- The rest of the flow that threw the error isn’t executed.
- The error is rethrown up to the next level and handled there.
The HTTP listener returns the error response.
On Error Continue
All event processors in the error handling scope are executed. At the end end of the scope:
- The rest of the flow that threw the error isn’t executed.
- The event is passed up to the next level as if the flow execution had been completed successfully.
The HTTP listener returns the successful response.
A global error handler can also be defined for the whole application. It’s revoked only when there’s no scope level or processor level error handler. We can do so by adding the “Error Handler” scope to a Mule configuration file. Typically, it’s put in the global configuration file. Then this handler needs to be specified as the application’s default error handler.
You can add any number of error handler (propagate or continue) scope to this global error handler. Each error handler scope specifies when it should be executed. The error is handled by the first error scope whose condition evaluates to true.
— By Sanket Kangle