Maintaining an online presence in Jabber

Follow these steps to maintain a presence in the Jabber online community, such as retrieving a list of friends from the roster.
Written by Lee Chuk-Munn, Contributor

In the previous article, we talked about how you can connect to a Jabber online community using the XMPP peer-to-peer protocol. In this article, we will be looking at maintaining our online presence.

For that, we will be performing the following tasks:

  • Announce our availability to the Jabber community
  • Obtain a list of friends/buddies from our roster
  • Organize a list of conference rooms for birds of a feather discussion

However, before we continue, let me say that there are some features that we will not be looking at, such as creating an account, maintaining your roster, etc. These features can be found in any standard Jabber IM client.

And since Jabber allows developers to specify a resource to distinguish different connection log-ins simultaneously to a same account, our application will only read the roster, initiate application-to-application chat, and leave the account and user management aspects to these IM clients.

As in the previous article, all code examples will use the Smack XMPP library.

Announcing our presence
One of the first things we should probably do once we have logged in to a Jabber server is to let others know about our availability. We do this by sending a Presence packet. The Presence packet allows us to specify our availability and also to attach a short note like "I am available".

The following code snippet shows how this is done.

//Create a XMPPConnection
XMPPConnection connection = ...
//Login to the server
connection.login(username, password, "my_app_service");

//Create a Presence packet
Presence presence = new Presence(Presence.Type.available);
//Set a short message
presence.setStatus("I'm all ears");

From the code above, we create the Presence where the type is Presence.Type.available. The 'available' here refers to the user logs in to the server; and 'unavailable' when the user logs out. However, the Presence.Type information is normally handle by the Jabber server.

To indicate of your availability to chat, you have to use Presence.Mode. This is set using setMode() method. Finally, we attach a short message to the presence information using the setStatus() method. Figure 1 shows how your presence will appear to others.

Figure 1
Figure 1

Accessing the roster
The second thing that you will want to do after you have announced your online presence is to get a list of friends and buddies, which is stored in the roster. The roster will return RosterEntry objects.

Each of your friend is represented by one of these RosterEntry object. The RosterEntry will tell you the:

  • name getName()
  • user (JID) getUser(). A JID has the following format user@domain/resource. For example if a user login to jabber.org as fred with my_app_service resource, then the JID will be fred@jabber.org/my_app_service
  • the groups that this entry belongs to getGroups()

You can now use the JID to retrieve the presence information with Roster.getPresence(). The following code shows how to retrieve your friends from the roster and list the user information:

//Assume we have a valid connection
Roster roster = connection.getRoster();
//Listen to roster changes. Implement RosterListener
//Get a list of RosterEntries
for (RosterEntry entry: roster.getEnteries()) {
    System.out.println("Name: " + entry.getName());
    System.out.println("User (JID):" + entry.getUser());
    //Get presence information on the user
    Presence presence = roster.getPresence(entry.getUser());
    System.out.println("Mode: " + presence.getMode());
    System.out.println("Status: " + presence.getStatus());
    //Get the group that the user belongs to
    System.out.print("Groups: ");
    for (RosterGroup group: entry.getGroups())
        System.out.print(group.getName() + " ");

//Methods from RosterListener
public void presenceChanged(Presence presence) { //Do something

public void entriesAdded(Collection<String> addresses) { //Do something

public void entriesDeleted(Collection<String> addresses) { //Do something

public void entriesUpdated(Collection<String> addresses) { //Do something

As you are probably aware, users changes their status all the time. To keep track of their presence information, you have to implement RosterListener. The listener will notify you if the presence of user changes and whether entries have been added, deleted or updated.

Conference rooms
The final piece of information that you may want to get from the Jabber server is the list of themed conference rooms--each conference room will host users discussing a particular topic.

Conference rooms are organized under multi-user chat services. So what we need to do is to get the list of services, then list all the conference rooms under the service. You can get the service and conference rooms from MultiUserChat class.

From the conference room, we can get the RoomInfo object that gives the following information:

  • the name and description of the room
  • whether the conference room is moderated
  • if a password is required to join the room
  • the current number of participants

The following code snippet shows how we get this information:

//Assume we have a valid connection
//List all the services
for (String service: MultiUserChat.getServiceNames(connection)) {
    System.out.println("Service name: " + service);
    //Get the list of rooms under this service
    for (HostedRoom room: MultiUserChat.getHostedRooms(connection, service) {
        System.out.println("\tName: " + room.getName());
        System.out.println("\tRoom JID: " + room.getJid());
        //Get the detail information on the room 
        RoomInfo info = MultiUserChat.getRoomInfo(connection, room.getJid());
        System.out.println("\tDescription: " + info.getDescription());
        System.out.println("\tOccupant: " + info.getOccupantCount());
        System.out.println("\tPassword: " + info.isPasswordProtected());

One thing you do have to keep in mind whenever you are accessing information the Jabber servers is to run your code in a separate thread; the reason is that a call, for example MultiUserChat.getServiceNames(), may block because of heavy server load or network lag. So if you are running this on the main application thread then your Swing application may seem slow or sluggish.

Sample code
The following sample code in this ZIP file shows a working example of all that is discussed in this article. Unzip the file. The directory is a NetBeans project so you can open it with NetBeans.

To build from the source, you will need to add smack.jar and smackx.jar into NetBeans project. See the previous article on how to do this.

If you are just interested in running the application, go into the dist directory and use the following command to execute the application:

java -jar JabberEnvironment.jar

After you have logged in, the application list your buddies from your roster and the list of available conference rooms. Note that these data are loaded in a separated thread so if nothing shows up be patient; especially the conference room list. The core of these operations are performed in JabberEnvironment.java file, line 116.

Figure 2 and Figure 3 show the list of buddies in your roster and the list of available rooms under a particular service, respectively.

Figure 2
Figure 2
Figure 3
Figure 3

Note that with certain Jabber servers, not all the room information is available, eg. jabber.org does not maintain room description. So when you select a conference room to view its information, you may get a NullPointerException. The part of the code that handles this in the Smack library does not check for this.

In the next article, we will look at how to join conference rooms and initiate chat with other users. Once we understand that, we can then build our application on top of XMPP's infrastructure and leverage these peer-to-peer features.

Till next time, happy coding.

Note: In this article, XMPP and Jabber means the same thing although XMPP is a protocol and Jabber is a peer-to-peer server that implements this protocol.

Lee Chuk-Munn is a staff engineer at Sun Microsystems.

Editorial standards