Menu

Introducing RabbitMQ-Web-Stomp

For quite a while here, at RabbitMQ headquarters, we were struggling to find a good way to expose messaging in a web browser. In the past we tried many things ranging from the old-and-famous JsonRPC plugin (which basically exposes AMQP via AJAX), to Rabbit-Socks (an attempt to create a generic protocol hub), to the management plugin (which can be used for basic things like sending and receiving messages from the browser).

Over time we've learned that the messaging on the web is very different to what we're used to. None of our attempts really addressed that, and it is likely that messaging on the web will not be a fully solved problem for some time yet.

That said, there is a simple thing RabbitMQ users keep on asking about, and although not perfect, it's far from the worst way do messaging in the browser: exposing STOMP through Websockets.

STOMP + Websockets

We're delighted to introduce a new plugin for RabbitMQ:

It is basically a bridge between RabbitMQ-STOMP plugin and a Websockets server (SockJS). Hopefully, it is a decent solution for a set of rabbit-on-the-web use cases.

What it actually does

Within RabbitMQ

RabbitMQ-Web-Stomp is a simple beast. It takes the STOMP protocol as provided by the RabbitMQ-STOMP plugin and exposes it using the SockJS server.

Wire protocol

One can connect to the SockJS endpoint from any browser using the reliable SockJS protocol. This will work even in browsers that don't support native websockets or in environments behind broken proxies that block non-http transports.

Alternatively, for users that don't need this level of sophistication, SockJS exposes a raw websockets url that can be accessed directly from a recent, websocket-capable browser.

In the browser

Within the browser, the connection to SockJS endpoint is basically a raw STOMP connection. You can send and receive normal STOMP frames.

Any decent javascript STOMP library should be able to handle that. For our examples we're using the stomp-websocket library by Jeff Mesnil and Jeff Lindsay.

We use this code in the examples:

<script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
<script src="stomp.js"></script>
<script>
   WebSocketStompMock = SockJS;

    var client = Stomp.client('http://127.0.0.1:55674/stomp');
    [...]

Installation

Rabbitmq-Web-Stomp is an experimental plugin. It's not distributed with vanilla RabbitMQ releases; you need to install it manually.

  1. You need at least Erlang R14 (more info).
  2. You need Rabbitmq-server 2.8.2 installed
  3. Grab the needed erlang plugin .ez files:
    wget \
      http://www.rabbitmq.com/releases/plugins/v2.8.2-web-stomp-preview/cowboy-0.5.0-rmq2.8.2-git4b93c2d.ez \
      http://www.rabbitmq.com/releases/plugins/v2.8.2-web-stomp-preview/sockjs-0.2.1-rmq2.8.2-gitfa1db96.ez \
      http://www.rabbitmq.com/releases/plugins/v2.8.2-web-stomp-preview/rabbitmq_web_stomp-2.8.2.ez \
    
    http://www.rabbitmq.com/releases/plugins/v2.8.2-web-stomp-preview/rabbitmq_web_stomp_examples-2.8.2.ez
  4. Next, copy them to the plugins directory. For example, on my Ubuntu box this will be:
    sudo cp *.ez /usr/lib/rabbitmq/lib/rabbitmq_server-2.8.2/plugins
    
  5. Now, you're ready to enable them using rabbitmq-plugins:
    sudo rabbitmq-plugins enable rabbitmq_web_stomp
    sudo rabbitmq-plugins enable rabbitmq_web_stomp_examples
    
  6. Restart the rabbitmq server. On ubuntu:
    sudo /etc/init.d/rabbitmq-server restart
    

As you may have noticed, we enabled two plugins:

Keep in mind, that RabbitMQ-web-stomp depends on RabbitMQ-STOMP which by default will bind to port 61613.

The usage

If you enabled RabbitMQ-web-stomp-examples plugin, you should be able to instantly run two examples prepared by us. Just open a web browser at http://127.0.0.1:55670/.

  • "echo" - shows how to use STOMP to do simple message broadcasting (source)
  • "bunny" - example of a simple collaboration canvas painting app (source)

Summary

RabbitMQ-web-stomp is quite a simple plugin, but opens wide possibilities, exposing the STOMP protocol to the browser.

Like always, feedback welcome. We're also looking for inspiration for more examples!

10 Responses to “Introducing RabbitMQ-Web-Stomp”

  1. Simon R. Says:

    That solution sounds really great! Congrats for the idea and its smart implementation.
    Under integration on my side. Last point would consist in extending an existing JS logging framework with an integrated SockJS+STOMP logs appender!
    Thank you

  2. Tetsu Says:

    I mashed up an web log viewer with log.io and fluentd + amqp plugin.

  3. Hendy Irawan Says:

    It fails on this step :

    $ sudo rabbitmq-plugins enable rabbitmq-web-stomp
    Error: The following plugins could not be found:
    rabbitmq-web-stomp

    What did I do wrong ?

    This is the plugins directory :

    $ ls -l /usr/lib/rabbitmq/lib/rabbitmqserver-2.8.2/plugins/
    total 2040
    -rw-r--r-- 1 root root 216097 2012-04-27 21:40 amqp
    client-2.8.2.ez
    -rw-r--r-- 1 root root 221600 2012-06-05 02:45 cowboy-0.5.0-rmq2.8.2-git4b93c2d.ez
    -rw-r--r-- 1 root root 99293 2012-04-27 21:40 eldap-2.8.2-git.ez
    -rw-r--r-- 1 root root 48806 2012-04-27 21:40 erlando-2.8.2.ez
    -rw-r--r-- 1 root root 213176 2012-04-27 21:40 mochiweb-1.3-rmq2.8.2-git.ez
    -rw-r--r-- 1 root root 17059 2012-04-27 21:40 rabbitmqauthbackendldap-2.8.2.ez
    -rw-r--r-- 1 root root 10584 2012-04-27 21:40 rabbitmq
    authmechanismssl-2.8.2.ez
    -rw-r--r-- 1 root root 7451 2012-04-27 21:40 rabbitmqconsistenthashexchange-2.8.2.ez
    -rw-r--r-- 1 root root 95153 2012-04-27 21:40 rabbitmq
    federation-2.8.2.ez
    -rw-r--r-- 1 root root 8222 2012-04-27 21:40 rabbitmqfederationmanagement-2.8.2.ez
    -rw-r--r-- 1 root root 2892 2012-04-27 21:40 rabbitmqjsonrpc-2.8.2.ez
    -rw-r--r-- 1 root root 67233 2012-04-27 21:40 rabbitmq
    jsonrpcchannel-2.8.2.ez
    -rw-r--r-- 1 root root 52947 2012-04-27 21:40 rabbitmq
    jsonrpcchannelexamples-2.8.2.ez
    -rw-r--r-- 1 root root 375215 2012-04-27 21:40 rabbitmqmanagement-2.8.2.ez
    -rw-r--r-- 1 root root 16561 2012-04-27 21:40 rabbitmq
    managementagent-2.8.2.ez
    -rw-r--r-- 1 root root 32469 2012-04-27 21:40 rabbitmq
    managementvisualiser-2.8.2.ez
    -rw-r--r-- 1 root root 25697 2012-04-27 21:40 rabbitmq
    mochiweb-2.8.2.ez
    -rw-r--r-- 1 root root 36521 2012-04-27 21:40 rabbitmqshovel-2.8.2.ez
    -rw-r--r-- 1 root root 13001 2012-04-27 21:40 rabbitmq
    shovelmanagement-2.8.2.ez
    -rw-r--r-- 1 root root 86842 2012-04-27 21:40 rabbitmq
    stomp-2.8.2.ez
    -rw-r--r-- 1 root root 42097 2012-04-27 21:40 rabbitmqtracing-2.8.2.ez
    -rw-r--r-- 1 root root 17849 2012-06-05 02:45 rabbitmq
    webstomp-2.8.2.ez
    -rw-r--r-- 1 root root 48201 2012-06-05 02:45 rabbitmq
    webstompexamples-2.8.2.ez
    -rw-r--r-- 1 root root 59 2012-04-27 21:40 README
    -rw-r--r-- 1 root root 44465 2012-04-27 21:40 rfc4627_jsonrpc-2.8.2-git.ez
    -rw-r--r-- 1 root root 97673 2012-06-05 02:45 sockjs-0.2.1-rmq2.8.2-gitfa1db96.ez
    -rw-r--r-- 1 root root 132332 2012-04-27 21:40 webmachine-1.7.0-rmq2.8.2-hg.ez

  4. Hendy Irawan Says:

    I found it, it should be like this:

    $ sudo rabbitmq-plugins enable rabbitmqwebstomp
    $ sudo rabbitmq-plugins enable rabbitmqwebstomp_examples

    Please update the article. Thank you :)

  5. Hendy Irawan Says:

    Thank YOU very much for this plugin !!

    It works flawlessly, even on Android 2.3 mobile browser ^_^ Loving it !!

    At first I tried Atmosphere, JMS, HornetQ, Camel, and combinations thereof...

    but this one RabbitMQ coupled with Stomp-Web's stomp.js and SockJS works wonderful :

    https://github.com/soluvas/primefaces-bootstrap/commit/cc020d8c604756bbd976caa3f37a5bfb044f23c8

    My server-side code is now very simple (just publishing/consuming RabbitMQ exchanges), and the client-side JavaScript code is also very simple (just subscribe to a bunch of Stomp destinations). Right now I'm declaring exchanges but I think a much better way for my usecase is just to use AMQP Topics so I can have dynamic routing keys. I think this will scale to a huge number of topics.

    Thank you Marek !

    P.S. Are you the Marek from SockJS fame ?

  6. Jeff Mesnil Says:

    Fiy, I have updated the stomp-websockets[1] JavaScript library and it impacts the client code.

    The WebSocketStompMock variable was a hack to be able to test the lib using a mock stomp web
    server.
    I replaced it with a variable "WebSocketClass" inside the Stomp object to use another WebSocket implementation than the one provided by the Web browser.

    This means you must now specify:

    Stomp.WebSocketClass = SockJS;
    client = Stomp.client(url);

    That makes for better encapsulated code.

    --
    jeff

    [1] https://github.com/jmesnil/stomp-websocket

  7. Sergey Says:

    Sorry, I didn't have any response in http://127.0.0.1:55670/ and http://127.0.0.1:55674/stomp, but i changed port to 155670 and 155674, and all is working. If this is not error in text write me about it.
    Thank you for a very good plagin.

  8. Nathan Says:

    Cool, downloading your Web Stomp now. It seems too easy to use. I'll report back when I get the time.

  9. TJ Says:

    It worked for me when I changed the port to 15670 instead of 55670 i.e http://127.0.0.1:15670/. Please update the tutorial.

  10. Abbas Ahmed Says:

    Hi, I am using RabbitMQ 3.1.3 and I found two thing that you guys might find useful.

    1. There seems to be a quirk in the restart operation as the web-stomp-examples plugin didn't activate until the broker was stopped and started, a simple restart didn't work.
    2. The example listens on port 15670 and not 55670 as mentioned above by TJ.