Using STOMP JS

The STOMP Broker

Ensure that your STOMP broker supports STOMP over WebSockets. Some messaging brokers supports it out of the box while some may need special configuration or activating plugins. See STOMP Brokers for a non authoritative list.

Include STOMP.js

In Web Browser

In NodeJS

Create a STOMP client

STOMP JavaScript clients will communicate to a STOMP server using a ws:// URL.

To create a STOMP client JavaScript object, you need to call Stomp.client(url) with the URL corresponding to the server's WebSocket endpoint:

  var url = "ws://localhost:15674/ws";
  var client = Stomp.client(url);

The Stomp.client(url, protocols) can also be used to override the default subprotocols provided by the library: ['v10.stomp', 'v11.stomp', 'v12.stomp'] (for STOMP 1.0, 1.1, & 1.2 specifications). This second argument can either be a single string or an array of strings to specify multiple subprotocols.

Notes:

Connection to the server

Once a STOMP client is created, it must call its connect() method to effectively connect and authenticate to the STOMP server. Usually the STOMP borker needs two arguments, login and passcode corresponding to the user credentials. As per STOMP 1.2 host is mandatory, however many STOMP brokers do not insist on this.

Behind the scene, the client will open a connection using a WebSocket and send a CONNECT frame.

The connection is done asynchronously: you have no guarantee to be effectively connected when the call to connect returns. To be notified of the connection, you need to pass a connect_callback function to the connect() method:

  var connect_callback = function() {
    // called back after the client is connected and authenticated to the STOMP server
  };

But what happens if the connection fails? the connect() method accepts an optional error_callback argument which will be called if the client is not able to connect to the server. The callback will be called with a single argument, an error object corresponding to STOMP ERROR frame:

  var error_callback = function(error) {
    // display the error's message header:
    alert(error.headers.message);
  };

The connect() method accepts different number of arguments to provide a simple API to use in most cases:

  client.connect(login, passcode, connectCallback);
  client.connect(login, passcode, connectCallback, errorCallback);
  client.connect(login, passcode, connectCallback, errorCallback, closeEventCallback);
  client.connect(login, passcode, connectCallback, errorCallback, closeEventCallback, host);

where login, passcode and host are strings. connectCallback and errorCallback is a function which will receive a Frame as argument and closeEventCallback is a function which will receive a CloseEvent

The connect() method also accepts two other variants if you need to pass additional headers:

  client.connect(headers, connectCallback);
  client.connect(headers, connectCallback, errorCallback);
  client.connect(headers, connectCallback, errorCallback, closeEventCallback);

where header is a map. connectCallback and errorCallback is a function which will receive a Frame as argument and closeEventCallback is a function which will receive a CloseEvent

Please note that if you use these forms, you will typically add login, passcode (and host) headers yourself:

    var headers = {
      login: 'mylogin',
      passcode: 'mypasscode',
      // additional header
      'client-id': 'my-client-id'
    };
    client.connect(headers, connectCallback);

To disconnect a client from the server, you can call its disconnect() method. The disconnection is asynchronous: to be notified when the disconnection is effective, the disconnect method takes an optional callback argument.

  client.disconnect(function() {
    alert("See you next time!");
  });

When a client is disconnected, it can no longer send or receive messages.

Heart-beating

If the STOMP broker accepts STOMP 1.1 or higher frames, heart-beating is enabled by default.

The client object has a heartbeat field which can be used to configure heart-beating by changing its incoming and outgoing integer fields (default value for both is 10,000ms). These can be disabled by setting to 0.

    client.heartbeat.outgoing = 20000; // client will send heartbeats every 20000ms
    client.heartbeat.incoming = 0;     // client does not want to receive heartbeats
                                       // from the server

Auto Reconnect

The client supports automatic reconnecting in case of a connection failure. It is controlled by a field reconnect_delay. Default value is 0, which indicates auto reconnect is disabled.

  // Add the following if you need automatic reconnect (delay is in milli seconds)
  client.reconnect_delay = 5000;

Send messages

When the client is connected to the server, it can send STOMP messages using the send() method. The method takes a mandatory destination argument corresponding to the STOMP destination. It also takes two optional arguments: headers, a JavaScript object containing additional message headers and body, a String.

  client.send("/queue/test", {priority: 9}, "Hello, STOMP");

The client will send a STOMP SEND frame to /queue/test destination with a header priority set to 9 and a body Hello, STOMP.

If you want to send a message with a body, you must also pass the headers argument. If you have no headers to pass, use an empty JavaScript literal {}:

  client.send(destination, {}, body);

Subscribe and receive messages

To receive messages in the browser, the STOMP client must first subscribe to a destination.

