Developing XMPP Components – The Setup

There are few ways to develop ‘server’ type XMPP applications; by server I mean a bot or an application connecting to a XMPP server and providing some sort of service like weather, fortunes, die roll, magic 8 ball or even act as mediator for games like Diplomacy and chess. For the sake of this blog, lets call this a xmpp service. The following are 3 possible ways you can implement xmpp service

  1. As a ‘regular’ XMPP user – what I mean by this is that the xmpp service is like a regular user. The service would create an account with say jabber.org, logs in and waits messages. The XMPP service can also be part of a real user’s (human) login. When a person logs in, the service starts. XMPP clients like Spark provides a plugin architecture (sparkplug) to develop such services. This method is by far the easiest method to develop the services; the disadvantage is that your service has a limited reach because in order to use the xmpp service other users must discover the JID and must also explicitly add that JID into their roster before you can do anything with it.
  2. XMPP Server plugins – another way of developing these services is to make them part of the server. Most servers have some sort of a plugin architecture; see Openfire’s as an example. The advantage of this approach is that the service does not need to in a users roster for the user to use it. And discovering the service boils down to sending a disco#item packet to the server. For example sending a disco#item to jabber.org returns the following <item jid=’conference.jabber.org’ name=’Multi-User Chat’/> in part of the reply. We can now start a conference with that JID. The disadvantage of this approach is that the service that you have developed may not be portable across to other servers.
  3. XMPP components  – the XMPP Foundation has defined a standard protocol for services to connect to XMPP servers. This is defined in Jabber Component Protocol (XEP-0114). The way this works is that the service will communicate with a standard XMPP server using a predefine mechanism for identification and authentication. Once the handshake is successful, the XMPP component effectively becomes part of the server and behaves like a server plugin in that it can be discoverable using the standard disco#item as well as disco#info mechanism. The component runs outside (in a separate process) of the XMPP server. So you can shutdown the service without affecting the server. An added advantage is that because XEP-0114 is a standard, in theory , you can connect the service to different XMPP servers.

There are a few XEP-0114 Java libraries like XMPP Gateway and Whack. We will be using Whack. The first step is to setup the CLASSPATH the the appropriate libraries

  • Start by downloading the Whack source from the repository as shown here. The reason why you download the source instead of just the binaries is because when you eventually run your XMPP service, the Whack runtime will need a few more libraries that are not present in the binary download. So its better to bite the bullet and get the source which contains all the dependencies. There is also 2 sample services which you can reference. They are actually the same service  (weather) but implemented differently
  • Build it either with Ant or Maven. For Ant the whack.jar will be target directory and for Maven it’ll be in sample/weatherabstract/build/lib/merge/whack.jar.
  • Now set your CLASSPATH to include whack.jar and all the JARs in build/lib/dist and build/lib/merge and other libraries that you may need for your application. You can exclude the Jetty JARs if you want to run your component as a standalone Java application. Tip: if you are using JavaSE 6 or later, you can use the wildcard character like so
    CLASSPATH=’/whack_src/build/lib/dist/*:/whack_src/build/lib/merge/*:<other_jars>’.

The second step is to give a subdomain name and a secret key that is shared between the XMPP server and the service. Both the subdomain and secret key are setup on the XMPP server. A subdomain is a name that will be used to identify your service; eg in the example above, jabber.org MUC’s JID is conference.jabber.org; the subdomain here is conference and jabber.org is the domain. So if we call our subdomain rot13 because we are going to provide a ROT13 service, then the JID will be rot13.jabber.org (assuming its on jabber.org).

The following diagram shows how to set these 2 values if you are using Openfire.

  • Login to the admin console http://localhost:9090
  • Click on Server Settings then External Components
  • Type in the subdomain name and the secret key and click on Add Component to save the setting

In my next blog we will look at developing the XMPP service.

Advertisements

36 Responses to Developing XMPP Components – The Setup

  1. sean says:

    Hey,

    Great work so far, a lot of useful info! I’m a bit stuck on the whole default key and subdomain and key thing. Can you provide a bigger screenshot of those settings in the admin console?
    Thanks!

    • Hi Sean

      Here is a bigger picture of the admin console.

      Regards

      • sean says:

        Thanks for the prompt reply! So, in the subsequent article, based on the screenshot you would have something like ExternalComponentManager mgr = new ExternalComponentManager(“myserver”, 5275);
        mgr.setSecretKey(“uppercase”, “uppercase”);
        try {
        mgr.addComponent(“openfire”, new UpperCaseComponent());
        } catch (ComponentException e) { . . .}

        Is this correct? Thanks again.

  2. If the subdomain is ‘mysubdomain’ and secret key is ‘mykey’ then the setup should be

    //Map key to subdomain
    mgr.setSecretKey(“mysubdomain”, “mykey”);
    //Map component to subdomain
    mgr.addComponent(“mysubdomain”, new UpperCaseComponent());

  3. kency says:

    Hi,
    Your post is great, but is it tutorial write component for server side such as Openfire?

    • Yes its ‘server side’ in the sense that XEP-0114 components will connect to a XMPP server and offer its servers as as part of the XMPP’s server offerings

      • kency says:

        Hi, i have one question for you. Can i write server side look like Openfire? Because i need write a server for my application it managed chat and other component such as department, product….

      • Openfire and most XMPP servers already offer 1 to 1 and group chat features so you don’t need to write a XMPP server.
        If you are offering a soup up version of chat or some services that is not offered by Openfire, then what you do is write a XMPP component which implements this service. When your component/service starts up, it will connect to your Openfire server (myopenfire.com) . Your service will look like it is being offered from myopenfire.com. The way your service distinguish itself is be registering a subdomain name with myopenfire.com (the domain). So if your service’s subdomain name is fred, then you can address your service by using fred.myopenfire.com.

      • kency says:

        Many thank you! i understand my problem . 😀

  4. Stefano says:

    Thank you for these entries on how to build a XMPP Component using Whack 🙂
    It helped me a lot.

    I would like to point out a few things, though:
    – the precompiled Whack is outdated so it would be no use to download it anyway;
    – the trunk of Whack does not compile out of the box, it seems the jetty library has to be updated. Just download a more recent version of the library to make it work.

    It gave me some headache to make it work, but then everything got smoothly.

    It is a shame theere isn’t a real community following it anymore… XMPP is just great.

    • Yeah. It has been a learning experience for me. After Whack I found Tinder which is a lot better. BTW if you are developing XMPP component have you look at my XMPP container? Advertisement alert See my blog on Jabberwocky and the subsequent few blogs on it. I’m trying to make developing XMPP components easier.
      Thanks for stopping by.

      • Stefano says:

        Isn’t Tinder used by Whack?
        I did read about Jabberwocky and although it seems a good idea, I would have to learn about Glassfish and everything – it seems for what I need it is a bit too much.

        I think I will stick with the 2 files implementation (ExternalComponentManager/AbstractComponent) which seems actually easier..

        By any chance, do you know if there is something like the smack PubSubManager to use with Whack? My component should manage some pubsub nodes depending on the received IQs.. and I’d rather not re-implement the smackx pubsub extension 😀

      • To answer your PubSubManager question, no I don’t. But if you are writing a XEP-0114 component, would openfire handle that for you. Your component subscribe to a node and receives notification?

        I think Tinder is uses a more updated version of Whack.

        BTW with Jabberwocky you are still using AbstractComponent class or Component interface. What Jabberwocky provides is management of your component like startup, shutdown, etc. There are also statistics, etc. Also you don’t have to write the ‘server’ that keeps your component up.

      • Dan says:

        I’m working on an XMPP external component myself, and Tinder does seem simpler than Whack, at least in the sense that it doesn’t doesn’t include dependencies on Jetty and such. But Tinder doesn’t provide ExternalComponent, ExternalComponentManager, SocketReaderThread and the other classes you need to actually run a component. Jabberwocky looks interesting but I don’t use full-fledged Java EE in my environment so I guess I’ll just stick with Whack for now 🙂 Now, if Smack provided a way to do external components….

  5. Stefano says:

    I am developing a smartphone app, a client using this app should be able to publish the same item in different ways to different nodes (ex. some node should get only part of the info), it would be a shame to make the poor client send a message for each node, thus a component will receive this message and broadcast the info to the different nodes..

    I’ll have a look into jabberwocky 🙂

  6. Antony says:

    These are great posts, thanks! They got me a long way into understanding XEP-0114. I am trying to develop an external module that can get a user’s presence information based on another user, i.e. to achieve exactly what the Openfire presence plugin does, but in a ‘standard’ way, i.e. as a component. I really can’t see how I can achieve this via the component. Do you know how it could be done?

    • If you are using Tinder API, then you either implement Component or extend AbstractComponent. If you are doing the former, then you have to check if the packet is an instance of Presence in processPacket. If you are extending AbstractComponent, then override the handlePresence method.

      If you are developing XEP-0114 components have a look at Jabberwocky, my XEP-0114 container.

      • Antony says:

        I made an external component with Whack, but it’s not clear how to address any packet. e.g. if my external app A1 wants to find out the presence of user1@host on behalf of user2@host it can develop an external component C1 using Whack inside A1, which talks to an internal component C2 (which uses internal Openfire specific ways to find out Presence). However, I think I would send a probe presence packet, but in this situation there is From C1, to C2 but I want to know about the Presence between user1@host and user2@host, so what sort of packet can be sent and how can it be addressed.

      • I don’t think you need an external component (Whack/Tinder) for this situation.You can just use smack API in A1. From A1, you login as user1@host. If you and user2@host are ‘buddies’, then you will be notified once user2@host presence status changes. Use XMPPConnection.getRoster().addRosterListener(). Alternatively as you say you can send a presence probe to the server. To only caveat is that user1@host must subscribe to user2@host. Hope this helps.

  7. Antony says:

    Problem is that app has no knowledge of any user’s credentials and needs to handle presence for up to thousands of users. I was hoping that a component, as a trusted entity, could ask for presence between two users. The component needs to know the presence as exists in the subscription relationship between user1 and user2, not between the component and user1, so subscription between the component and the user is irrelevant. All I am trying to do is to propagate the presence information to a non XMPP aware, legacy system.

    It seems like I will have to go the proprietary way, to extend the existing Openifire presence plugin to give me what I want. Does seem odd that it cannot be done as a component though.

    • No I originally thought that you want to find out about user2 from an app. Now I see what you are trying to do. For your use case, I think you will probably need to write a plugin for Openfire.

  8. Minh Nguyen says:

    I am going to create an external component for Openfire but when I used Whack 1.0 and Tinder, it threw exception named NoClassDefFound at the declaration of ExternalComponentManager in Main class. What should I do now?

  9. Minh Nguyen says:

    I used Tinder 1.2.2 too and cannot run your sample code with that error. According to that link, there is incompatibility between two library Whack and Tinder. Any help???

  10. Minh Nguyen says:

    I’m sorry but I’ve just copied your code (2 files) to my project but I cannot find where to download your entire upper case component project. Can you show me? Probably it’ll help.

  11. tree1891 says:

    I don’t understand the disadvantage of implementing xmpp service as xmpp client.
    Why dose users must explicitly add service provider’s JID into their roster?

  12. medsalah says:

    Hey,

    This is a great work , thanks!
    I’m new with xmpp , and I have to control openfire users and chat rooms from my java application ( listen to new invitations and new messages , and send new invitation to users or send a new messages)
    I’m confused about using whack or Tinder ( or maybe connection manager module ).
    I really can’t see how I can achieve this ?

    • Not sure what you mean by control openfire users. XEP-0114 (Whack/Tinder) is not an openfire plugin so you will not have access to users registered with openfire. With XEP-0114, you have your own subdomain for your service. If your service has its own users then your service can manage those viz fred@myservice.jabberserver not fred@jabberserver assuming that myservice.jabberserver is your serivce’s subdomain.

      Tinder is the implementation of XEP-0114. Whack is the ‘engine’ that implements ComponentManager to run XEP-0114 components (Tinder). You can run Tinder without Whack but its just easier to use Whack.

      start_of_advert
      If you are thinking of using Tinder to write XEP-0114 components, consider my framework Vorpal which runs in a standard JavaEE 6 Web Container; it allow you to use all the resources on the EE 6 platform including JPA, session beans, etc. Vorpal is based on CDI. See this blog for an introduction.
      end_of_advert

      Regards

  13. Lalena says:

    Hello. Thanks for these posts. I have followed your advice and created an External Component by extending AbstractComponent. It is working well but I need to be able to detect in my external component when the connection to the server is lost. I have not found an obvious way to do this. What am I missing?

    • Hi

      if you are using AbstractComponent (Tinder) with Whack (ExternalComponent) then the ExternalComponent will handle the retries for you when the connection to the server is severed. But I don’t think you will be notified. See the source for ExternalComponent. If you really want to know about the event, then its pretty easy to add an event for connection retries. See ExternalComponent.connectionLost().

      HTH

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: