For one of my projects i wanted to develop an simple chat application , something like gmail chat.
The things i should consider before start were , the existing technology the project is developed (with Seam framework and richfaces) , also it should be reusable across different websites ( hence ability to handle huge volume of traffic). Richfaces <a4j:poll> is the easy and simple way of building an asynchronous chat (i will blog about this later). But the draw back is it has to keep polling the database tables for chat related data (performance bottleneck) and no DBA wants to store in the DB people’s howdy ‘s and LOL’s.

Earlier in our company we had Openfire installed for developers to communicate among themselves inside NetBeans IDE . So i thought of giving a try on setup like that, which led me into SMACK API. After some googling i hit upon an excellent article in java.net by John Ferguson Smart which helped me a lot in understanding about the SMACK API.

I dont want to explain here about SMACK API, but i will explain how i integrated it with Seam and richfaces.

1. Created an Seam Action Class as follows , for brevity omitting getters and setters
<pre class="brush:java">@Scope(ScopeType.SESSION)
@Name(“chataction”)
public class ChatAction{

private static XMPPConnection connection = null;
private String tomessage;
private String frommessage;
private List conversationList=new ArrayList();
</pre>


2. Wrote an method as follows to get the XMPPConnection.
<pre class="brush:java">private static XMPPConnection getConnection(){
if(connection == null) {
connection = new XMPPConnection("gmail.com");
try{
connection.connect();
connection.login("websiteuserlogin@gmail.com","password");
}catch(XMPPException xmppe){
xmppe.printStackTrace();
}
}
return connection;
}

</pre>

3. Check for the Contacts /Chat users availability.

<pre class="brush:java">public boolean chatAvailability(){
Roster roster = getConnection().getRoster();
Presence presence = roster.getPresence("websitechatadmin@gmail.com");
if (presence.getType() == Presence.Type.available) {
return true;
}
return false;
}

</pre>

4. Start Chat method.


<pre class="brush:java">public void startChat(){

try{
XMPPConnection connection = getConnection();
ChatManager chatmanager = connection.getChatManager();
Chat chat = chatmanager.createChat(websitechatadmin@gmail.com, null);
Message msgObj = new Message(to, Message.Type.chat);
conversationList.add(" me : "+getTomessage());
msgObj.setBody(getTomessage());
chat.sendMessage(msgObj);
setTomessage("");

// Accept only messages from
PacketFilter filter
= new AndFilter(new PacketTypeFilter(Message.class),
new FromContainsFilter(to));

// Collect these messages
PacketCollector collector = connection.createPacketCollector(filter);

Packet packet = collector.pollResult();

PacketListener myListener = new PacketListener() {
public void processPacket(Packet packet) {
if (packet instanceof Message) {
Message msg = (Message) packet;
if(msg!=null && !conversationList.contains("website chat admin: "+msg.getBody())){
// Process message by adding to conversationList
conversationList.add("website chat admin: "+msg.getBody());
}
}
}
};
// Register the listener.
connection.addPacketListener(myListener, filter);
}catch (Exception e) {
e.printStackTrace();
}

}
</pre>

5. Stop chat method.

<pre class="brush:java">public void stopChat(){

if(connection!=null){
connection.disconnect();
}
if(conversationList!=null){
conversationList.clear();
}
}
</pre>

6. Create chat.xhtml , i used <a4j:poll> to keep polling the server for message replies and updating the chat window on the browser.

<pre class="brush:html"><!DOCTYPE composition PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:s="http://jboss.com/products/seam/taglib"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:a4j="http://richfaces.org/a4j"
xmlns:rich="http://richfaces.org/rich">

<ui:define name="body">
<a4j:region>
<h:form>
<a4j:poll id="poll" interval="1000" reRender="chatwindow,chat"/>
</h:form>
</a4j:region>

<a4j:form>
<a4j:outputPanel id="chatwindow">

<h:outputText value="User is unavailable try again later....." rendered="#{!chataction.chatAvailability()}"/>
<ui:repeat value="#{chataction.conversationList}" var="frommesg">
<h:outputText value="#{frommesg}" escape="false" /><br></br>
</ui:repeat>

</a4j:outputPanel>

</a4j:form>
<a4j:form>

<h:inputText id="txtbox" value="#{chataction.tomessage}" />
<br></br>

<a4j:commandButton id="chat" value="Chat" action="#{chataction.startChat()}" reRender="chatwindow,txtbox"/>
</a4j:form>

</ui:define>
</ui:composition>
</pre>

maven project source code can be downloaded from here

Banner 468x60banner