Yet Another XMPP Client Library


Vorpal framework is an external component framework. You use it to build services to be delivered by your XMPP server. It occurred to me that I could use the same programming model for client connections viz. like Smack. So now let me introduce Vorpal Client.

Vorpal Client is a Java XMPP library that allows you to connect to an XMPP server; the framework can be used in 3 different ways depending on how much control you want to have.

  1. Implement the com.kenai.jabberwocky.framework.client.ClientComponent interface
  2. Extend the com.kenai.jabberwocky.framework.client.AbstractClientComponent class. The first and second method is very similar to Tinder where you either implement org.xmpp.component.Component or extend org.xmpp.component.AbstractComponent. These methods are quite low level in that you manipulate the XMPP packets directly.
  3. The third is to use CDI, like Vorpal. For the rest of this blog, we will be focusing on this third method. This mode uses the same programming model as Vorpal; the big difference is that whereas Vorpal runs in a container (GlassFish), Vorpal Client runs in an SE environment so there is a little bit of setup involved.

Lets look at the steps to create a simple application that connects to OpenFire (I’ll leave GoogleTalk as an exercise for the reader) using method 3 above.

Create a Configuration File

<connection port=”5222″ domain=”batcomputer”>
   <component-class name=”com.kenai.jabberwocky.framework.client.JabberwockyClientComponent”/>
   <classes-root>classes</classes-root>
   <packages>
      <package name=”com.acme.xmpp.client”/>
   </packages>
   <properties>
      <property
name=”vorpal.component.description” value=”A component to query the customer’s database”/>
      <property
name=”vorpal.component.name” value=”Customer Query Client”/>
   </properties>
</connection>

A few salient points regarding the configuration file

  1. The <connection> starts the configuration. You specify the XMPP server in domain attribute. port attribute is optional and will default to 5222.
  2. After specifying the connection, you now define the client component. If you’re using method 3, then you just use copy the line above.
  3. The <classes-root> and <packages> tells Vorpal Client where to look for your classes (annotated with @Message, @IQ and @Presence) and what packages it should scan. You only have to specify either <classes-root> or <packages>. .
  4. Finally you can specify properties for your components.

Create a Startup Class

Note: If you are not familiar with using CDI (Weld) in Java SE, have a look at this document before proceeding.

We need to first create a startup class.

public class Startup {
   //Inject the command line arguments
   @Inject @Parameters List<String> args;
   //Called when container starts up, like psv main()
   private void initialize(@Observes ContainerInitialized containerEvt) {
      …
   }
}

Next create a main class like so

public class Main {
   public static void main(String[] args) {
      new StartMain(args).go();
   }
}

StartMain is part of Weld SE environment. So you will need to download Weld and add weld-se.jar into your CLASSPATH. Compile the class and bundle it into a JAR file (myclient.jar). Don’t forget to add beans.xml in the META-INF directory.

To run it type the following

java -cp ${CLASSPATH}:myclient.jar Main jabberid password

Creating Connection using Vorpal Client

The following code snippet shows how to create a connection to XMPP server

public class Startup {
   //Inject the command line arguments
   @Inject @Parameters List<String> args;
   //Inject a client connection
   @Inject ClientConnection connection;

   //Called when container starts up, like psv main()
   private void initialize(@Observes ContainerInitialized containerEvt) {
      //Exceptions omitted
      //Read the configuration – see above
      ClientComponentConfiguration config = ClientComponentConfiguration.read(new File(“client.xml”));

      //Connect to the server specified in the config file
      connection = connection.connect(config);

      //Login to the server
      if (!connection.login(args.get(0), args.get(1)) {

         System.err.println(“Authentication failed!”);
         System.exit(-1);
      }
      //Create the application
      connection.createApplication(config);

   }
}

Some salient points regarding the code snippet from above

  • You can create ClientConnection manually by specifying the server and port; see javadoc. But if you are planning to get access to the ClientConnection object in other parts of your application, then its better to use CDI injection. The injected ClientConnection is application scoped so you’ll get the same object throughout your application. The current release does not supported @Named ClientConnections. @Named will allow the support of more than one injected connection. This is currently a very low priority cause I’m not sure if anyone will use more than 1 connection.
  • Next we read in the application’s configuration and use that to initialize the connection. Invoking connect() causes the connection to connect to the XMPP server.
  • Following that, we login to the server. Username and password is not part of the configuration so you have to somehow pass that in. In the example above, we pass it in through the command line. If the authentication fails, login() will return false
  • Finally we call createApplication() to create and start the application.

Initializing Your Application

Once you have got past the createApplication(), you can now start your application using Vorpal’s lifecycle events.

private void postComponentStart(@Observes ComponentPostStart postStartEvent) {
   //Exceptions omitted
   ResponseContext respContext = new ResponseContext();
   respContext.type(
ResponseContext.Type.Presence)
         .add(“I’m online”)
         .add(Presence.Show.chat);
   postStartEvent.getComponentContext.send(respContext);
}

In the example code above, after the ComponentPostStart event, we send a presence message using response context (see this if you are unfamiliar with response context). For Vorpal Client, if you do not fill in the to() and from() in the response context, then they will default to the server that your client is connect to and the Jabber ID that you’ve used to login respectively. There is also a new predefined binding call __self__. __self__ will give you the full JID of the Jabber ID that is used to login. For an application to find out what is the id that is used to login, you can do this

@Inject @Named(“__self__”) JID me;

While we are on this topic, __subdomain__ will return null and __domain__ will return the Jabber server that the application is connected to. There are also a few new annotations @Identity, @Feature and @Item to match disco#info and disco#items.

Your application can respond to incoming message in the same way that you are using Vorpal viz. their programming model is exactly the same so I won’t repeat it here. You can find an introduction to Vorpal programming model here.

Running the Application

The bad news is that Vorpal Client uses a quite a lot of external JARs. The good news is that most of these are already bundle for Jabberwocky. So lets assume that your application JAR is call myclient.jar, then this is how you run it

java -cp myclient.jar:vorpal.jar:weld-se.jar:jabberwocky_support.jar my.main.Class

You can get vorap.jar and jabberwocky_support.jar from the framework bundle. weld-se.jar from Weld download (use Weld 1.1). Please note that jabberwocky_support.jar MUST BE LAST JAR in the -cp switch because of this issue.

I have a full blown Vorpal Client application here if you need more example. The QueryClient complements the CustomerQuery; the source can be found here.

Vorpal Client currently is still considered experimental and does not support features like compression SSL, etc.

The latest bundle that supports Vorpal Client can be found here. There are lots of bug fixes to the Vorpal framework especially if you’re using CDI. So please upgrade to this release.

I’m keen to hear what you think of Vorpal Client as I’ve big plans for it. The really nice thing about it is that any feature that I add to the client can also be used in the ‘server’ portion. 

Till next time.

Advertisements
%d bloggers like this: