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.

22 Responses to Developing XMPP Components – The Service

  1. thorny says:

    Hello oneminutedistraction.
    I read 3 thread. But i am not successful.
    Download whack source, build it.
    Write Main, UpperCaseComponent class. Compile not error. But when i run it, has error: java.lang.ClassNotFoundException: com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap$Builder
    java.lang.ClassNotFoundException: gnu.inet.encoding.IDNA

    Please help me to run this example and guide how to use it.
    Thanks!

  2. thorny says:

    Thanks for your reply.
    It run ok.
    But i don’t know how to use my component (example UpperCaseComponent).
    Additional, can you explore me about “disco#info”?

  3. Sean says:

    Thank you for a very useful sample code. One question: How would one send the same message to multiple JIDs?
    Thanks and I would love to see more component oriented posts.

  4. Minh Nguyen says:

    start() and shutdown () have no definition???

  5. Bashar says:

    Hi,
    I followed the tutorial but I have got an exception. So far I could not solve it. I will be grateful if you can give some hints on the issue.

    Exception in thread “main” java.lang.NoClassDefFoundError: org/xmpp/component/Log
    at itm.stage.xmpp.services.UppercaseService.main(UppercaseService.java:22)
    Caused by: java.lang.ClassNotFoundException: org.xmpp.component.Log
    at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    … 1 more

    P.S. I am running your code with out changes. I have referenced the whack.jar in my eclipse project.

    Than ks a lot,
    B.

  6. tree1891 says:

    Is the ComponentManager.sendPacket() function threadsafe?

  7. tree1891 says:

    Is it possible developing external component by tinder?
    If so, where can I find sample?

  8. hemant mehta says:

    Its an excellent BLOG for component creation, I complied and added the uppercase component to the server. Can you please tell me how can I send message to this service?
    I need to send some messages to this service to test it.

  9. hemant mehta says:

    Thanks a lot for prompt reply, It is working now. I was trying to chat with the user but not using send message option.

  10. Piyush Pant says:

    How can i run multiple instances of XMPP component in a cluster using Whack and Ejabberd ?

Leave a reply to thorny Cancel reply