Receiving PEP Broadcast
August 31, 2010 8 Comments
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”>
<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>
<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>
</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
- Write a parser or provider for <game>. The parser will convert the XML fragment to Game object (see last weeks blog).
- 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
- A provider must implement the PacketExtensionProvider interface which has only one method, parseExtension()
- Your parser is responsible for parsing all XMLs between the opening and closing <item> tag.
- Don’t forget to get the id from the <item> tag
- 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”);
}
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”> <– 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”, 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!