Web Messaging with RabbitMQ-Web-Stomp and SockJS

5.00 avg. rating (96% score) - 4 votes

In this article, I will discuss sending messages from server to web browser using RabbitMQ-Web-Stomp as the backend, and a simple JavaScript library to handle the web browser side. SockJS is used as the browser WebSockets library. This setup enables you to directly push messages in realtime from the RabbitMQ message broker to the web client. This makes it possible to deliver status updates to multiple web clients directly from the message broker. No need for special application server software in the middle.

The reverse is also possible. You can push messages from web browsers directly into the RabbitMQ routing system. This article, though, will discuss the former case, from server to client. The infrastructure required for the latter case is the same, with nothing extra needed.

What’s Needed

RabbitMQ is a piece of server software which implements the AMQP messaging standard. Simply put, it maintains a number of queues for holding incoming messages, and enables other software to publish messages to those queues, and fetch messages from the queues. There are API libraries for all major programming languages, including C, Python, Java, Ruby, PHP and, of course, Erlang, because RabbitMQ itself is written in it.

AMQP is an open standard for messaging middleware. In theory, AMQP products from various vendors should be compatible. AMQP is a binary line protocol, which makes it fast, but unsuitable for web apps.

STOMP is the Simple (or Streaming) Text Orientated Messaging Protocol. The RabbitMQ-Web-Stomp plugin can deliver messages to/from web clients using Stomp.

The Stomp over Web Socket library allows running STOMP streams over web sockets.

SockJS is a WebSocket emulation library which gives a consistent API on all browser platforms, including some older ones which have partial or vendor-specific support. Native web sockets are used if the browser supports them.

RabbitMQ Installation

Here’s the RabbitMQ download page. The stuff discussed here has been tested with the package version 3.0.2 on Ubuntu, which is not yet in the official repositories.

After installation, you can use the rabbitmqctl command to command the server. It will require root privileges.

Web Management Plugin and the rabbitmqadmin script

After installing the package, enable the management plugin:

And restart:

The management plugin provides a web interface for configuring the server. By default it runs at port 15762 (eg. http://localhost:15672/).

The default username is “guest” and the password is “guest”. You should obviously change these. It can be done using the web admin interface.

You can download the rabbitmqadmin Python script from http://localhost:15672/cli/ . You can control RabbitMQ with this script without root privileges, if you provide a username and password either on the command line or in ~/.rabbitmqadmin.conf (run “rabbitmqdamin help configuration” for instructions).

Writing Programs with AMQP

Here are some very nice tutorials on how to write programs for RabbitMQ:

http://www.rabbitmq.com/getstarted.html

We will be using the same pattern as example number 5. But we will use a web client as the consumer.

Messaging in a Web Browser using RabbitMQ-Web-Stomp

The RabbitMQ-Web-Stomp plugin allows web browsers to do messaging using SockJS. This will enable a web browser to keep a connection with the message broker, and receive messages as soon as they appear in the queue. A callback function will be fired every time upon the receival of a message.

Install the Web Stomp plugin:

Restart RabbitMQ. You should now get a hello page in port 15674 (note the different port number), under /stomp (http://localhost:15674/stomp).

(If you install the rabbitmq_web_stomp_examples plugin as well, you can find examples at http://localhost:15670/. You can download the stomp.js file used in my example from http://localhost:15670/web-stomp-examples/stomp.js)

A simple example

To demonstrate a simple use case, let’s write two programs. The first one is a Python program for publishing messages, and the other one is a web app for reading those messages.

The publisher in Python

This one will use the Pika AMQP client library (sudo apt-get install python-pika, or pip install pika).

Let’s call this app publisher.py:

That will simply prompt the user for a line of text, and publish it to the amq.topic exchange of the default virtualhost “/”, using routing key mymessages.

Run the script with:

The Consumer in JavaScript

Here’s an example app which can read messages using SockJS. Let’s call it listener-app.html.

Here’s listener-app.js:

You will also need the sockjs-0.3.js and stomp.js files. I will include them in this post.

Test It

If you now point your browser to http://localhost/rabbitmq-web-stomp-example/listener-app.html, you should see a text saying “Connected to RabbitMQ-Web-Stomp”.

Now, write a message in the terminal window running the publish.py Python script. It should appear in the browser window immediately.

You can open multiple browser windows, and they should all get the message. You can also open multiple publisher scripts at once.

At this point, you should see some connections, channels and queues appear in the RabbitMQ web management interface. There should be one of each for every browser window and running Python script.

Useful links:

Here’s the example, unpack it under you web server’s document root:

5 thoughts on “Web Messaging with RabbitMQ-Web-Stomp and SockJS”

  1. I’ve been trying to use this example, and I wasn’t getting javascript to connect, I finally did it using Websocket instead of SockJs. So if there is someone wondering by with same problem, here is what I did:

    Erase this lines:
    2 |Stomp.WebSocketClass = SockJS;
    40 | var client = Stomp.client(mq_url);

    Add this in the beggining:
    var ws = new WebSocket(‘ws://127.0.0.1:15674/ws’);
    var client = Stomp.over(ws);

    And it should work!

  2. excellent !! many many thanks!! i’m using a different vhost (i call it “ursa”) and a publish/suscribe pattern with an exchange of type fanout called “status”, the code is the next:

    var Stomp = window.Stomp; // i’m using requirejs, but can’t import Stomp
    var mq_username = “another_user_name”;
    var mq_password = “my_pass”;
    var mq_vhost = “ursa”;
    var mq_queue = “/exchange/status”;
    var ws = new WebSocket(‘ws://’+location.host+’:15674/ws’);
    var client = Stomp.over(ws);

Leave a Reply