You can use the subscribe() method to subscribe to a destination. The method takes 2 mandatory arguments: destination, a String corresponding to the destination and callback, a function with one message argument and an optional argument headers, a JavaScript object for additional headers.

  var subscription = client.subscribe("/queue/test", callback);

The subscribe() methods returns a JavaScript object with one attribute, id, that correspond to the client subscription ID and one method unsubscribe() that can be used later on to unsubscribe the client from this destination.

By default, the library will generate an unique ID if there is none provided in the headers. To use your own ID, pass it using the headers argument:

  var mysubid = 'my-subscription-id-001';
  var subscription = client.subscribe(destination, callback, { id: mysubid });

The client will send a STOMP SUBSCRIBE frame to the server and register the callback. Every time the server sends a message to the client, the client will in turn call the callback with a STOMP Frame object corresponding to the message:

  callback = function(message) {
    // called when the client receives a STOMP message from the server
    if (message.body) {
      alert("got message with body " + message.body)
    } else {
      alert("got empty message");
    }
  };

The subscribe() method takes an optional headers argument to specify additional headers when subscribing to a destination:

  var headers = {ack: 'client', 'selector': "location = 'Europe'"};
  client.subscribe("/queue/test", message_callback, headers);

The client specifies that it will handle the message acknowledgement and is interested to receive only messages matching the selector location = 'Europe'.

If you want to subscribe the client to multiple destinations, you can use the same callback to receive all the messages:

  onmessage = function(message) {
    // called every time the client receives a message
  };

  var sub1 = client.subscribe("queue/test", onmessage);
  var sub2 = client.subscribe("queue/another", onmessage);

To stop receiving messages, the client can use the unsubscribe() method on the object returned by the subscribe() method.

  var subscription = client.subscribe("queue/test", onmessage);

  // ... use the subscription ...

  subscription.unsubscribe();

JSON support

The body of a STOMP message must be a String. If you want to send and receive JSON objects, you can use JSON.stringify() and JSON.parse() to transform the JSON object to a String and vice versa.

  var quote = {symbol: 'APPL', value: 195.46};
  client.send("/topic/stocks", {}, JSON.stringify(quote));

  client.subcribe("/topic/stocks", function(message) {
    var quote = JSON.parse(message.body);
    alert(quote.symbol + " is at " + quote.value);
  });

Acknowledgment

By default, STOMP messages will be automatically acknowledged by the server before the message is delivered to the client.

The client can choose instead to handle message acknowledgement by subscribing to a destination and specify a ack header set to client or client-individual.

In that case, the client must use the message.ack() method to inform the server that it has acknowledge the message. This method sends an ACK Frame to the broker.

  var subscription = client.subscribe("/queue/test",
    function(message) {
      // do something with the message
      // ...
      // and acknowledge it
      message.ack();
    },
    {ack: 'client'}
  );

The ack() method accepts a headers argument for additional headers to acknowledge the message. For example, it is possible to acknowledge a message as part of a transaction and ask for a receipt when the ACK STOMP frame has effectively be processed by the broker:

  var tx = client.begin();
  message.ack({ transaction: tx.id, receipt: 'my-receipt' });
  tx.commit();

The message.nack() method can also be used to inform STOMP 1.1 or higher brokers that the client did not consume the message using a NACK Frame. It takes the same arguments than the ack() method.

Transactions

Messages can be sent and acknowledged in a transaction.

A transaction is started by the client using its begin() method which takes an optional transaction_id, a String which uniquely identifies the transaction. If no transaction_id is passed, the library will generate one automatically.

This methods returns a JavaScript object with an id attribute corresponding to the transaction ID and two methods:

The client can then send and/or acknowledge messages in the transaction by specifying a transaction set with the transaction id.

  // start the transaction
  var tx = client.begin();
  // send the message in a transaction
  client.send("/queue/test", {transaction: tx.id}, "message in a transaction");
  // commit the transaction to effectively send the message
  tx.commit();

If you forget to add the transaction header when calling send() the message will not be part of the transaction and will be sent directly without waiting for the completion of the transaction.

  var txid = "unique_transaction_identifier";
  // start the transaction
  var tx = client.begin();
  // oops! send the message outside the transaction
  client.send("/queue/test", {}, "I thought I was in a transaction!");
  tx.abort(); // Too late! the message has been sent

Debug

There are few tests in the code and it is helpful to see what is sent and received from the library to debug application.

The client can set its debug property to a function with takes a String argument to see all the debug statements of the library:

  client.debug = function(str) {
    // append the debug log to a #debug div somewhere in the page using JQuery:
    $("#debug").append(str + "\n");
  };

By default, the debug messages are logged in the browser window's console.

On a busy system the logs can be overwhelming, to disable logging, set it to an empty function:

  client.debug = function(str) {};

    Quickly fuzzy find classes, mixins, methods, file:

    Control the navigation frame:

    You can focus and blur the search input: