Access Keys:
Skip to content (Access Key - 0)
WELCOME TO KAAZING.ORG LOGIN | REGISTER
Kaazing.com | FAQ | Jobs | Forum | Wiki
 

This tutorial is also packaged with the Kaazing Gateway demo bundle, which is available here

How to Create an XMPP-Driven Application in JavaScript

Kaazing Gateway 8.12 (Battlestar) Release
Technologies used: HTML, JavaScript, XMPP, and Kaazing Gateway

February 2009

Contents

Introduction

There are several innovations within the HTML 5 specification that will forever change the direction of the Web. Two of these innovations in particular--Web sockets and Server-sent events-- revolutionize the way Web applications are going to be architected, developed, and deployed. Until recently, bi‑directional browser communication has been an elusive goal of the Web community. However, with updates to the HTML 5 specification, developers can now use a full-duplex communications channel that operates over a single socket.

HTML 5's WebSocket interface enables communication from the browser to any TCP-based back-end service (for example, JMS, JMX, IMAP, Jabber, and so on). For example, it is now possible to avoid convoluted architectures by simply channeling certain protocols to the browser over HTTP and Web applications can now be deployed without the need for a traditional Web application server.

Kaazing Gateway delivers a WebSocket server that enables full-duplex communication from the browser to any TCP-based back-end service. Kaazing Gateway is the first solution that understands the WebSocket protocol and provides support for all major enterprise protocols (for example, Stomp, JMS, IMAP, JDBC, Jabber, and so on). Before you start, let's discuss XMPP in a bit more detail.

Overview of XMPP

XMPP (Extensible Messaging and Presence Protocol) is an open XML technology for presence and real-time communication, developed by the Jabber open-source community in 1999. XMPP was formalized by the IETF (Internet Engineering Task Force) between 2002 and 2004 and the protocol continues to be extended through the XMPP Standards Foundation.

XMPP consists of XML streams that enable any two entities on the Internet to exchange messages, presence, and other structured information. Chat and presence are obvious candidates for real-time communication. Examples of chat solutions that use XMPP today are Google Talk and Apple iChat. For more information about XMPP, see http://www.xmpp.org/xsf.

Unlike Stomp, XMPP messages are not sent in frames, but in XML streams that must be parsed carefully. The following list of commands are some of the standard XMPP commands, but there are many other extensions, see http://www.xmpp.org/extensions/.

  • Connect and disconnect
  • Register
  • Check roster
  • Send messages
  • Set status
  • Communicate presence

Example XMPP Communication

The following is an example of XMPP communication from the client to the server. In this case, the server can be a server or another client.

First, a stream is initialized between client and server:

<?xml version='1.0'?>
  <stream:stream
  to='example.com'
  xmlns='jabber:client'
  xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>

The server's response will look something like this:

<?xml version='1.0'?>
  <stream:stream
  from='example.com'
  id='someid'
  xmlns='jabber:client'
  xmlns:stream='http://etherx.jabber.org/streams'
  version='1.0'>

Once the stream is initialized, encryption, authentication, and resource binding takes place so the client send messages to the server. After that, the client can send a chat message like this:

<message from='rocky@example.com'
 to='sean@example.com'
 xml:lang='en'>
 <body>Hi Sean</body>
</message>

The chat message response looks like this:

<message from='sean@example.com'
 to='rocky@example.com'
 xml:lang='en'>
 <body>Hi Rocky!</body>
</message>

WebSocket and XMPP

WebSocket enables direct communication from the browser to an XMPP server. Kaazing Gateway provides an XMPPClient client library, which radically simplifies the application design and eliminates the need for using convoluted server- and client-side architectures to map server-side protocols to the browser over HTTP. Web developers can use the browser’s native JavaScript support and code directly against the back-end services without the need for custom Servlets or server-side programming.

The XmppClient JavaScript client library allows developers to take advantage of the many XMPP features, making JavaScript a first-class citizen in XMPP messaging systems. The XmppClient JavaScript library is layered on top of WebSocket, because XMPP is a text-based protocol. Because the implementation is layered on top of the WebSocket and ServerSentEvents Client Libraries, Kaazing Gateway provides persistence and reliability by extending the message receipt acknowledgment guarantee all the way to the browser.

Creating an XMPP-Driven Application in JavaScript

Before we start, let's take a look at the finished chat Web application that you will build in this tutorial. The following image shows the chat application (in the browser) communicating with a desktop chat client (Spark):

Chat app in action

Setting Up the Environment

Before you start building the XMPP-driven application, you must download, install, and run the Kaazing Gateway demo bundle as described in the Getting Started Guide. You will also need your favorite IDE.

Starter Files

Starter files are located in the $KAAZING_HOME/kaazing-gateway-demos-8.12/web/tutorials/xmpp-javascript directory of the Kaazing Gateway demo bundle. These files provide a starting point to avoid having to build everything from scratch.

