Feb 18 2008

Integrating Flex and RabbitMQ using STOMP

Tag: Flex, Messaging, RabbitMQ, STOMPDerek Wischusen @ 12:21 am

An experimental STOMP adapter was recently released for RabbitMQ. This means that it is now possible for Flex/Flash apps to communicate with RabbitMQ using the ActionScript 3 STOMP client. The following is a simple demonstration of how to get these technologies to work together.

First, let’s start with a quick description of RabbitMQ and STOMP.

RabbitMQ:

RabbitMQ is a complete and highly reliable Enterprise Messaging system. The RabbitMQ client libraries and broker daemon can be used together to create an AMQP network, or used individually to bring the benefits of RabbitMQ to established networks.

Packages/installers are available for all major operating systems and platforms. RabbitMQ can also be deployed as a VMWare/Debian virtual appliance.

Features:

* A complete, conformant and interoperable implementation of the published AMQP specification
* Based on a proven platform, offering exceptionally high reliability, availability and scalability
* Good throughput and latency performance that is predictable and consistent
* Compact, easily maintainable code base, for rapid customisation and hot deployment
* Extensive facilities for management, monitoring, control and debugging
* Licensed under the open source Mozilla Public License

STOMP:

The Stomp project is the Streaming Text Orientated Messaging Protocol site (or the Protocol Briefly Known as TTMP and Represented by the symbol :ttmp).

Stomp provides an interoperable wire format so that any of the available Stomp Clients can communicate with any Stomp Message Broker to provide easy and widespread messaging interop among languages, platforms and brokers.

As you can see from its description, the primary protocol that RabbitMQ uses is AMQP. If you’d like to learn more about AMQP, then check out this site.

There is an ActionScript 3 client for AMQP that is being developed by Ben Hood. You can read more about this client and learn how to use it by checking out this post on Ben’s site.

Alright, let’s get started with the example of how to use as3-stomp client with RabbitMQ.

1. Follow the steps in this tutorial to get RabbitMQ running with the STOMP adapter.

2. Download the project files for the Flex app.

This project consists of two separate Applications: the ImageSender and the ImageReceiver. The project file also contains the compiled as3-stomp library, so you do not need to download it separately.

3. Import the project into Flex Builder. (This step is optional. Alternatively you could unzip the project file and run the apps by opening the ImageSender.html file and the ImageReceiver.html file in the bin-debug folder.)

4. Launch both applications.

Before we proceed let’s take a quick look at what happened when we launched the apps.

Both apps have an init method that gets called when the application first the creationComplete event. Here is what this method looks like in the ImageSender app:

private function init () : void
{
    var ch: ConnectHeaders = new ConnectHeaders();
    ch.login = "guest";
    ch.passcode = "guest"
    stomp.connect("localhost", 61613, ch);
}

In this code we create a ConnectHeaders object that we use to set the login and passcode for this session. By default, RabbitMQ creates a user called “guest” with password “guest”. We then call connect on the stomp client. The stomp client was instantiated using an MXML tag like so,

<stomp:Stomp id="stomp"  />

The code for the init method in the ImageReceiver app looks pretty much the same except that it contains one more line.


private var destination: String = "/queue/images";

private function init () : void
{
    var ch: ConnectHeaders = new ConnectHeaders();
    ch.login = "guest";
    ch.passcode = "guest"
    stomp.connect("localhost", 61613, ch);
    stomp.subscribe( destination );
}

On the final line in the init method we call the subscribe method on the stomp client. By calling this method we tell the stomp broker (RabbitMQ in this case) that we want to consume messages that are sent to this destination.

The code where we instantiate the stomp client in the ImageReceiver is also pretty much the same as it is in the ImageSender,

<stomp:Stomp id="stomp" message="handleMessages(event)"  />

The only difference is that we set message event property so that every time a message event is fired the handleMessages method gets called.

Ok, back to the demo.

5. Go to the ImageSender app and click the Images button.

6. Select an image from the list and use the mouse cursor to draw some lines on the image.

Stomp Image Share ImageSender

7. Click Send Image.

8. Go to the ImageReceiver app and you should see the image that you sent.

Stomp Image Share ImageSender

Ok, back to the code. When you clicked the Send Image button the sendImage method was called,

private function sendImage():void
{
    var image: ByteArray = ImageSnapshot.captureImage(canvas).data;
    stomp.send(destination, image);
}

In this method we use the ImageCapture class (FYI: this class is only available in Flex 3) to capture the image data from that canvas that contains our image and store it in a ByteArray. We then call send on the stomp client to send this data to the “/queue/images” destination.

RabbitMQ receives this message and sends it along to any consumer that are subscribed to this destination, including our ImageReceiver app.

When the stomp client in the ImageReceiver receives the message it fires a message event and calls the handleMessage method.

private function handleMessages(event : MessageEvent) : void
{
    var bd: BitmapData = new BitmapData(canvas.width, canvas.height);
    var loader : flash.display.Loader = new flash.display.Loader();
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onBytesLoaded);
    loader.loadBytes(event.message.body);
    function onBytesLoaded (event : Event) : void
    {
        var content : DisplayObject = LoaderInfo( event.target ).content;
        bd.draw( content );
        canvas.graphics.beginBitmapFill(bd);
        canvas.graphics.drawRect(0,0, canvas.width, canvas.height);
        canvas.graphics.endFill();
    }
}

This method grabs the body of the message (which is the ByteArray containing the image data) and draws it on to a canvas.

That’s it. As always, let me know if you have any questions. And if you encounter any bugs that appear to be in the as3-stomp client, please submit a report here.