Feb 18

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.

16 Responses to “Integrating Flex and RabbitMQ using STOMP”

  1. Ben Hood says:

    Hi Derek,

    Great article! I really like the simplicity of the Stomp approach in comparison to full blown AMQP. Whilst rewriting the AS3 client for AMQP, I tried to come up with an API that exposes AMQP in the simplest possible way. You can see the first version here:http://hopper.squarespace.com/blog/2008/3/24/as3-amqp-client-first-cut.html

    HTH,

    Ben

  2. links for 2008-07-01 « Brent Sordyl’s Blog says:

    [...] Integrating Flex and RabbitMQ using STOMP 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 (tags: flex rabbitmq as3 stomp) [...]

  3. Everett says:

    Perhaps this is not the best place to ask, but I will try anyway.

    When I try a demo application which just sends a message to a queue (on ActiveMQ in my case), nothing happens. Is there a way to debug what is happening in your STOMP AS3 code?

    Thanks,

    Everett

  4. Derek Wischusen says:

    Hi Everett,

    You could download the source and then step through your app with a debugger. The source is available here: http://code.google.com/p/as3-stomp/

    What client are you using to view the messages? Based on your description of the issue my best guess is that you should try using the sendTextMessage() method. It sends the message out as a text message rather than a byte message. Not all clients work with the byte message format, so this may solve the issue for you.

    Derek

  5. Joe says:

    Hi, I’d like to try this out, but the files and folder mentioned in the post,

    ImageSender.html,
    ImageReceiver.html,
    bin-debug folder

    Do not appear to be part of the present downloadable .zip file. I also am not familiar with .mxml files and am not sure what I might do with them instead…

  6. Bob says:

    There is no longer any ‘bin-debug’ folder in the project download specified in the post.

  7. Bob says:

    Sorry about my above comment. I am totally new to flash, and did not realize that it was necessary to open the project in flex builder before the bin-debug folder would appear. Please disregard my previous comment.

  8. Hans says:

    Hi Derek,

    Would this work with ActiveMQ instead of RabbitMQ? Still not sure about the differences between the two when it comes to Stomp and Flex.

    Kind regards,

    Hans.

  9. Derek Wischusen says:

    Hans,

    No difference at all when it comes to STOMP and Flex. To use ActiveMQ it’s as simple as booting up ActiveMQ instead of RabbitMQ. There are headers that are specific to RabbitMQ and ActiveMQ, but this example does not make use of them.

  10. Rich Apps Consulting says:

    Hi, i’d like to thank you for such an intresting and helpful article. Great help for Begginers.

  11. Mohith says:

    The sample works – thanks for the intro. However when I try this in a flex app which is downloaded from
    a URL say http://localhost:3000 and if this swf tries to connect using stomp then I get an exception in
    the flex console as follows

    ********************************
    Warning: Timeout on xmlsocket://localhost:61613 (at 3 seconds) while waiting for socket policy file. This should not cause any problems, but see http://www.adobe.com/go/strict_policy_files for an explanation.

    Error: SWF from http://localhost:3001/bin/nanoMetric.swf may not connect to a socket in its own domain without a policy file. See http://www.adobe.com/go/strict_policy_files to fix this problem.

    *** Security Sandbox Violation ***
    Connection to localhost:61613 halted – not permitted from http://localhost:3001/bin/nanoMetric.swf
    Error #2044: Unhandled securityError:. text=Error #2048: Security sandbox violation: http://localhost:3001/bin/nanoMetric.swf cannot load data from localhost:61613.
    at org.codehaus.stomp::Stomp()[C:\Users\wischusen\Documents\FlexBuilderProjects\Stomp\org\codehaus\stomp\Stomp.as:52]
    ***************************

    Please can you comment on how to get around the security sandbox ?

    Thanks
    M

  12. stevie says:

    What is better, ActiveMQ or RabbitMQ?

  13. Ryan says:

    I’m having the same Security sandbox violation issue. It seems connecting to a different port on the same server causes the failure. I’ve been unsuccessful in finding out how to integrate a crossdomain.xml file into rabbitmq or activemq. Anyone have any clues as to how to handle this?

  14. JOsH says:

    The Sample Flex project works great. however, I would like to use the stomp.swc with my project.

    I am using the Flex 3 SDK, Flex Antasks, and ant. So I can pull in your swc, but I am not using mxml or flexbuilder. How would I attach an EventListner to stomp in an Actionscript 3 class, without using MXML? Is this just a matter of creating an instance of the stomp class and attaching an eventListener to it? I would imagin I’d need to also config the channel.

    ie
    var _stomp:Stomp = new Stomp();
    _stomp.addEventListener(MessageEvent.Message, function(event:MessageEvent):void{ trace(”event:message:” + event.message.body ) );

  15. Pedro says:

    Yes, I have the same problem, on the security violation. I am serving my app out of the ActiveMQ 5.2.0 demo/ application using Jetty on port 8161. I placed my SWF and HTML files there, which talk to the ActiveMQ on the same box, but on port 61613. The strict policy seems to apply because I get a 2048 error. However, when I use the flashpd policy server from Adobe, the problem goes away.

  16. Pedro says:

    On the previous post: Running the flashpd on port 843 requires root access on the server (it’s a Linux box) so probably that meets Adobe’s tightened standards, but it’s still a bit of an inconvenience to have the Flashpd server running at all times.

Leave a Reply