Kaazing Gateway Server

Start the Kaazing Gateway Server by performing the following steps:

  1. Navigate to $KAAZING_HOME/kaazing-gateway-demos-8.12/bin folder and run gateway.start or gateway.start.bat.
  2. Verify that the Kaazing Gateway Server is working by opening a browser and navigating to http://localhost:8000/documentation/index.html (The home page should display).

Openfire XMPP Server

Install and run the Openfire XMPP server by performing the following steps:

  1. Download the Openfire XMPP server (version 3.6.x) from http://www.igniterealtime.org/projects/openfire.
  2. Install Openfire in the directory $KAAZING_HOME/openfire-3.6.0a/bin by running the Openfire executable file and accepting the default settings.
  3. Run openfire. The Openfire console displays as shown in the following image:Openfire XMPP server started
  4. Click Launch Admin to launch the admin console in a browser.
  5. Perform the initial setup steps in the Admin Console. For testing purposes, you can use the Embedded Database and Default profile settings.

Next, create two sample users (sean and rocky) and a sample group (friends) by performing the following steps:

  1. Login to the Openfire Admin Console as the administrator
  2. On the Admin Server Information page, click the Users/Groups tab
  3. On the Users subtab, click Create New User and add two new users: sean and rocky.
  4. Click the Groups subtab and click Create a New Group
  5. Enter friends as the Group Name and click Create Group.
  6. On the Edit Group page, in the Contact List (Roster) Sharing section, click Enable contact list group sharing and enter friends as the contact list group name.
  7. On the Edit Group page, in the Members of This Group section, add the previously defined users using their JID (Jabber ID) and click Add.

Finally, edit the rosters for the users you just created so that they are preconfigured buddies. To do this, perform the following steps:

  1. In the Openfire Admin Console, click the Users subtab and select one of your sample users, for example sean.
  2. Click Roster and click Add New Item.
  3. Enter rocky as the JID and friends for Groups and click Save.
  4. Edit the roster item settings by adding friends to Groups and setting Subscription to Both.
  5. Perform the same roster setup steps for the other user (sean).

You should now be able to login to Openfire as either sean or rocky with the passwords you configured during the setup steps above. These two sample user accounts are preconfigured to be buddies, so they will show up on each other's contact lists.

Install the Spark XMPP Client

Install the Spark XMPP client by performing the following steps:

  1. Download the Spark XMPP client from http://www.igniterealtime.org/projects/spark/.
  2. Install Spark by running the spark executable file.
  3. Accept the default settings.
  4. After the installation completes, select Run Spark and click Finish.
  5. Login to Openfire with one of the preconfigured accounts: Username rocky and Server localhost as shown in the following image:

    xmpp tutorial

  6. The Spark client connects to the Openfire server, and displays the (preconfigured Openfire) member (sean) in the friends group as offline as shown in the following image:

Spark client, logged in

Creating the XMPP-Driven Application

  1. Navigate to $KAAZING_HOME/kaazing-gateway-demos-8.12/web/tutorials/xmpp-javascript/
  2. Open the chat.html file in your preferred editor. The chat.html file is a simple HTML file. It contains a few TODO sections. This is where you will be adding extra code.
  3. Make a backup copy of the file before you make any changes.
  4. First, let's add a reference to WebSocket.js, the JavaScript library that allows us to open a socket and fully leverage bi-directional communication for all browsers. The WebSocket.js library will auto-detect any native browser support for WebSocket and Server-sent events (SSE). If the browser does not support WebSocket and SSE the library will automatically fall back to Kaazing's client-side emulation of the standard.

Replace:

<script src="TODO 1"></script>

With:

<script src="/html5/WebSocket.js"></script>

  1. Next, you must add support for XMPP. This is an API-specific JavaScript implementation of XMPP provided by Kaazing Gateway.

Replace:

<script src="TODO 2"></script>

With:

<script src="/protocol/XmppClient.js"></script>

  1. Next, add some variables..

Replace:

// <TODO 3>

With:

var client;
var contactList = [];

// hard-coded reference to the WebSocket server (for simplicity)
var url = "ws://localhost:8002/jabber";

// hard-coded value of the "resource" (for simplicity)
var resource = 'spark';

// name of the remote server, derived from the roster list
var chatserver;

// Add a logging message to the window
var log = function(s) {
  var output = document.getElementById('console');
  output.innerHTML = "<div class='line'>" + s + "</div>" +   output.innerHTML;
}
// Set the status and availability of this user
var gui_setStatus = function() {
  var s = document.getElementById('status').value;
  var a = document.getElementById('availability').value.toLowerCase();
  client.setStatus(s, a);
}

// Utility method for escaping out XML characters
var gui_xescape = function(s) {
  return s.replace("&", "&amp;", "g")
  .replace("<", "&lt;", "g")
  .replace(">", "&gt;", "g")
}

  1. Next, add a roster callback function.

Replace:

// <TODO 4>

With:

//Register a callback for receiving the roster, then fetch it
var gui_getRoster = function() {
  var rosterCallback = function(roster) {
    contactList = roster;
    gui_updateRoster();
  }
  client.getRoster(rosterCallback);
}

  1. Next, add code to update the roster. The code scans the message and grabs the host name out of the sender string (for example, it extracts the host name “example.com” out of rocky@example.com/spark).

Replace:

// <TODO 5>

With:

// update the roster list with incoming contacts
var gui_updateRoster = function() {
  var r = document.getElementById("roster");
  var s = "<h4 class=line>Contact List</h4>";
  var entity;
  
  for (var i=0; i<contactList.length; i++) {
    entity = contactList[i];
    var shortName = entity.jid.split('@')[0];
    if (chatserver == null) {
      chatserver = entity.jid.split('@')[1].split('/')[0];
    }
  
    s += "<div class=entity>" + shortName
           + (entity.status ? "<div   class=status>"
           + entity.status +"</div>": "")
           + (entity.show ? "<div   class=show>"
           + entity.show +"</div>" : "") + "</div>";
    }
    r.innerHTML = s;
}

  1. Next, add a function to format the message text. In this case, the code scans the message and grabs the sender's name out of the sender string (for example, it extracts the user name “rocky” out of rocky@kaazing.com/spark) and then formats the output string using a class defined in the associated stylesheet to give the sender and buddy different colors in the message console.

Replace:

// <TODO 6>

With:

// format an incoming message for display in the UI
// c is the sender class
var gui_format_msg = function(sender, body, c) {
  sender = sender.split('@')[0];
    return "<b class=" + c + ">" + sender + ": </b>"
             + gui_xescape(body);
}

  1. Next, add a send function to send messages to contacts.

Replace:

// <TODO 7>

With:

// Send a message to a chat user
var gui_send = function() {
  var j = document.getElementById('recipient').value;
  
  // restore the full name of the recipient
  j += '@' + chatserver + '/' + resource;
  
  // send the message in the body element
  var b = document.getElementById('body').value;
  client.sendMessage(j, b);
  
  var u = document.getElementById('username').value;
  log(gui_format_msg(u, b, "me"));
}

  1. Next, add an authentication function that challenges the user to log in.

Replace:

// <TODO 8>

With:

// Send in the authentication credentials
var gui_auth = function() {
  var u = document.getElementById('username').value;
  var p = document.getElementById('password').value;
  credentials = {};
  credentials.password = p;
  
  // add localhost to the username to get the server
  // identification correct
  credentials.username = u + '@localhost';
  
  client.authenticate(credentials);
}

  1. Next, add additional functions for each of the server methods.

Replace:

// <TODO 9>

With:

var gui_connect = function() {
client = new XmppClient();

// Once connected, start authentication
client.onopen = function() {
  log("<span style='font-style:italic'>Connected to server.</span>");
  gui_auth();
}

// Once authenticated, bind to the correct resource,
// get the roster of buddies, and set my status
client.onauthenticated = function() {
  client.bind(resource);
  gui_getRoster();
  gui_setStatus();
}

client.onclosed = function() {
  log("<span style='font-style:italic'>Disconnected from server.</span>");
}

// Got a message from the server... display it!
client.onmessage = function(msg) {
  log(gui_format_msg(msg.from, msg.body, "them"));
}

client.onerror = function(e) {
  log("<span style='color:red'>" + e + "</span>");
}

client.onpresence = function(p) {
  var rosterName = p.from.slice(0, p.from.indexOf("/"));
  for (var i=0; i<contactList.length; i++) {
    if (contactList[i].jid === rosterName) {
      contactList[i].status = p.status;
      contactList[i].show = p.show;
    }
    gui_updateRoster();
  }
}

  1. Finally add the connect function.

Replace:

// <TODO 10>

With:

// Now, connect to the chat server
client.connect(url, "localhost")

  1. Save the file chat.html.

Congratulations! You just built your first JavaScript XMPP application.

Running the JavaScript XMPP Client

To test your new XMPP application, perform the following steps:

  1. Open a browser and navigate to http://[localhost:port]/tutorials/xmpp-javascript/chat.html. For example, http://localhost:8000/tutorials/xmpp-javascript/chat.html.
  2. Log in as sean (all lower case) with password welcome1.
  3. Send a message to rocky (the user that is already logged in through the Spark desktop XMPP client).
  4. Verify that the chat client is working by sending messages back and forth between the Web interface (chat.html) and the Spark desktop XMPP client as shown in the following image.

xmpp web client in action

Adaptavist Theme Builder (3.2.1) Powered by Atlassian Confluence 2.9, the Enterprise Wiki.
Free theme builder license