Example: Implementing a Simple Pub/Sub Client
The Universal Messaging JavaScript API makes it easy to implement JavaScript Publish & Subscribe clients. These clients can communicate using Comet techniques (both streaming and long-polling), as well as using Web Sockets when supported by the client browser.
The code shown below is a fully functioning example of such a client, containing JavaScript connection, publishing and subscription logic and an HTML UI.
In some circumstances you may wish to serve your web application from another web server (e.g. Apache). Universal Messaging supports this also but due to security restrictions within browsers it requires that your application is organised differently (see
Serving From Another Webserver for related information).
<?xml version="1.0" encoding="UTF-8"?>
<!doctype html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script language="JavaScript" src="lib/nirvana.js"></script>
<script>
window.onload = isLoaded;
var demoChannel = null;
var demoUsername = "anonymous";
function isLoaded() {
/********************************************************************
* As soon as the page loads, we should create our Universal Messaging session.
* This method is invoked by the body tag's "onload" event.
* We use the pre-instantiated object NirvanaSession and define what
* we want to happen once the session is initialised by implementing
* a callback function, NirvanaSession.onInit:
*********************************************************************/
NirvanaSession.onInit = function(nirvanaSessionID) {
/********************************************************************
* Now that our session has initialised, we can access an automatically
* instatiated object named Nirvana, which provides access to classes
* representing events and dictionaries, such as Nirvana.nConsumeEvent
* and Nirvana.nEventProperties.
* In this demo, we shall subscribe to a channel and define what we
* want to happen when certain activities occur (such as subscribing,
* or receiving events). We do this by implementing callback logic,
* either with anonymous functions, or if preferred, with named functions:
*********************************************************************/
demoChannel = new NirvanaChannel("/showcase/simplechatroom");
demoChannel.onSubscribe =
function(cname, msg) { window.status = "Subscribed to " + cname; }
demoChannel.onData = demoEventHandler;
demoChannel.onPublish = updateUserInputUI;
demoChannel.subscribe();
}
NirvanaSession.onConnect = function() { window.status = "Connected"; }
NirvanaSession.onDisconnect =
function() { window.status = "Disconnected. Reconnecting..."; }
/********************************************************************
* Now that we have defined all that should happen when our session is
* up and running, let us *start* it. We pass in a configuration object
* to specify properties about this connection.
*********************************************************************/
NirvanaSession.start({
domain : "my-channels.com", // as we are going to use
// realm showcase.um.softwareag.com
realmHosts : [ "showcase" ], // an array of realm hostnames
// - in this case just the one
applicationName : "SimpleChatRoom",
sessionName : "JavaScriptDemoSession",
username : demoUsername // in a typical app, this would be
// an authenticated username
});
}
function demoEventHandler(event) {
/********************************************************************
* This method automatically gets invoked every time we receive an
* event from the demoChannel (since this is the method we specified
* as the demoChannel.onData event handler. Note that the
* event object will be passed to this method as a parameter. We can
* then get the event's data "dictionary", and read the value of any
* of its keys. In this demo, we use this data to update a textarea.
*********************************************************************/
var dictionary = event.getDictionary();
var newData =
dictionary.get('publisher') + ": " + dictionary.get('message') + "\n"
var oldData = document.getElementById("outputTextarea").value;
document.getElementById("outputTextarea").value = newData + oldData;
}
function publishMessage() {
/********************************************************************
* This method is an example of how to publish events to our channel.
* We first create an nConsumeEvent, and assign it an nEventProperties
* object (which represents a data "dictionary" - essentially a hash of
* key-value pairs). Finally, we call the channel's publish method,
* It is good practice to wrap code like this in try/catch blocks.
*********************************************************************/
if (document.getElementById("demoInput").value == "") return;
try {
var evt = new Nirvana.nConsumeEvent();
var dictionary = new Nirvana.nEventProperties();
dictionary.put("publisher", demoUsername);
dictionary.put("message", document.getElementById("demoInput").value);
evt.setDictionary(dictionary);
demoChannel.publish(evt);
} catch (error) {
alert("Error: " + error.message);
}
}
function updateUserInputUI() {
/********************************************************************
* This method automatically gets invoked after we successfully
* publish to testChannel (since this is the method we specified
* as the handler for testChannel.onPublish.
* A typical implementation of such a function would re-enable UI components
* that might have been disabled while publishing took place.
*********************************************************************/
if(!initialiasedASession)
alert("We did not get a session to Universal Messaging");
document.getElementById("demoInput").value = "";
window.status = "Published";
}
</script>
<title>Universal Messaging JavaScript Tutorial Application:
Simple Chat Room</title>
</head>
<body onload="isLoaded()">
<h1>Universal Messaging JavaScript Tutorial Application:
Simple Chat Room</h1>
<form onsubmit="publishMessage(); return false;">
<h2>Input</h2>
<input type="text" id="demoInput"/>
<input type="submit" value="Publish">
<h2>Output</h2>
<textarea id="outputTextarea" rows="10" cols="70"></textarea>
</form>
</body>
</html>