powered by Jive Software

Packet extensions not being sent in xml

Hi

I would be grateful if you could help me. I downloaded the latest smack 1.1.1 as I noticed that you can add extensions to Packet objects. (i.e custom xml)

I created a DefaultPacketExtension object with my custom namespace xml, and confirmed this with the toXML() method.

I attached this to the my Packet object (an IQ object) with the addExtension method. However my extension isn’'t getting sent, only the basic IQ stanza. (I confimed this with the debug window and with the toXML method of the IQ object.

Thanks

john,

There was a bug with the DefaultPacketExtension handler code in 1.1.1. I’‘m not positive it’‘s the same issue from your description, but I’'d recommend trying out the latest daily build to see if that solves the issue. Daily builds are at:

http://www.jivesoftware.com/xmpp/smack/dailybuilds.jsp

If that doesn’‘t fix the problem I’'ll investigate further. Let me know how it goes!

Thanks,

Matt

Thanks for your prompt reply Matt. I got the latest build and it’'s no different. Here is my code:

IMUser user=null;

try

{

user=new IMUser(“john”, “pass”, “machine”, 5222);

}

catch (XMPPException e) { e.printStackTrace(); }

IQ iqPacket=new IQ();

iqPacket.setType(IQ.Type.SET);

iqPacket.setPacketID(“humm”);

DefaultPacketExtension query=new DefaultPacketExtension(“query”, “hcl:iq:admin”);

query.setValue(“corpgroups”, “value”);

iqPacket.addExtension(query);

// sanity check…

System.out.println("query xml: "+query.toXML());

System.out.println("packet xml: "+iqPacket.toXML());

user.sendPacket(iqPacket);

// wait for packets to be processed

try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); }

user.logoff();

System.out.println(“Logged off.”);

IMUser is a class which just handles the connection object (creating, login etc), sendPacket calls same on XMPPConnection object.

From debug window and toXML method of packet, all that is being sent is:

Am I doing something wrong with this extension stuff? I want to send:

value

Hi John,

First, if you could surround your java code with code goes here (without spaces between the brackets and ‘‘code’’) you’'ll get your java code pretty printed.

Second, I’'d highly recommend moving all your code into the try-catch block. This will prevent your code that relies on the user object from running if the user creation fails.

Last, and most important to your actual question, IQ is a special XMPP packet. According to the standard, IQ packets can only have one child element. So the general Packet.add/getExtension mechanism is NOT used by the IQ packet. Instead, IQ has a getChildElementXML() method that returns null indicating no extensions by default.

To create an IQ packet with your own XML inside of it, extend IQ and produce your XML string in the overridden getChildElementXML() method. For example:

public class IQAdmin extends IQ {   private String corpGroups;
    public IQAdmin(String corpGroups){
    setCorpGroups(corpGroups);
  }   public void setCorpGroups(String corpGroups){
    this.corpGroups = corpGroups;
  }   public String getCorpGroups(){
    return corpGroups;
  }   // Overrides IQ.getChildElementXML() to provide extension text.
  public String getChildElementXML(){
    StringBuffer buff = new StringBuffer("<query xmlns=''hcl:iq:admin''><corpgroups>");
    if (corpGroups != null){
      buff.append(corpGroups);
    }
    buff.append("</corpgroups></query>");
    return buff.toString();
  }
}

Then use it like this:

try {
  IMUser user=new IMUser("john", "pass", "machine", 5222);
  IQ iqPacket=new IQAdmin("value");
  iqPacket.setType(IQ.Type.SET);
  iqPacket.setPacketID("humm");   // sanity check..
  System.out.println("packet xml: "+iqPacket.toXML());
  user.sendPacket(iqPacket);   // wait for packets to be processed
  try {     Thread.sleep(5000);   } catch (InterruptedException e) { e.printStackTrace(); }   user.logoff();
  System.out.println("Logged off.");
} catch (XMPPException e) { e.printStackTrace(); }

Hope that gets you back up and running!

-iain

Iain,

Do you think I should throw a RuntimeException if addPacketExtension is called on an IQ class? That might let people know there is an issue a bit more easily. Another option would be to make IQ not extend Packet. It’'s a tricky problem in general…

-Matt

Matt,

I agree. I was looking at it and wondering how to make the API enforce correct behavior. Perhaps we should remove the *PacketExtension methods from Packet and create a new sub-class “ExtensiblePacket” or something with the *PacketExtension methods, and then make Message and Presence descend from ExtensiblePacket. That leaves the common Packet methods (root element attributes) for IQ to extend. Downside is it complicates and deepens the heirachy for Message and Presence but it may be worth it in a cleaner separation between Message/Presence and IQ.

Also, I was wondering if IQ should be an abstract class with the getChildElementXML() method abstract? That way no-one will be creating IQ improperly, and will be told by the compiler if they aren’‘t overriding it correctly (because they aren’'t supplying their own getChildElementXML() method)… I suppose it does complicate things if you want to make a simple result IQ though…

-iain

Thanks to both of you for your help. I started to do it manually but will probably revert back to smack with this advice, especially since I can more easily control recieving pakets through smack - i.e errors etc.

Withregards to the scenario, I’'m thinking the three packet types are natural subclasses of Packet. Could you just overidde the addExtension method of IQ to just accept one extension - i.e overwrite any existing extension in the list. Short word about it in the JavaDoc should be enough, given that it is required in the jabber protocol.

The library has come in very handy for us here, especially for load tetsing our server. Keep up the good work!

John,

It’‘s a good suggestion. I played around with it and agree that overriding and making addExtension just replace existing extensions (if any) is probably the cleanest solution. I’'ll file an issue to have it changed in future releases of Smack.

-iain