Developing XMPP Components – The Service

In the first part of this blog, I talked about XMPP component, server configurations (subdomain name and secret key) and also about setting up the build environment for Whack.

At the most basic level, developing XMPP components (XEP-0114) with Smack consists of the following Java classes

  1. A ‘main‘ class – This is the class that
    • Creates the XMPP component; this is the service
    • Connects and performs handshaking with a Jabber server
    • Keeps the XMPP component alive by going into an infinite loop
  2. The XMPP component class – This class either implements Component or extends AbstractComponent. The difference between the two is how much do you want to write viz. AbstractComponent provides a simple framework to handle various message type while Component you must implement all these yourself. I will go into this in greater detail in my next blog. For the time being, we will just go with Component

We will implement a simple uppercase service, where any message that you send to the service, the service will echo it back to you in uppercase. The following is the main class

import java.util.logging.*;
import org.jivesoftware.whack.*;
import org.xmpp.component.*;

public class Main {
   public static void main(String[] args) {

      ExternalComponentManager mgr = new ExternalComponentManager(“myserver”, 5275);
      mgr.setSecretKey(“landofthegiants”, “uppercase”);
      try {
         mgr.addComponent(“landofthegiants”, new UpperCaseComponent());
      } catch (ComponentException e) {
         Logger.getLogger(Main.class.getName()).log(Level.SEVERE, “main”, e);
         System.exit(-1);
      }
      //Keep it alive
      while (true)
         try {
            Thread.sleep(10000);
         } catch (Exception e) {
            Logger.getLogger(Main.class.getName()).log(Level.SEVERE, “main”, e);
         }
   }
}

Some salient points about the above code

  • You create an instance of ExternalComponentManager. This class will be responsible for all components connecting to a particular server. In this case its myserver. Note that 5275 is the standard port
  • What you need to do next is to associate a secret key (uppercase) with the subdomain (landofthegiants) of your component. The secret key and subdomain must first be defined on the XMPP server. See part 1.
  • Next you create an instance of your component and add that to ExternalComponentManager; the component is associated with the subdomain name. UpperCaseComponent must either implements Component or extends AbstractComponent.
  • Finally keep your ‘server’ alive with an infinite loop. 

The following class shows UpperCaseComponent

import org.xmpp.component.*;
import org.xmpp.packet.*;

public class UpperCaseComponent implements org.xmpp.component.Component {
    private ExternalComponentManager mgr = null;

    public String getName() {
        return (“Upper case”);
    }

    public String getDescription() {
        return (“Echos your message back to you in upper case”);
    }

    public void processPacket(Packet packet) {
        if (packet instanceof Message) {
            org.xmpp.packet.Message original = (Message) packet;
            org.xmpp.packet.Message response = original.createCopy();
            //Swap the sender/recipient fields
            response.setTo(original.getFrom());
            response.setFrom(original.getTo());
            //Convert the text to upper case
            response.setBody(original.getBody().toUpperCase());
            mgr.sendPacket(this, response);
        }
    }

    public void initialize(JID jid, ComponentManager componentManager) throws ComponentException {
        mgr = (ExternalComponentManager) componentManager;    
    }

    public void start() { }

    public void shutdown() { }
}

As you can see, implementing a component is quite simple. getName(), getDescription(), start() and shutdown() are pretty self explanatory. The initialize() method is called before start(). In the initalize() method, the component will be passed its JID; this will be the subdomain plus the domain. for example the JID of this component will be landofthegiants.myserver.com. The other thing that gets pass into the component via initialize() is the instance of the ComponentManager that created the component. Hold a reference of this because the component manager is the key to communicating with the outside world eg. sendPacket().

The processPacket() is the meat of the component; all packets to landofthegiants.myserver.com subdomain are routed to this method. So what you have to do is check if packet parameter is one of the 3 types of message: Message, IQ or Presence, and cast packet appropriately.

In the final part of my blog in this series, I’ll talk about using AbstractComponent, Smack versus org.xmpp API and advertising your component.

Advertisements
%d bloggers like this: