With a Mule and a Toad involved, one could expect that a third character would quickly need to be added to the cast: a princess to ride the former and kiss the latter. But then, what would be so exceptional about it? Because, actually, this story is about exceptions and their graceful handling. Moreover, the story takes place in the clouds, and princesses don’t fly so well…
So let’s come back to our main protagonists: you know Mule ESB already but you may not have heard about Hoptoad, an on-line service from thoughbot that takes care of aggregating exception messages and presenting them on a very well-crafted dashboard. Hoptoad is well known in the Ruby community, as it was initially built for Rails application, but any application that can post XML over HTTP, or use one of the numerous clients, can benefit from it.
As more and more applications get deployed in the cloud, using cloud-based services is starting to make a lot of sense for anything that’s outside the realm of a business’ core. Dealing with errors falls into that category. In this post, we will look at how your Mule applications could leverage Hoptoad for handling exceptions. Even if you don’t run Mule ESB on CloudCat and even if you’re already benefiting from the advanced error management features of Mule’s Management Console, you’ll still be interested to read on and learn about the construction of a custom exception handler for Mule.
Hoptoad’s Java client comes complete with a specific Log4j appender that can broadcast errors directly to the web service. Using this appender in Mule is easy (just configure it in your Log4j configuration) and gives results immediately. But, because it is a generic plug-in, the Log4j appender doesn’t extract any Mule-specific information out of the context of the error. Knowing that the Hoptoad API supports a lot of different type of contextual information for an error, building a Mule-aware plug-in that fully leverages the API sounds like a good idea.
Before delving into code, let’s take a look at the way we will bind the error’s contextual information with the fields supported by Hoptoad. It’s not a perfect one-to-one mapping but it’s good enough to produce exception messages that make sense:
|Contextual information||Hoptoad API||Mule specific?|
|Error message and class||Same||N|
|Environment name||Rails Environment||N|
|Java System Properties||Environment||N|
|Mule’s working directory||Project Root||Y|
|Endpoint URI||Request URL||Y|
|Service name||Request component||Y|
|Message properties||Request params||Y|
|Session properties||Request session||Y|
Concretely speaking, we will implement a custom exception strategy that will have all the behavior of Mule’s default one except it will also dispatch exceptions to Hoptoad. For this, we will rely on the existing Hoptoad Java client (more precisely its most advanced incarnation on GitHub). The Java client uses a notification builder to produce the messages that will be sent to Hoptoad: we will subclass this builder in order to perform the Mule specific bindings discussed in the table above. Here is the plan for the UML buffs out there:
Let’s first look at the HoptoadExceptionStrategy class:
As you can see, most of the class is boilerplate Java code for receiving two parameters: the environment name (like “development”, “staging”, “production”…) and the API key for the Hoptoad project that will be associated with your Mule instance. The interesting stuff happens in the exceptionThrown method, where we look up the Mule event context that is potentially associated with the current thread (it can be null if the exception is caught outside of the context of a message flow). We then pass it on to our specific notification builder and send the notification to Hoptoad.
One may wonder why using the (rudimentary) notification broadcasting infrastructure bundled with the Hoptoad’s Java client instead of Mule’s support for HTTP outbound requests. The problem is that we would be assuming that Mule’s HTTP transport would always be present (which is not a given, as it depends on the deployment model and the project itself). Moreover, using a piece of an infrastructure to report exceptions about itself can leave you incommunicado if it’s failing really badly.
Notice how we’ve overridden exceptionThrown in order to intercept and report all exceptions caught by our exception strategies. If we have wanted to process only certain types of exceptions, we could have instead overridden more specific methods from the default exception strategy, namely: handleMessagingException, handleRoutingException, handleLifecycleException and handleStandardException.
Now let’s have a look at the Mule specific notification builder:
If a null Mule event context has been passed, we basically build a standard non Mule-specific notification. To the opposite, when an event context is available, notice how in addFromEventContext we’re able to extract all the Mule-specific information we’ve listed in the above table.
Now it’s time to put all this into motion! Here is a Mule configuration snippet that uses our exception strategy:
As you can see, we grouped the services for which we want to have exceptions broadcasted to Hoptoad in a specific model. Indeed, it’s very possible that you will not be interested into applying this exception strategy to the whole Mule configuration: this is when using multiple models come handy. Now it’s time to generate some errors and see the final result on-line:
Everything looks good: we can now enjoy a pretty thorough Mule-specific context in the errors aggregated on Hoptoad.
In the opening paragraph, we said that this story didn’t need a princess. What it could use though is a benevolent despot: would you be interested to turn this into a MuleForge project and maintain it? If yes, sign-up here!
Or maybe you have a cool cloud or Saas related Mule gimmick you’d like to talk about or share with the community? Feel free to comment on this post and tell us all about it!