Though a veteran language and platform, Erlang has recently gained a lot of traction, as very visible web sites and open source projects decided to use it in order to leverage its intrinsic support for highly concurrent, fault tolerant and distributed applications. To name a few, let’s mention: Facebook Chat, Mochiweb, ejabberd, RabbitMQ, riak and CouchDB.
Without opting for Erlang as a development platform, companies may still be tempted to leverage an Erlang-built middleware: most of them offer public interfaces accessible over generic protocols, like HTTP, and are easy to integrate quickly and efficiently. That said advanced scenarios can require a tighter integration like, for example, creating a module for ejabberd that requires to call custom Java code or reaching server functions on RabbitMQ that are not accessible through AMQP.
This is when the Duke meets Erl. And this is when Mule ESB can help, thanks to the new and coming Erlang Transport for Mule 3. Read on for more information about the transport and a walk-through a simple use-case of RabbitMQ integration.
The Mule Erlang Transport is built on top of Erlang’s Jinterface, which provides the low level building blocks necessary to interface Java and Erlang systems. The transport takes care of configuring these building blocks and does extra stuff like supporting threading (so incoming messages are processed in parallel and not sequentially), offering support for inbound and outbound gen_server call semantics (for better integration with OTP applications) and transparent Java ⇔ Erlang message transformations.
So what can we concretely do with this new transport? Here are a few examples:
- Access POJOs or Spring beans from Erlang, with standard gen_server semantics,
- Expose enterprise resources, like JMS queue, to Erlang applications, again with standard gen_server semantics.
- Dispatch messages to Erlang systems, with a wide range of possible call semantics (raw, PID wrapped, gen_server call and cast, and RPC).
We’re going to use the latter to implement a simple use case: we want to enable the provisioning of RabbitMQ users, through Mule ESB, via a simple HTTP POST of a JSON object (something that is not feasible over AMQP).
Use case: Provisioning RabbitMQ users through Mule
The Erlang transport connector declaration is very simple:
This connector will be identified as MuleRabbitMqController amongst all the Erlang nodes that may engage in a cluster. Note that we need to use the same magic cookie (Erlang’s security is delicious) as the one used by RabbitMQ in order to communicate with it.
A user provisioning operation is done with two RabbitMQ commands: create user and set permissions. Therefore we will create two Mule services, one for each operation, chaining them together with an in-memory queue. We will set the permissions only if creating the user was successful. Let’s look at the first service, which does the JSON heavy-lifting for incoming HTTP requests and their responses, and tries to create a user on RabbitMQ:
The important aspect of this service is the outbound RPC call to Erlang. Note how we pass a list of binaries, which are the arguments expected by the rabbit_access_control:add_user/2 function. Also, since we only have one Erlang connector in our configuration, we don’t need to explicitly refer to it in each endpoint. We pass whatever the result to this call was to the next service, listed below:
Following a common Erlang pattern, the user creation service should have returned “ok” in case of success. If that was the case, we proceed with the setting of permissions, calling rabbit_access_control:set_permissions/5 in a similar fashion as we did for the user creation. If the user creation failed, we send whatever error response was returned to a logger service:
With this in place, we can now try to run our Mule configuration. The JSON object to HTTP POST has a very simple form:
Let’s give it a try:
Success! We now have a user ‘mule’ created with all permissions granted on the / virtual host. Let’s run the command again:
Expected failure! Errors are correctly returned from RabbitMQ and reported back to the caller. Note that a failure in permission setting would be directly reported to the caller too.
Thanks to this simple Mule service, any HTTP-capable system or application in your IT landscape is now able to provision users in RabbitMQ.
In the future, if someone mentions Erlang, have no fear and… bring Erl on!