I noticed a couple different people wanting information on instant messenging with ColdFusion and then in another place instant messenging with Jabber and ColdFusion in the last couple days (for reasons beyond me) [first on cfguru, then on my blog, then on the jive software forums]. For those that care I put together a quick and ugly web-based instant messenging interface to Jabber using an open source Java library called Smack. You can download the source code at the end of this article or follow along as I describe the process.
Setup: 1) You need to download the Smack library and place the smack.jar and smackx.jar files into a directory acccesible to ColdFusion (commonly /WEB-INF/lib/). 2) You need to setup a couple Jabber accounts. You can either download, install and run your own jabber server or create a free account on jabber.org (or one of the many other public jabber servers). 3) You need to get a Jabber client (I’m using Exodus).
There are 2 (technically 3) parts to the interface. The easiest is a standard Application.cfm that creates an application that enables us to use sessions. You need sessions because you need to be able to persist the Jabber chat and connection objects across requests.
The second part is composed of 2 documents: a) the default page that presents a form for sending a message and has an iframe to hold the conversation and then b) the iframe that holds the conversation and then initializes the Jabber connection and chat objects. I’ll show the iframe first.
The iframe is split up into 2 parts: initialization and display. The first thing it does is check to see if the connection object exists in session scope:
// if no connection exists, create one
if (NOT structKeyExists(session, "connection")) {
If the connection doesn’t exist, the following block of code is run:
// create a connection to the jabber.org server
XMPPConnection = createObject("java", "org.jivesoftware.smack.XMPPConnection").init("jabber.org");
// login to the jabber server
login = XMPPConnection.login("username", "password");
// create a chat w/ another user
chat = XMPPConnection.createChat("user@domain.com");
// store the connection and chat objects in session scope
session.connection = XMPPConnection;
session.chat = chat;
// init an empty string to hold the conversation
session.conversation = "";
The block above creates a Smack XMPPConnection to the Jabber server (in this case I’m using ‘jabber.org’, but you should change this to be whatever server you have an account on). Next I call the login(username,password) method to login to the Jabber server and then I create a Smack Chat object by called the createChat() method on the connection. Because I need the chat and the connection to persist (in order to chat with someone), I store both in session scope. Finally, I create a session variable called ‘conversation’ that will store the conversation between the 2 chatting clients.
If the connection already exists in session scope, another block of code is run:
// get the connection & chat objects from the session
connection = session.connection;
chat = session.chat;
// retrieve the message using pollMessage() (which is nonblocking)
nextMessage = chat.pollMessage();
// if no message exists 'nextMessage' will be undefined (I think 'null' technicall)
if (IsDefined("nextMessage")) {
// message does exist, add it to the conversation
session.conversation = session.conversation & "<br /><strong><font color='blue'>" & chat.getParticipant() & "</font></strong> : " & nextMessage.getBody();
}
I retrieve the Smack XMPPConnection and Smack Chat objects from the session, and then call the pollMessage() method on the chat object. It’s important that I use the pollMessage() method instead of the nextMessage() method because the pollMessage method is non-blocking, it won’t wait until a message shows up from the person I’m chatting with, it returns immediately if no message exists. If the pollMessage() method returns a Smack Message object (which in Java will either return a Message or null), then I add the message to the conversation and finally display the conversation:
writeoutput("<html><head><title></title>");
writeoutput("<META HTTP-EQUIV='Refresh' CONTENT='1'>");
writeoutput("</head><body>");
writeoutput(#session.conversation#);
writeoutput("</body></html>");
You’ll notice that I’m having the iframe page refresh itself every 1 second, it would probably be better to use some JavaScript and a one pixel image to do the trick, but this works for now.
The last step is to create the page that holds the iframe and that presents the form for sending a message. The iframe is simple:
<iframe src="frame.cfm" name="chatwindow" id="chatwindow" width="800" height="500" marginwidth="5" marginheight="5"></iframe>
and then some code to handle a form post, retrieve the chat and connection objects from session scope, send the message to Jabber and then add the message to the conversation:
// if we have a form post
if (IsDefined("form.formPosted")) {
// grab the connection and chat objects from the session
connection = session.connection;
chat = session.chat;
// send the message via the chat object
chat.sendMessage(form.message);
// append the message to the conversation
session.conversation = session.conversation & "<br /><strong><font color='red'>" & connection.getUser() & "</font></strong> : " & form.message;
}
Finally, a short form for entering the message:
<form action="#cgi.script_name#" method="post">
<input type="text" name="message">
<input type="submit" name="newmessage" value="Send Message">
<input type="hidden" name="formPosted" value="1">
</form>
That’s all there is too it!
You can download the source code for my examples here:
source code
I’d love your feedback on the code (if you use it) and I’d love to hear how you’re using instant messenging with ColdFusion, if you’re so inclined.
Screenshots: