Using Server Sent Events with Vorpal

bridge

I came across the following 2 blogs (here and here) on a CDI framework for server sent event (SSE) several months ago. I downloaded the source then tried it with Vorpal running on Glassfish 3.1.x. The result was a really long exception stack.

4 months later.

After publishing part 4 of on conversations, I decided to see if I have any luck with the SSE framework. I wasn’t really expecting it to work. Well it did. What is even more surprising is that it worked with Vorpal. 

What I’m going to do in this blog is explain how the SSE framework works and more importantly how you can use it with Vorpal. Its really easy.

Setup the push event stream

Firstly create a notification handler. The notification handler will maintain the connection between the browser and the web application. The following is a simple notification handler

@ServerSentEvents(“/notifications”)

public class NotificationHandler extends ServerSentEventHandler {

   public void sendMessage(String msg) {

      try {

         connection.sendMessage(msg);

      } catch (IOException ex) {

      }

   }

A few points to note: the notification handler must extend ServerSentEventHandler; this class is from the framework. You also have to annotate the class with @ServerSentEvents and specify the URL of the event stream. In this case it is notifications. More on this later.

Now you need to write a HTML/JSP/JSF/whatever page to invoke this event stream. Here is a snippet of the HTML page along with a snippet of Javascript that loads loads the event stream

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html">
    <h:head>
        <title>XMPP with SSE</title>
        <script src="resources/app.js"></script>
    </h:head>
    <h:body>
        <h1>Using Vorpal with SSE</h1>       
    </h:body>
</html>

The Javascript that creates the event stream is in app.js. Here is the code

var url = ‘http://’ + document.location.host

      + “/xmppsse/notifications”;

eventSource = new EventSource(url);

eventSource.onmessage = {

   document.body.innerHTML += msg + ’<br>’;

};

The important thing here is to get the event stream URL right. If our example, this is made up of the application context of our web application (in blue) and the value that you’ve specified in @ServerSentEvent annotation (in green).

 

Pushing data to the browser

We now hook the event handler to a Vorpal application. I did a screencast on developing a customer query service which allows you to use a Jabber client to query a database, which you can find here and the source here.

Lets extend this so that whenever someone performs a query, the result is also pushed to the browser using SSE.

@Message

public class MessageHandler {

   @EJB CustomerManager mgr;

   @Inject @ServerSentEventContext(“/notifications”)

        ServerSentEventHandlerContext<NotificationHandler> ctx;

   @Body(“{id}”)

   private String handle(@Named(“id”) int id) {

      //Assume we find every record and no NPE

      String record = mgr.find(id).toString();

      //Loop through all handlers

      for (NotificationHandler nh: ctx.getHandlers())

         try {

            nh.sendMessage(record);

         } catch (Exception ex) {

            nh.close();

         }

      return (record);

   }

After we got the record from CustomerManager, which uses JPA, we loop through all the registered handlers for an event stream channel and pushes the record to them. You have to get the correct handler to push to.

In our example, we are pushing to all browser registered on notifications. So we inject an instance of ServerSentEventHandlerContext with qualifying it with @ServerSentEventContext(“notifications”).

Example code

You can download the example source from here. I’ve bundled the SSE library into the download which is a NetBeans project.

Use the following steps to setup, deploy and run the example

  1. Configure an external component on your Jabber server. The example uses customer for subdomain and AlwaysRight for shared secret (Caps!). You can always change these settings. I use Openfire for the Jabber server
  2. Make sure that you’ve installed your Glassfish with Jabberwocky container.
  3. Deploy the project to Glassfish either from NetBeans or using asadmin command. It’s probably easier if you deploy if from NetBeans
  4. Open your browser and point to http://yourserver:port/xmppsse. I’ve tested with Firefox and Chrome, latest versions.
  5. Open your Jabber client, open a chat with query@customer.your_jabber_server. Send 1
  6. You should now see your reply display in your Jabber client and in your browser.

The source code for the SSE can be found here if you wish to look at it.

Part of the code (the app.js) is taken from Bhakti Mehta’s blog. Big thanks.

Till next time.

Screencast: Are you there?

In this screencast we will show how to use @Presence to allow a XMPP external component to respond to subscription and probe messages. This is a continuation of our series of tutorial on developing CustomerQuery component with Vorpal framework.

The source thaw was developed in the screencast is availble here.

Till next time

Hello?

In XMPP, presence allows a person/bot/service to tell others about its availability. The latest release of Vorpal now supports presence; major annotations include the followin

  • @Presence – top level annotation to denote a class is a presence message handler
  • @PresenceType – type of the presence packet; see this
  • @Priority – priority of presence packet
  • @Show – availability. See this
  • @Status – the status of the presence packet

Lets see how we handle presence from an example. Remeber query@customer.batcomputer from the service discovery blog? Let say that after we have discovered query@customer.batcomputer, the user wants to add query to his/her roster. The following are the series of message exchanges between the user and the Customer Service.

The user sends a subscribe message, indicating that the user wants to receive query’s presence info

<presence to=”query@customer.batcomputer” from=”…” type=”subscribe“/>

If query@customer.batcomputer decides to accept the subscription, it’ll return a presence message with subscribed

<presence to=”fred@batcomputer/pidgin” … type=”subscribed“/>

Note: In most cases, there is also a reverse subscription send out viz. query@customer.batcomputer will also send a subscribe to fred@batcomputer. However in this use case query@customer.batcomputer is not interesed in fred@batcomputer‘s availability.

Once query has accepted the presence subscription of fred, the next message that query is going to get is most likely to be a probe message viz. enquiring about the presence status

<presence to=”query@customer.batcomputer” … type=”probe“/>

query can reply in the following way

<presence to=”fred@batcomputer/pidgin” …>
   <show>chat</show>
   <status>Available for customer enquiry</status>
   <priority>5</priority>
</presence>

assuming it is available.

We will now implement the above set of interactions with Vorpal.

@RequestScoped
@Presence
@To(“query@{__subdomain__}”)
public class PresenceHandler {
   //Method to handle subscription
   @PresenceType(type=org.xmpp.packet.Presence.Type.subscribe)
   public Object handleSubscription() {
      return (org.xmpp.packet.Presence.Type.subscribed);
   }
   …
}

  • Firstly presence handlers must be annnotated with @Presence annotation.
  • The @To is really optional; in here we are really particular in that we only want to entertain subscription request to query@customer.batcomputer.
  • Another point here is the use of @PresenceType to discriminate the packet; as you can see from the example above, when there is a subscription request handleSubscription() will fire and reply with a subscribed.

After accepting the subscription, we will now need to handle probe messages. The following handler shows how this is done

   @PresenceType(type=org.xmpp.packet.Presence.probe)
   public List<Object> handleProbe() {
      List<Object> result = new LinkedList<Object>();
      //Available to ‘chat’
      result.add(org.xmpp.packet.Presence.Show.chat);
      result.add(“Available for customer enquiry”);
      result.add(5); //Priority
      return (result);
   }

Before I conclude this blog, I would like to add that any subscription to the component is not handle by the XMPP server viz. fred@batcomputer subscription to query@customer.batcomputer should be handle by the component (CustomerService). In the example above you should probably save the senders JID if you want to do something with it later eg. notifying them that the service is going away when you are shutting the service down. Here is the modifed presenceHandler() with the sender’s JID

   //Method to handle subscription
   @PresenceType(type=org.xmpp.packet.Presence.Type.subscribe)
    public Object handleSubscription(@From JID from) {
      //Persist sender
         …
      return (org.xmpp.packet.Presence.Type.subscribed);
   }

Vorpal supports component lifecycle event which allows you to send presence info to your subscribers. I’ll blog about lifecycle and other miscellaneous features in an upcoming blog. For the impatient, see this as an example of using lifecycle events.

The latest build of the project is available here.

Till next time

XMPP Forms

Up till now, all my examples pertaining to exchanging data between the client and the external component have been using <message>. However there is a more structured way of exchanging data using forms (XEP-0004) very much like HTTP forms. The XMPP forms has a very rich structure; the following points provide a quick overview of XMPP data forms
  • firstly all the fields in the form are typed (or not, if you so choose); types includes ‘primitives’  like String, JID, boolean. Field can have attributes like hidden, fixed (label) and password. Furthermore fields can also be multivalued viz. a collection. The following shows an example of a XMPP form

<x xmlns=’jabber:x:data’ type=’form’>
   <title>Bot Configuration</title>
   <instructions>Fill out this form to configure your new bot!</instructions>
   <field type=’hidden’ var=’FORM_TYPE’>
      <value>jabber:bot</value>
   </field>
   <field type=’list-multi’
         label=’What features will the bot support?’ var=’features’>
      <option label=’Contests’><value>contests</value></option>
      <option label=’News’><value>news</value></option>
      <option label=’Polls’><value>polls</value></option>
      <option label=’Reminders’><value>reminders</value></option>
      <option label=’Search’><value>search</value></option>
      <value>news</value>
      <value>search</value>
         …
</x>

  • each form is denoted by a “type” which defines the semantics of the form. The type can be form, submit, cancel and result. In the example above, we see that the type is ‘form’; this means that the party that is submitting the form is asking the receiver to fill in the form.
  • XMPP forms can also contain multiple items; for example when you submit a Google search, Google will list multiple results in a page. All these result items contain the same structure like a text heading, a URL, a short description of the result. XMPP form can model this structure. A form of this type consist of 2 parts: a ‘header’, between a pair of <reported> tags, contains the structure of each <item> and the item itself with just the values. The following is an example of this type of form

<x xmlns=’jabber:x:data’ type=’result’>
   <title>Google Search: verona</title>
      <reported>
         <field var=’name’/>
         <field var=’url’/>
      </reported>
      <item>
         <field var=’name’>
            <value>Comune di Verona – Benvenuti nel sito ufficiale</value>
         </field>
         <field var=’url’>
            <value>http://www.comune.verona.it/</value&gt;
         </field>
      </item>
      <item>
         <field var=’name’>
            <value>benvenuto!</value>
         </field>
         <field var=’url’>
            <value>http://www.hellasverona.it/</value&gt;
         </field>
      </item>
         …
</x>

  • A XMPP form can be embedded into any of the 3 XMPP packets; the implication of this is that a XMPP form can be used in many different context for example a form can be used in an IQ packet to configure a MUC room or in a <message> packet to solicit details from a user

@DataForm Annotation

Vorpal allows you to manipulate data forms very easily through @DataForm annotation together with some powerful mapping capabilities. There are 2 use cases: the first is unmarshalling/unserializing a data form from a packet and the second is creating a data form to be returned as result.

Processing DataForm

Lets look at capturing a data form from an incoming packet. Assume we have the following incoming packet

<iq id=”F80xW-15″ to=”query@customer.batcomputer” type=”get“>
   <query xmlns=”uri:customer_query“>
      <x xmlns=”jabber:x:data” type=”form”>
         <field var=”customerId” type=”text-single”>
            <value>1</value>
         </field>
         <field var=”name” type=”text-single”/>
         <field var=”addressline1″ type=”text-single”/>
         <field var=”addressline2″ type=”text-single”/>
         <field var=”city” type=”text-single”/>
         <field var=”zip” type=”text-single”/>
         <field var=”state” type=”text-single”/>
         <field var=”phone” type=”text-single”/>
         <field var=”fax” type=”text-single”/>
         <field var=”email” type=”text-single”/>
         <field var=”discountCode” type=”text-single”/>
         <field var=”creditLimit” type=”text-single”/>
      </x>
   </query>
</iq>

In the packet example shown above, the packet contains a data form in <query>. The idea here is that we have an empty form except the customerId field. query@customer.batcomputer service will lookup the customer id (customerId field), from the database, fill in the form and return it to the submitter (data form type is form). The following code shows how we might handle this packet

@RequestScoped
@IQ
@Query(“uri:customer_query”)
public class ProcessQuery {
   @PersistenceContext EntityManager em;

   @Field(name=”customerId”, parameter=”{custId}”)
   public Object process(@Bind(“custId”) int custId) {
      Customer customer = em.find(Customer.class, custId);
      //etc. etc
   }

Lets go through the code

  1. we have a @Query (see disco blog) annotation which handles only uri:customer_query namespaced query.
  2. Next we have a @Field annotation which only fires process() method if the data form has a field call customerId. By using a @Field annotation we are assuming that the packet has a data form. Vorpal will look for a XMPP data form in the ‘usual’ places; in <iq> that ‘usual’ place translate to inside the child of <iq> packet which in this example will be in <query>. For <message> and <presence>, Vorpal will look for a data form as a direct child of <message> and <presence> packets. Any other location you’ll have to use XmlPath annotation, which is an annotation for XPath, from com.kenai.jabberwocky.framework package

Instead of using @Field to fire process(), you can also use @DataForm annotation:

   @DataForm
   public Object process() {

process() will fire if there is a data form in the packet in the ‘usual’ place. Of course that example complete ignores how we get the customer’s id which will be the subject of our next section.

Unmarshalling DataForm

There are 3 ways that you can get a data form into your message handler; the first and simplest way is to simply inject it into a DataForm object. The following is an example of how you do this

@RequestScoped
@IQ @Query(“uri:customer_query”)
public class ProcessQuery {
   @PersistenceContext EntityManager em;  
   @DataForm org.xmpp.forms.DataForm customerForm;

A second method is to inject the form into a Map (map injection). As you might have guessed, the keys of the Map are the form’s name, and the value(s) are converted into their default Java type based on the field type. The following table shows this conversion.

DataForm type Default Java type
boolean java.lang.Boolean
fixed fixed fields are ignored. Will also not appear in map injection and form binding (see below)
hidden See text-single below
jid-single org.xmpp.packet.JID
text-single java.lang.Boolean if it is ‘true’/'false’, java.util.Date if we can parse it, java.lang.Long or java.lang.Double if it is a ‘numeric’ string, java.lang.String otherwise
text-private char[] viz. an array of character. Inspired from JPasswordField
jid-multi java.util.Collection<JID>
list-multi java.util.Collection<Object> where Object will follow the conversion rule of text-single
text-multi java.util.List<String>
list-single As text-single

If the field type is missing, Vorpal will try to guess. So you can inject a data form into a Map like so

@DataForm Map<String, Object> customerForm;

or

//Using the non generic Map which is exactly the same as above
@DataForm Map customerForm;

You can also use Map<String, String>; in this case all the values will all be String. For ‘multi’ field types like text-multi, list-multi, jid-multi, the value will be a comma separated list of the field values. Besides injecting the form values into a Map, you can also get the form field’s type by specifying FormField.Type as the second parameterized type in Map. The following example shows how forms injection works

//Map the value
@DataForm Map<String, Object> customerForm;
//Map the field type
@DataForm Map<String, FormField.Type> fieldType;

for (String fieldName: fieldType.keySet()
   System.out.println(“Field name: %1$s, value: %2$s, type: %3$s”
         , fieldName, customerForm.get(fieldName), fieldType.get(fieldName));

A third way to read the value from a data form is to use forms binding. Forms binding is very similar to JAXB in that you map a data form into a Java object. The following Java object creates a binding to our customer query form example shown above

@DataForm
public class Customer {
   …
   public int getCustomerId() { …
   public void setCustomerId(int id) { …

   @FormField(name=”addressLine1″)
   public String getAddress1() { …
   public void setAddress1(String addr1) { …

   …
}

  • Firstly annotate your Java object with @DataForm to tell Vorpal that you want to use this class to bind (marshall/unmarshall) to a form. Vorpal will then try to match your JavaBean property names with the field name and copy the values from the form to the instance or vice versa. Type conversion is based on the type of the form
  • If for some reason, you need to override the above behaviour, annotate the JavaBean accessor with @FormField providing the field name that we should bind to and optionally the type
  • At the moment forms binding does not have an equivalent @XmlTransient to ignore a property

Now to bind Customer to a data form, do the following

@DataForm Customer customerForm;

Marshalling DataForm

After you have process the customer query, you’ll now need to return the form to the sender. Again the simplest way to do this is to create a DataForm object. If you do not wish to manipulate DataForm directly, Vorpal has a utility class call DataFormBuilder. Assume you would like to create the following data form

<x xmlns=”jabber:x:data” type=”form”>
   <field var=”customerId” type=”text-single”>
      <value>1</value>
   </field>
   <field var=”name” type=”text-single”>
      <value>JumboCom</value>
   </field>
   <field var=”address” type=”text-multi”>
      <value>111 E. Las Olas Blvd</value>
      <value>Fort Lauderdale</value>
      <value>33015 FL</value>
   </field>
   …
</x>

you perform do the following

DataFormBuilder builder = DataFormBuilder.create(DataForm.Type.result);
builder.field(“customerId”).textField(“1″)
      //The following is a longer version of .textField()
      .field(“name”).type(FormField.Type.text_single).value(“JumboCom”)
      .field(“address”).textField(“111 E. Las Olas Blvd”, “Fort Lauderdale”, “33015 FL”);
DataForm result = builder.build();

DataFormBuilder uses the fluent style API so using it is quite straightforward. If your form contains multiple result, DataFormBuilder handles that as well

DataFormBuilder builder = DataFormBuilder.create(DataForm.Type.result);
//Build the ‘header
builder.startReported()
      .field(“customerId”).type(FormField.Type.text_single)
      .field(“name”).type(FormField.Type.text_single)
      .field(“address”).type(FormField.Type.text_multi)
      //Other headers…
.endReported();

//For each row
builder.startItem()
      .field(“customerId”).value(“1″)
      .field(“name”).value(“JumboCom”)
      .field(“address”).values(“111 E. Las Olas Blvd”, “Fort Lauderdale”, “33015 FL”)
      …
.endItem();

//Next row
builder.startItem()
      .field(“customerId”).value(

You can also return a Map as your result. This is the reverse of the marshalling process that I’ve described above. If you return multiple result, then return a list (or any Collection) of Maps like so List<Map<String, Object>> or just List<Map>.

Finally results can also be returned using forms binding. Again if you returning multiple result using forms binding, then return a list of your objects eg. List<Customer>

Lets complete our ProcessQuery handler above using forms binding to return the result

@RequestScoped
@IQ @Query(“uri:customer_query”)
public class ProcessQuery {
   @PersistenceContext EntityManager
   @Field(name=”customerId”, parameter=”{custId}”)
   public Object process(@Bind(“custId”) int custId) {
      Customer cust = em.find(Customer.class, custId);
      if (null == cust)
         return (ErrorPacketBuilder.create(Condition.item_not_found));
      //Vorpal will default form to result if type is not specified
      return (cust);
   }
}

Since Customer supports both JPA and forms binding we must make sure that it has the appropriate annotations

@Entity // for JPA
@DataForm
public class Customer {
   …

Download the latest bundle here (look for “Latest XMPP Project” entry) if you intend to try out Vorpal.

Till next time

Screencast: Developing Discoverable XMPP Components with Vorpal

A screencast explaining how disco#info and disco#items works in XMPP. There is also a ‘live’ coding show how to use @IQ and @Query nnotation.

Comments and feedback are welcomed.

Another Screencast – Stateful Objects with Conversation

I’ve really caught the screencast bug; here is another screencast on conversation support in Vorpal. In the screencast I use Vorpal to develop an Eliza service.

Here is how it works. IM users establish a chat session with eliza@arkham.batcomputer JID (or whatever subdomain you choose to deploy it in). If the in coming messages to Eliza has <thread> element, then Vorpal can use that to establish a conversation.

To begin a ‘therapy session’ with Eliza, send to eliza@arkham.batcomputer a message with start as the message content. Vorpal will create an instance of Eliza and hold that for the duration of the conversation. When you decided to end the session, simply send it a message with quit. Vorpal will clear all the objects in the conversation’s context.

Note: the above screencast is about 16:28 mins. Not sure why Youtube thinks its 49:18 mins

I’ve blogged extensively about conversation support and the programming model in my previous posting call Conversations with Vorpal.

You can get the source code of the demo here.
Get the latest Jabberwocky bundle here.
The Eliza source used in the screencast is available from http://chayden.net/eliza/Eliza.html.

Till next time.

Screencast – Developing XMPP Services with Jabberwocky and Vorpal

I’ve decided to move to the 21st century by recording my first screencast. After hunting and testing various Linux tools, I’ve settled on recordMyDesktop.

The following 2 screencast on this blog are my effort.

So what’s the screencast about? I’ve blog extensively about XMPP and the two framework that I’ve been working on, Jabberwocky and Vorpal. I thought it’ll be nice to show how to use these frameworks.

Part 1 of the screencast talks about the various ways you can develop XMPP services.
These includes service bots, server plugin and external component. The
second segment of this part describes a use case for querying a
database using XMPP.

In part 2 of the screencast, I will show how to implement the use case described above with Jabberwocky and Vorpal along with JavaEE services including CDI and JPA.

The source for the code from part 2 can be found here.

Please provide your comments and feedbacks. Till next time.

Integrating CDI with Vorpal and the Cuckoo Bird Effect


Nest with Cuckoo bird’s egg

I first came across the insidious practices of the Cuckoo bird in Clifford Stoll’s book The Cuckoo’s Egg. The Cuckoo bird is a brood parasite. They never build any nests of their own; so when its time for them to lay their eggs, they lay their eggs in the nest of other species (of bird) whose egg resembles that of their own. Unawares, the “foster” bird will feed the Cuckoo’s nestling when they hatch. In the book Cuckoo’s Egg, a hacker used a similar method to trick the host computer to give him root access through movemail.

Fascinating stuff you say but what does this piece of trivia have to do with Vorpal? Vorpal uses a similar technique, though for benign reasons, to coax Glassfish application server into giving it what it wants – JavaEE resources (object lifecycle management, JPA, transaction, Stateless Session Bean, validation, etc). Vorpal achieve this firstly by masquerading as a Web Application and secondly by integrating with CDI. The first allows a Vorpal application to be deployed into Glassfish and the second allowed the Vorpal applications to consume container resources.

In this blog, I will show you how you can use Vorpal with CDI. Note that the Vorpal programming model that I describe here is still valid. CDI supports builds on this. This blog is not a CDI tutorial. I’ll just be listing what are the features that are supported by Vorpal. Those of you who are not familiar with CDI are encouraged to go through this tutorial before continuing.

Message Handler Lifecycle

When you are using Vorpal with CDI, all Vorpal message handler class must be annotated with either @RequestScoped or @ApplicationScoped. The semantics of these 2 annotations are similar to those in a Java EE 6 application. Vorpal also supports a third lifecycle annotation call @com.kenai.jabberwocky.framework.ConversationScoped. This annotation is conceptually similar to @javax.enterprise.context.ConversationScoped but supports XMPP conversation semantics. As conversation support is quite involved, I’ll explain this in my next blog. Vorpal does not support @SessionScoped.

Once you have annotated with any one of the 3 annotations listed, you can also use lifecycle methods like @PostConstruct and @PreDestroy.

Here is a simple example of an object using CDI

@RequestScoped @Message
@Body(“Hello {*name}”)
public class HandleMessage {
   private final String name;
   @PostConstruct void init() {
      //Do something
   }
}

As in the example above, the HandleMessage class is a request scoped object meaning that a new instance of HandleMessage will be created when there is a match and HandleMessage is selected for firing.

Note the asterisk before name in @Bind. This is a new matching feature and it denotes none or more. If you specify “Hello {name}“, then a match will include a String literal following “Hello ” in the body like “Hello Fred Flintstone“. However with an asterisk, @Body will  match “Hello ” as well. See my previous blog for matching and firing.

Resource Injection

Vorpal supports full CDI resource injection. Injection points include

Furthermore all Vorpal annotations, eg. @Body, @Message, @XmlElement, @Bind, etc. are CDI qualifiers if they are use on fields and method parameters. If you are annotating members and methods, then the @Inject annotation is optional. There are also some predefined injection types like ComponentManager, Conversation, ThreadID and ConversationContext.

@RequestScoped @Message
@Body(“Hello {*name}”)
public class HandleMessage {
   private final String name;
   @From private JID from;
   @Inject @To private JID to; //@Inject is optional
   @Inject ComponentManager mgr; //Predefined type injection
   //Constructor injection
   @Inject public HandleMessage(@Bind(“name”)String n) {
      name = ((null == n) || (n.trim().length() <= 0))? “Fred”: n;
   }
   @PostConstruct void init() {
      //Do something
   }
   //Method injection
   @Inject void setSubject(@Subject String subject) {
      —
}

From the example above

  • Notice the member injection. Since all Vorpal annotations are CDI qualifiers, the @Inject annotation is optional
  • Vorpal defines a set of injectable objects which I’ve listed above. You can inject any of these types without qualifiers; as there are no qualifiers, you have to annotate the member with @Inject
  • You can injected any valid CDI resources into constructor, member and method
  • setSubject() is an example of method injection

Capture and @Named

Vorpal works by matching incoming XMPP messages against message handlers. Captures are bound to members and parameters by the @Bind annotation. See example above. If you are using Vorpal with CDI, you can continue to use @Bind to bind capture values; if however you are a CDI purist, you can use @Named instead. Every capture export themselves as @Named. These @Named objects have a slightly different semantics to the regular JavaEE @Named objects in the following ways:

  1. Capture @Named are local to the class – viz. they are not visible outside of the class
  2. Capture @Named are bound to the ‘nearest’ capture – viz. members and methods injection capture @Named are bound to class level capture and a method parameters capture @Named are bound that method capture

Here is a simple example to illustrate the point

@RequestScoped @Message
@Body(“Hello {*name}”) @From(“{from}@jabber.org”)
public class HandleMessage {
   private final String name;
   //Member level capture, bound to class
   //’name’ is only visible in HandeMessage class
   @Inject @Named(“name“) private String name;
  
   //Method injection – also bound to class
   @Inject void setFrom(@Named(“from“) String from) {
      —
   //name is bound to capture in @To
   @To(“{name}@{__domain__}”)
   public String handleMessage(@Named(“name“)String to) {
      …
   //name is bound to this method’s @To
   @To(“info-{name}@{__domain__}”) @Subject(“{subject}”)
   public String handleInfo(@Named(“name“) String name
         , @Named(“subject“) String subject) {
      …
}

Firstly notice that the @Named member (String name) and the @Named method (setFrom) parameter injection are bound to @Body and @From from the class level. Furthermore @Named are bound to their nearest capture. So @Named(“name”) in handleMessage method will be bound to the @To annotation on that method and not to @Body. Similarly for handleInfo, its @Named(“name”) will be bound to its @To annotation. If my explanation is a little confusing, you can see the various @Named association above from their colours. Another simple way of deciding which capture @Named is bound to which capture is to place your finger on the @Name, eg. on @Named(“name”) on handleInfo, and move up. The first capture with the same name that you encounter will be bound to that @Named. In this case, the it will be @To(“info-{name}@{__domain__}”).

One other point is that message handler methods are not annotated with @Inject. In the above example handleMessage and handleInfo are message handler methods because they do not have @Inject. If these methods were annotated with @Inject, then they would be invoked when HandleMessage is instantiated.

JavaEE 6 Resources

Once a message handler are under CDI control, the message handler can access all of the JavaEE’s platform resources via injection. I’ll not go into defining JavaEE resources like JPA, Stateless Session Bean, etc. The following code shows how you use JPA from within a message handler.

@RequestScoped @Message
@Body(“Hello {*name}”) @From(“{from}@jabber.org”)
public class HandleMessage {
   //Injecting EntityManager
   @PesistenceContext EntityManager em;
   private final String name;
   @Inject @Named(“name“) private String name;
   …

The latest bundle of Vorpal and Jabberwocky container can be found here. As of this blog, the latest bundle (Merdeka 2011) contains Glassfish containers, NetBeans plugin, Vorpal framework JAR (if you are not using NetBeans) and demo code. There are 2 demo code; the first Eliza demonstrate conversation support; however I feel that this is NOT a very good example and I’ll update it in the next release. The second is query, which basically shows using JPA from within a message handler. The persistence unit points to the default customer database on Derby/JavaDB. Both of these are NetBeans project so they should compile and deploy with out problem if you are using NetBeans (7.0 and 7.0.1).

There is a bug in the Jabberwocky container which prevents 2 or more Vorpal applications to be deployed at the same time. I’ll hopefully fix this in the near future.

CDI support for Vorpal is enabled in the usual way by adding a file call beans.xml to WEB-INF directory.

I’ll talk about conversation support in my next blog.

Vorpal Framework – A Second Try

After releasing the first version of Vorpal framework, I re evaluated at the programming model and felt that it was a little too limited. As I’m not a very experienced API designer, I relooked at JAX-RS (which Vorpal is based on) and CDI (which I hope to integrate with in the next release). I got some ideas from those API which I’ll outline in this blog.

Capturing Message Elements

Assuming we are going to process the following incoming message

<message
    from=’romeo@shakespeare.lit/orchard’
    to=’juliet@capulet.com’
    type=’chat’>
  <thread>act2scene2chat1</thread>
  <body>
    I take thee at thy word:
    Call me but love, and I’ll be new baptized;
    Henceforth I never will be Romeo.
  </body>
  <active xmlns=’http://jabber.org/protocol/chatstates’/&gt;
</message>

We write the following handler

@Message @To(“juliet@capulet.com”)
public class ToJuliet {
   @From(“romeo@{anydomain}”) @Body(“{body}”)
   public String processToJuliet(@Bind(“body”) String body) {
      return (“*Sigh* Oh Romeo – ” + body.toUpperCase());
   }
   @From(“{everyone}@{anydomain}”)
   public String processEveryoneElse(@Bind(“everyone”) String others) {
      return (other + “, you are not my Romeo”);
   }
}

First off, the @Message indicates that this class is a message processor. The @To, @From and @Body annotations at the class and methods are pattern matcher. These matchers look for certain patterns in the incoming message (elements and attributes) and if the message attributes and elements match these patterns, then that particular handler (class) will be selected.

In this example, we have a class level matcher; for ToJuliet handler to be ‘fired’, the incoming message must be addressed to juliet@capulet.com. Happily for us, it is. The next step is to find which method we should use. Again we examine the annotations from more specific (more annotations) methods to more general. In this case we examine processToJuliet() first followed by processEveryoneElse() (see Method Resolution in this blog).

You can specify how an annotation should match the message by specifying a pattern string. In @From(“romeo@{anydomain}”), we say that the incoming from JID must match the literal string ‘romeo@’ and the remainder of the JID is to be captured by {anydomain}. For our sample message, the from JID matches ‘romeo@’ and ‘shakespheare.lit/orchard’ is captured by {anydomain}. So we select processToJuliet() for handling the message.

If you wish to use what is capture in the method then you use a @Bind (previously known as @Parameter) annotation to bind the capture to a parameter. Since we are going to use the body of the message, we specify @Body(“{body}”) to capture the contents of the body and then bind that to the formal parameter body with @Bind(“body”). For a detailed discussion on capture see Example 2 in this blog.

Anyone else besides Romeo sends a message to Juliet, then that message will be handled by processEveryoneElse().

Injecting Values

Up till this point, all values that we are using are from capture viz. we use @Bind to map an attribute to a parameter. This way of getting values from the incoming message forces you to match every attributes and elements.

Vorpal supports message attributes and elements injection. Suppose you would like the message body to be available to processEveryoneElse() without matching it, you can do the following

@From(“{everyone}@{anydomain}”)
public String processEveryoneElse(@Bind(“everyone”) String others, @Body String body) {
   …

If you want chatstates to be available to all the methods in ToJuliet, you can inject it into a member like so

@Message @To(“juliet@capulet.com”)
public class ToJuliet {
   @XmlElement(uri=”
http://jabber.org/protocol/chatstates“) private Element chatstates;
   …

In the above example, if there is a chatstate element in the incoming packet, the it’ll be injected into Element. Furthermore you can inject most values into several different types of object depending on how you use them. For XML elements , you can either inject it into an Element, or a String type, or a JAXB object. Since XMPP messages are XML documents, you can use XmlElement to inject any part of the message into a member or a parameter.

Some elements can be injected into specific type eg. the from and to JID can be injected into JID type, <thread> can be injected into ThreadID, etc. I’ll list all the available mappings in a future blog.

Finally you can also inject class level capture into field as well as formal parameters. Here is an example of injecting chatstates into a field

@Message @To(“juliet@capulet.com”)
@XmlElement(parameter=”{chatstates}”, uri=”
http://jabber.org/protocol/chatstates“)
public class ToJuliet {
   @Bind(“chatstates”) private Element chatstates;
   …

There are a few predefined capture that Vorpal automatically provides

  • __domain__ – the domain of the deployed component
  • __packet__ – the current Message
  • __componentManager__ – the ComponentManager
  • __conversation__, __threadID__, __conversationContext__ – used for conversation support which I will discuss in the next section

For example if you wish to have access the entire message, simply inject it into Message type

@Message @To(“juliet@capulet.com”)
public class ToJuliet {
   @XmlElement(uri=”
http://jabber.org/protocol/chatstates“) private Element chatstates;
   @Bind(PredefinedBindings.PACKET) Message message; //__packet__

One final note before we leave the value injection topic, it may be a little confusing with Vorpal annotation. After all you could use an annotation like @Body as a pattern matcher as well as an injection point. One good way to remember is that if an annotation is use to annotate a class or a method, then its a pattern matcher; and if the same annotation is use to annotate a field or a formal parameter then its an injection point.

Conversation Support

One of the feature in XMPP Message is to be able to support session or conversation thread. To participate in a conversation , all exchanged messages between the various parties must have the <thread> element; furthermore all <thread> must have the same thread id. An example of a threaded message is shown at the start of this blog. For more information on conversation see Best Practices for Message Threads.

Vorpal has built-in support for threads or conversation. So what is the benefit of conversation support? Simply put, stateful objects. In all our examples so far, the objects are request scoped. With every new request, Vorpal will create a new instance of a handler to process the message. This makes keeping track of state crumblesome.

With conversation support, the same instance of message handler will be used, if it the message matches the annotations. So you can keep states in the message handler. To use conversation, you have to inject Conversation type into your handler. Here is an example of how you do it

@Message @To(“juliet@capulet.com”)
public class ToJuliet {
   @Bind(PredefinedBindings.CONVERSATION) private Conversation conversation;
   private StringBuilder messageLog;
   @Body(“start”)
   public void startLog() {
      if (conversation.isTransient()) {
         conversation.begin();
         messageLog = new StringBuilder();
      }
   }
   @Body(“end”)
   public void endLog() {
      if (!conversation.isTransient()) {
         conversation.end();
         //Do something with messageLog
         …
      }
   }
   @From(“romeo@{anydomain}”) @Body(“{body}”)
   public String processToJuliet(@Bind(“body”) String body) {
      String result =
“*Sigh* Oh Romeo – ” + body.toUpperCase();
      if (null != messageLog)
        messageLog.append(result).append(“\n”);

      return (result);
   }

To start a logged session with Juilet, we have to first send juilet@capulet.com a message with the word start. This will trigger the handler to mark the conversation as started.

The conversation semantics is the same as CDI. See this tutorial if you are unfamiliar. Conversation have to be enabled explicitly by invoking Conversation.begin(). To end the conversation, call Conversation.end(). When you invoke end(),  Vorpal will add the gone chatstate

<gone xmlns=’http://jabber.org/protocol/chatstates’/&gt;

in the reply message back.

Conversation support is really about both communication parties honouring the <thread> element. In some situation, the incoming message do not have the <thread> element. You can still invoke Conversation.start() and Vorpal will insert a <thread> element, with a randomly generated id, in the reply message. However it is up to the client to decide if the next message will contain the <thread> element. If the client does not reply in kind, then there will be no conversation support.

You can find out if an incoming message have the required <thread> element by injecting ThreadID type.

@Message @To(“juliet@capulet.com”)
public class ToJuliet {
   @Bind(PredefinedBindings.CONVERSATION) private Conversation conversation;
   @Bind(PredefinedBindings.THREAD_ID) private ThreadID threadId;
   private StringBuilder messageLog;
   @Body(“start”)
   public void startLog() {
      if ((null != threadId) && conversation.isTransient()) {
         conversation.begin();
         messageLog = new StringBuilder();
      }
   }

Conversation support is not just limited to one handler. Let say you have more that one message handler class in your application; now if one or more of these message handlers are selected for ‘firing’ then all of these will be grouped under the same conversation. When you end the conversation, all these objects will also be destroyed. The ConversationContext type allows all message handler instances from the same conversation to share data among themselves. ConversationContext behaves very much like HttpSession. The ConversationContext is also injected into your message handler. One caveat is that ConversationContext is available only after the start of a conversation, viz at the point when you invoke Convesation.start() the injected ConversationContext member will be null. It is available in the next message handle cycle. I do currently have a solution (more injected objects!) but I’ve not implemented it.

The latest Jabberwocky bundle is available here. If you are trying it, let me know what you think. I’ve not tested it extensively yet so I’m sure there are a few bugs lurking. Let me know of them as well.

My next plan for Jabberwocky is to implement CDI support. I’ve got some code in but its still not working. With CDI, I hope to

  • provide a richer injection model
  • to allow message handlers to access JavaEE resources such as Stateless Session Bean, EnityManager, etc.

Till next time

Writing External Components (for Jabberwocky) with NetBeans

I’ve been working on a NetBeans plugin for the past few weeks. I wanted the plugin because I wanted a place where you could develop, debug and deploy Jabberwocky external components. Download the latest package here. Select the Mayday 2011 download.
The package contains the following

  1. xmpp-gf-container.jar, jabberwocky_support.jar – the latest and greatest Jabberwocky container. I’ve hope to avoid updating the containers but certain issues (see below) have forced me to make changes to the container. See here on how to install the containers if you are new to Jabberwocky.
  2. update directory – this directory contains NetBeans plugin and also the Vorpal framework binaries which I talked about in my previous blog entry

Before I begin I have to say that I have made some rather major modifications to Jabberwocky packaging. Previously, it Jabberwocky components are XAR packages which is basically a JAR file. It is now a WAR package, yes it’s a JavaEE 6 compliant Web ARchive. There are 2 main reason for this change, the first is to do with Glassfish’s architecture (which sort of prevents me from doing certain things); the second is that make this change will allow me to work better with other Glassfish container. Also having a standard WAR package it really makes writing the NetBeans plugin a lot easier.

Installing NetBeans Plugin

The plugin is written for the latest version of NetBeans 7.0. (Don’t even bother trying it on any version other than 7.0). Startup NetBeans 7.0, go to Tools | Plugins | Downloaded | Add Plugins… Navigate to the update directory and select all the NBMs files as shown in the diagram below.


If this or any subsequent images is not clear, right click on the image and select View Image

Creating Jabberwocky External Component

Create a Web application in NetBeans. Select File | New Project | Java Web | Web Application. See diagram below

Select Next for the next 2 screens entering the relevant details for your web application like project name, context path, etc. Then you will come to the fourth screen which is the Frameworks screen as shown below

Select Jabberwocky framework. What this will now do is add the relevant libraries and deployment files into the WAR package. First choose the type of component

  1. Jabberwocky framework – this the the Vorpal framework. If you select this you do not have to fill in the package and class name. The framework will handle that for you
  2. AbstractComponent – selecting this means that you intend to create your external component by extending com.xmpp.component.AbstractComponent abstract class. Enter the package and class name that will extend AbstractComponent.
  3. Component – selecting this means that you intend to implement org.xmpp.component.Component interface. Enter the package and class name that will implement Component.

If your component has any properties, click on the Properties tab and enter the properties as name/value pair. Click Finish to complete the setup.

NetBeans will now display the project and open the xep-0114.xml configuration file.

If xep-0114 file is not opened in the editor area, double click on xep-0114 file in the project window to your left. The editor allows us to configure our external component when we deploy to Jabberwocky. Right at the top is the main component class. If you are using Vorpal (Jabberwocky framework), then you should not change the default class (com.kenai.jabberwocky.core.JabberwockyComponent). Otherwise if you are using the other two types of components, then the fully qualified class name will be display here and you can change this. But remember you can only deploy one external component per WAR package.

Next comes the subdomain properties. This is the subdomain that your component is going to deploy to. Enter the subdomain name, domain and the port number. The Shared secret field is disable. What this means is that you have defined the subdomain in Jabberwocky using the asadmin create-xmpp-subdomain; see this blog.

However if you want to automatically create the subdomain as you deploy the external component, select Create subdomain checkbox. This will enable the Shared secret field. Enter the shared secret of your subdomain (eg. landofthegiants from above is uppercase) or leave it blank to use the default shared secret. Note that this option only creates the subdomain definition in Jabberwock and not with the XMPP server. The Cleanup checkbox ask Jabberwocky to cleanup the subdomain definition when you undeploy your component.

Now you can write your component. If you are using Vorpal, then you need to write some message handlers. My previous blog gives a brief tutorial on using Vorpal.

If you are using AbstractComponent or Component, then the plugin will generate an appropriate template for you.

You need to also ensure that the Glassfish instance that you are deploying to supports Jabberwocky. To check if the Glassfish instance supports Jabberwocky, right click on the project node (eg. EchoUpperCaseComponent in the diagram above) and select Properties. The following dialog box will open.

The Server combo box will show a list of Glassfish instances that supports Jabberwocky. If the Glassfish instance that you have chose as your deployment server supports Jabberwocky, then that instance will be displayed here. If however you have accidentally selected Tomcat, then this combo box will be blank. Pull down the combo box to see which instance supports Jabberwocky. Also changing this do not change the actual deployment server of the web project. (I’ll fix this one day). You have to select Run under Categories and chose a Glassfish instance that matches this combo box.

Finally you are ready to deploy. Right click on the project node and select Deploy.

If all goes well you will see some communication between your component and the XMPP server in the output window.

If you switch over to the Services tab, you should also see your component deployed under Applications.

Note: if you fail to see any communications between your component and the XMPP server and you are sure its not because of your component, then undeploy your component from Glassfish. Open the build.xml file and save it. Then build and redeploy your component.

With this plugin I hope to make external component development on Jabberwocky easier. In my next blog I’ll show you how you can add external component to an existing WAR file.

Till then, give me feedbacks (love it, indifferent, sucks). If you discover any bugs send me a comment or file a bug at the Jabberwocky home.

Follow

Get every new post delivered to your Inbox.

Join 54 other followers