Receiving PEP Broadcast

In my last blog, I talk about PEP and how you can publish your own PEP events with
Smack. In this blog I will talk about how to hand incoming PEP
messages. First we look at how a PEP packet looks like.

<event xmlns=”http://jabber.org/protocol/pubsub#event”&gt;
   <items node=”urn:xmpp:gaming:0″>

      <item id=”L5xpMkzWopMPK2AtuBUj”>
  
      <game xmlns=”urn:xmpp:gaming:0″>
         <character_name>Sentor</character_name>
         <character_profile>http://wow.example.com/profile.html?123456</character_profile&gt;
         <level>66</level>
         <name>Worlds of Warefare</name>
         <server_address>wow6.example.com</server_address>
         <server_name>WOW Example</server_name>
         <uri>http://wow.example.com</uri&gt;
      </game>
   </item>
   </items>
</event>

The message that we are interested in is in orange. We need to do 2 things to get to this part of the message

  1. Write a parser or provider for <game>. The parser will convert the XML fragment to Game object (see last weeks blog).
  2. Register the provider with Smack’s provider framework so that our provider gets call whenever there is a <game> tag. (actually its not like that but its easier to think of it this way…)

Writing a Provider

A provider is basically a parser for the bits in orange and it returns a GameItems object. Here is how our GameProvider looks like

public class GameProvider implements PacketExtensionProvider {
   public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
      boolean stop = false;
      int evtType;
      String n;
      String id = null;
      Game game = new Game();
      while (!stop) {
         evtType = parser.next();
         n = parser.getName();
         switch (evtType) {
            case XmlPullParser.START_TAG:
               if (“item”.equals(n))
                  id = parser.getAttributeValue(“”, “id”);
               else if (“character_name”.equals(n))
                  game.setCharacterName(text(parser));
               else if (“character_profile”.equals(n))
                  game.setCharacterProfile(new URI(text(parser)));
              
               break;
            case XmlPullParser.END_TAG:
               //Stop parsing when we hit </item>
               stop = “item”.equals(n);
               break;
         }
      }
      return (new GameItems(new GameItem(id, game));
   }
}

Things to note about

  1. A provider must implement the PacketExtensionProvider interface which has only one method, parseExtension()
  2. Your parser is responsible for parsing all XMLs between the opening and closing <item> tag.
  3. Don’t forget to get the id from the <item> tag
  4. Once you are done, wrap the Game object in a GameItem and GameItems object.

What is the GameItems object? GameItems is responsible for wrapping our Game object inside an <event> viz. the blue bits in the XML fragment at the start of this blog. Furthermore GameItems must extend PEPEvent class. Here is an implementation

public class GameItems extends PEPEvent {
   private final GamePEPItem item;
   public GameItems(GamePEPItem i) {
      item = i;
   }
   public GamePEPItem getGameItem() {
      return(item);
   }
   @Override
   public String getNamespace() {
      return (“http://jabber.org/protocol/pubsub#event&#8221;);
   }
   public String getNode() {
      return (“urn:xmpp:gaming:0”);
   }
   public String getItemDetailsXML() {
      return (item.toXML());
   }
   @Override
   public String toXML() {
      StringBuilder sb = new StringBuilder(“<event xmlns=\””);
      sb.append(getNamespace()).append(“\”><items node=\””);
      sb.append(getNode()).append(“\”>”);
      sb.append(getItemDetailsXML());
      sb.append(“</items></event>”);
      return (sb.toString());
   }
}

I know it is a bit confusing with layers of objects, hopefully the following illustration will help clarify this

<event xmlns=”http://jabber.org/protocol/pubsub#event”&gt; <– GameItems extends PEPEvent
   <items node=”urn:xmpp:gaming:0″> <– generated from GameItems
      <item id=”L5xpMkzWopMPK2AtuBUj”> <– GameItem extends PEPItem
         <game xmlns=”urn:xmpp:gaming:0″> <– Game
           
         </game>
      </item>
   </items>
</event>

Registering and Receiving PEP Events

In order to receive PEP messages, we must register our interest by
providing a provider (parser) and the namespace associated with the
provider. Here is a code snippet to show how this is done

PEPProvider prov = new PEPProvider();
prov.registerPEPParserExtension(“urn:xmpp:gaming:0”, new GameProvider());
ProviderManager.getInstance().addExtensionProvider(“event”, “http://jabber.org/protocol/pubsub#event&#8221;, prov);

PEPProvider is part of the PEP framework that allows you to indicate you interest in some or all PEP objects. Line 2 associates User Gaming namespace with our provider; you can register your interest in more that one namespace. The next step is to add the PEPProvider
to the overall Smack provider framework. Here the registration is very
specific, boilerplate in fact; you basically tell Smack that your
instance PEPProvider are taking over control of parsing any <event> tag that is in http://jabber.org/protocol/pubsub#event namespace
(line 3). (Note: I’m not sure what the ramifications are if there are
other providers that are also interested in the same namespace.)

The final piece of code snippets show how to add listeners (implements PEPListener).

XMPPConnection conn = … //Create an instance of XMPPConnection
PEPManager pepMgr = new PEPManager(conn);
pepMgr.addPEPListener(this); //this being PEPListener

public void eventReceived(String from, PEPEvent pEvt) {
//Cast it to GameItems object. pEvt is return from GameProvider
GameItems items = (GameItems) pEvt;
Game game = items.getGameItem().getGame();

That’s it! Feebacks and happy hacking!

Advertisements

8 Responses to Receiving PEP Broadcast

  1. Brett Delia says:

    Hey there,

    I have read your XMPP PEP blogs posts regarding pub/sub, https://oneminutedistraction.wordpress.com/tag/java-xmpp-jabber-smack-pep-xep163-196-user-gaming/.

    I have tried to implement the ideas in a proof of concept command line application. I do not seem to be catching any PEPEvents though and I am wondering if there is anything you might point me to to assist? I realize this is a bit vague without source code, I would be happy to send you some if you are interested and if that would help.

    Thanks
    Brett Delia

    • Brett, if you are using Smack, have you tried turning on debugging to see if the stanzas are coming back?
      My source code for XMPP user gaming can be found here http://kenai.com/projects/jabberwocky. The source code is under XMPPUserGaming. I’ve written this as a plugin for Spark which you can download from the Download area. The XMPPUserGaming is separated into 2 main packages, specific to Spark and XMPP user gaming which is more generic. HTH

      • Brett Delia says:

        Thanks for the reply. First, your blog posts on this subject are what got us working, we really appreciate your insights and willingness to document your experiences.

        I will definitely go through your source to see how you put it all together to verify we have everything wired up correctly. We ended up getting it to work finally, we had some initial issues with the fact that we needed to define two separate parsers (providers) and were initializing them incorrectly at first. We assumed, through lack of documentation, that we would need to create two distinct providers. Turns out you just need to register the PEP Parser Extention for each provider on the same Provider. That got use working.

        Original code:
        PEPProvider lineItemProv = new PEPProvider();
        prov.registerPEPParserExtension(“urn:xmpp:lineitembom:0”, new PepMessageProvider());
        PEPProvider visiBomProv = new PEPProvider();
        prov.registerPEPParserExtension(“urn:xmpp:visibom:0”, new PepMessageProvider());
        ProviderManager.getInstance().addExtensionProvider(“event”, “http://jabber.org/protocol/pubsub#event”, lineItemProv );
        ProviderManager.getInstance().addExtensionProvider(“event”, “http://jabber.org/protocol/pubsub#event”, visiBomProv );

        Code that works:
        PEPProvider bomProv = new PEPProvider();
        prov.registerPEPParserExtension(“urn:xmpp:visibom:0”, new PEPVisiBOMMessageProvider());
        bomProv .registerPEPParserExtension(“urn:xmpp:lineitems:0”, new PepMessageProvider());
        ProviderManager.getInstance().addExtensionProvider(“event”, “http://jabber.org/protocol/pubsub#event”, bomProv );

      • That is how I did it as well.

  2. Brett Delia says:

    I can’t seem to get to the source. The repository seems empty, though it could be that I do not understand how to use Kenai. I put this into my browser after I logged in: https://hg.kenai.com/hg/jabberwocky~source but see no source tree.

  3. Stan says:

    Reference: Registering and Receiving PEP Events:
    (line 3). (Note: I’m not sure what the ramifications are if there are
    other providers that are also interested in the same namespace.)

    Within the basic PubSubManager (and I assume operation of PEP is similar) the first programmatic entity to ‘register’ to a namespace get’s the notification – the others are never registered in the Map.

  4. Pingback: asmack – receiving custom XML messages || | PHP Developer Resource

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: