Sunday, December 14, 2014

XMPP: IM using OpenFire and Smack

While searching for some useful tutorials on how to do IM using OpenFire and Smack, I found there is no a satisfactory one-stop basic tutorial to get one easily started on creating an IM application, therefore i decided to write something about it after some experiments. This post will show how to setup OpenFire for instant messaging application and send notification via XMPP using Smack.

Setup Droplet

As OpenFire needs public IP address in order to send and receive messages, to this end, a droplet is created at digitalocean. Follow the following link to create droplet at digitalocean:

https://www.digitalocean.com/community/tutorials/how-to-create-your-first-digitalocean-droplet-virtual-server

Suppose the droplet that we created has the following settings:

hostname: droplet.demo.com
IP: 1.1.1.1
port: 9090
user: root

Setup OpenFire on Droplet

The following describes how to set up openfire on droplet:

https://www.digitalocean.com/community/tutorials/how-to-install-openfire-xmpp-server-on-a-debian-or-ubuntu-vps

Below I describe my process of setting up openfire on a droplet which may be a bit different. Suppose you have set up your droplet at root@1.1.1.1. Run the following command to login to root@1.1.1.1:

> ssh root@1.1.1.1

Once login to root@1.1.1.1, run the following command to download the latest openfire:

> wget -O openfire_3.9.3_all.deb http://www.igniterealtime.org/downloadServlet?filename=openfire/openfire_3.9.3_all.deb

Once downloaded, run the following commands to update the environment:

> sudo apt-get update
> sudo apt-get install openjdk-7-jre

The above commands install the openjdk-7 on the droplet. Now run the following command to install openfire:

> dpkg --install openfire-3.9.3_all.deb

Open the web browser and navigate to http://1.1.1.1:9090/ to configure the openfire. After the installation the files can be found in "/usr/share/openfire"

After the openfire is installed, one can check whether it is running by the following command:

> sudo ps -ef | grep openfire

To stop openfire at root@1.1.1.1, run the following command after login:

> /etc/init.d/openfire stop

To start openfire at root@1.1.1.1, run the following command after login to root@1.1.1.1

> /etc/init.d/openfire start

Lets visits 1.1.1.1:9090 to add to users account (non-admin) to the Users/Groups:

  • demo
  • reader
Install Spark IM Client to receive IM
Download and install Spark IM Client from the following link:


After the installation, we will login the Spark IM client using the "reader" account.

Smack as OpenFire Client to send IM

Now we will develop the java code which allow the "demo" account to send IM to the "reader" account (which we have login Spark IM client in the previous step). To this end, the Smack library is used to connect to the openfire server running in the droplet (which is at 1.1.1.1:5222). Lets create a Maven project and add the following dependencies:

<dependency>
<groupId>jivesoftware</groupId>
<artifactId>smack</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>jivesoftware</groupId>
<artifactId>smackx</artifactId>
<version>3.1.0</version>
</dependency>

Now in the main class java file App.java, add the following implementation:

package com.memeanalytics.openfire_client;

import java.util.Calendar;

import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Message.Type;

public class App 
{
    public static void main( String[] args )
    {
     sendMessage();
    }
    
    private static void sendMessage()
    {
     String hostname =  "1.1.1.1";
     int clientPort = 5222;
        ConnectionConfiguration config=new ConnectionConfiguration(hostname, clientPort);
        XMPPConnection conn=new XMPPConnection(config);
        
        String username="demo";
        String password="[demo_password]";
        
        String to_username = "reader";
        String to = to_username + "@droplet.demo.com";
        
        try {
         conn.connect();
         conn.login(username, password);
   
  listContacts(conn);
   
  sendMessage(conn, to, "This is some message! The time is "+(Calendar.getInstance().getTime()));
   
  if(!hasContact(conn, to))
  {
   addFriend(conn, to, "reader");
  }
   
   
   
  conn.disconnect();
   
   
 } catch (XMPPException e) {
  // TODO Auto-generated catch block
  e.printStackTrace();
 }
    }
    
    private static void sendMessage(XMPPConnection conn, String to, String message_body)
    {
     Message message = new Message(to, Type.normal);
 message.setBody(message_body);
 conn.sendPacket(message);
 System.out.println("Message sent!");
    }
    
    private static boolean hasContact(XMPPConnection conn, String to)
    {
     RosterEntry entry = conn.getRoster().getEntry(to);
     return entry != null;
    }
    
    private static void addFriend(XMPPConnection conn, String to, String to_nickname) throws XMPPException
    {
     String[] groups=new String[] { "Friends" };
  
 conn.getRoster().createEntry(to, to_nickname, groups);
 System.out.println("Invitation sent!");
    }
    
    private static void listContacts(XMPPConnection conn)
    {
     for(RosterEntry entry : conn.getRoster().getEntries())
     {
      String userId = entry.getUser();
      String username = entry.getName();
      System.out.println(username + " >> " + userId);
     }
    }
    
   
}

The above implementation should be quite well self-explainable. The code start with opening an XMPP connection to 1.1.1.1:5222 which runs the OpenFire XMPP server at DigitalOcean's Droplet, and end by closing the connection.

After connection, the java code login using the demo's account, next it invokes the listContacts() method which list down all the contacts in demo's contact list. and sends a message to "reader" account. Lastly it checks whether "reader" is in demo's contact list, if not, then it sends an invitation to "reader".


No comments:

Post a Comment