powered by Jive Software

Receive AdHocCommandData not totally right, how to handle this?

Receive AdHocCommandData not totally right, how to handle this?

I sent adhoc command to get user roaster using smack API, here is the returning msg in debug window.

** **

** **

** **

** **

** **

** admin@zhengkai.domain**

** **

** **

** **

however, I checked the “RAW RECEIVED PACKETS”, the packet actually received is :


you see, what I want to get, is in the part, but this part is cut off by the API?

My original xmpp messages as below:

1> request to get admin’s roaster list

2> receive the reply of server

Getting a User's Roster

Fill out this form to get a user’s roster.


3> submit the form to server



4>result, that’s in the begining of the question.

I currently use the method addPacketListener to listen IQ messages.

Is there a way to receive the xml directly in the api?

****Or how to get the original return of server but not the cut off one.



I tried another user’s roaster, and the result is the same, only in the ‘raw received packets’ on debug window, can I see the whole IQ message.



This is a weakness in AdHocCommandProvider: It does not parse the query element, in fact it doesn’t allow packet extensions at all. Logged as SMACK-605

hi can I receive the whole xml using another method if there is any? (original XML is ok for me, I can specially handle this format of xml message to get the data)

because I want the data in the tag, thx.

can I receive the whole xml using another method

No, but you could replace the AdHocCommandDataProvider with one that parses the query element (and adds it to the resulting AdHocCommandData for example as a PacketExtension).

If you come up with a good solution, that others may also would want to use, feel free to share it.

you mean, I will change the SMACK source code, and modify part of AdHocCommandDataProvider related codes?


I have added a new class AdHocCommandDataEx extends IQ

and DataFormEx implements PacketExtension,

the DataFormEx has query tag.

and also, I want to replace the iq provider with the old one like this

ProviderManager.getInstance().addIQProvider(AdHocCommandDataEx.ELEMENT, AdHocCommandDataEx.NAMESPACE, AdHocCommandDataEx.class);

but now, exception occured, the new provider may not substitude the old one,

do anyone know how to solve this?

By the way , I didnot know how to change the Smack source code, and make a temp edition.

Could anyone give a hand? Thanks very much!

I have added a new class AdHocCommandDataEx extends IQ

and DataFormEx implements PacketExtension,

the DataFormEx has query tag.

You don’t need a new AdHocCommandData class, use the existing one. Instead you write a AdHocCommandDataProvider class that parsers the query element to an PacketExtension and adds this extension to the AdHocCommandData IQ via addPacketExtension. You can later retrieve the extension via getExtension(String,String).

There are no modifications of the source code necessary to achieve that.

This is interesting. XEP-0004 does not define any extensions in Data Forms, nor does XEP-0050.

The only place I saw it is in Example 32 of XEP-0133, but… it’s just an example without a real specification.

There are some defined extensions for Data Forms, but they are all well specified in their own XEP. (e.g. XEP-0122, XEP-0221)…

Therefore I am just wondering about this issue.

Ahh right. Imissed that the query was embedded into the data form.

Hi I have fixed the issue by adding a new item in form. And replace the following 2 kinds of provider.

ProviderManager.getInstance().addIQProvider(AdHocCommandDataEx.ELEMENT, AdHocCommandDataEx.NAMESPACE, new AdHocCommandDataProviderEx());

** ProviderManager.getInstance().addExtensionProvider(DataFormProviderEx.ELEMENT, DataFormProviderEx.NAMESPACE, new DataFormProviderEx());**

Now, in my IQ listener, I can catch the user roaster items in the branch as below:

if(iq instanceof AdHocCommandDataEx) { … }

**I’m wondering if there is any impact on other kinds of IQ?
AdHocCommandDataEx.java.zip (1604 Bytes)
AdHocCommandDataProviderEx.java.zip (1227 Bytes)
DataFormEx.java.zip (2021 Bytes)
DataFormProviderEx.java.zip (1503 Bytes)
RoasterItemEx.java.zip (716 Bytes)

here shows the iq content


May this solution ok?

May this solution ok?

If it works for you, sure.

But I think you are modifying to much of Smack. Smacks modular design allows to replace existing components with help of the API. It would have been sufficient to subclass DataForm and replace DataFormProvider.

AdHocCommandData use DataForm as private data, so I think not only DataForm but also AdHocCommandData has to be modified. And so is the providers.

Do you agree?

No, I don’t agree.

The query element is part of the DataForm which is retrievable via AdHocCommandData.getForm. I would have simply extended DataForm to contain further PacketExtensions (List) and put the information from the query element within such a PacketExtension. All you need to touch in this case is DataForm and DataFormProvider.

sorry I’m not quite clear.

But I found that class AdHocCommandData has a property “private DataForm form;”

I just wonder if I have a subclass of DataForm , but in AdHocCommandData, the decode of xml is the same as before, so nothing will come out .

I’ve done some tests upon your advice, but the is not decoded out because of the reason described.

but in AdHocCommandData, the decode of xml is the same as before, so nothing will come out .
Not if you overwrite toXML() in your DataForm subclass.

Thanks for your reply! But I still not very clear.

I overwrote the method in DataForm subclass.

public String toXML() {

StringBuilder buf = new StringBuilder();

buf.append("<").append(getElementName()).append(" xmlns="").append(getNamespace()).append(

“” type="" + getType() +"">");

if (getTitle() != null) {



for (Iterator it=getInstructions(); it.hasNext():wink: {



// Append the list of fields returned from a search

if (getReportedData() != null) {



// Loop through all the form fields and append them to the string buffer

for (Iterator i = getFields(); i.hasNext():wink: {

FormField field = (FormField) i.next();



// Loop through all the items returned from a search and append them to the string buffer

boolean hasItem = false;

  •    StringBuilder bufQuery = new StringBuilder();*
  •    for (Iterator i = getRoasterItems(); i.hasNext();) {*
  •        RoasterItemEx item = (RoasterItemEx) i.next();*
  •        bufQuery.append(item.toXML());*
  •        hasItem = true;*
  •    }*
  •    // if has items then handle this*
  •    if (hasItem)*
  •    {*
  •        buf.append("<query xmlns=\"jabber:iq:roster\">");*
  •        buf.append(bufQuery);*
  •        buf.append("</query>");*
  •    }*


return buf.toString();


but toXML() is not called by AdHocCommandDataProvider:parseIQ

else if (elementName.equals(“x”) && namespace.equals(“jabber:x:data”)) {

adHocCommandData.setForm((DataForm) dataFormProvider.parseExtension(parser));


dataFormProvider is DataFormProvider, not the subclass.

So toXML will never be called… Do you miss that? Or…

See https://github.com/Flowdalic/Smack/commit/9016120d718ef9142cebf16af39009ad4e4be8 9a for my minimal invasive fix for SMACK-605. That’s all that’s required. You can now retrieve the information from the “query” element within the data form as RosterPacket with

AdHocCommandData data = …

RosterPacket packet = (RosterPacket) data.getForm().getExtensionElements().get(0);

Yes, this is the minimal fix for the bug.

I’m now wondering how to pack a smack jar, could you plz tell the way to pack one?

I think if I change the codes in smack, I would not have to change that much codes, and can customize my smack jar, thx!

plz refer to :