400 bad request when retrieving pubsub messages

Hi. I am trying to use the smack api and pubsub to retrieve persisted pubsub messages but I am getting a 400 bad request error instead of the list of messages. I have a node named theNode created that has a number of messages associated with it. I have verified that the node and messages exists on the openfire server using the xml console in psi. I am using the latest svn of the smack api and the latest binary release of openfire. I am using the following code.

import java.util.*;
import org.jivesoftware.smack.*;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.pubsub.ConfigureForm;
import org.jivesoftware.smackx.pubsub.AccessModel;
import org.jivesoftware.smackx.pubsub.FormType;
import org.jivesoftware.smackx.pubsub.LeafNode;
import org.jivesoftware.smackx.pubsub.PubSubManager;
import org.jivesoftware.smackx.pubsub.Node;
import org.jivesoftware.smackx.pubsub.listener.*;
import org.jivesoftware.smackx.pubsub.*;
import org.jivesoftware.smackx.pubsub.PayloadItem;
import org.jivesoftware.smackx.pubsub.Node;
import org.jivesoftware.smackx.packet.DiscoverItems;
import org.jivesoftware.smackx.packet.DiscoverItems.Item;
        ConnectionConfiguration config = new ConnectionConfiguration("mymachine", 5222);
XMPPConnection connection = new XMPPConnection(config);
connection.connect();
connection.login("notify@mymachine", "");
PubSubManager manager = new PubSubManager(connection, "pubsub.mymachine"); LeafNode myNode = (LeafNode) manager.getNode("theNode"); Collection<? extends org.jivesoftware.smackx.pubsub.Item> items = myNode.getItems();

However, when I run this I get a bad request 400. I have looked at the packet being sent to the server for the getItems request and it looks like this:

<iq id="B9tI0-4" to="pubsub.mymachine" type="get"><query xmlns="http://jabber.org/protocol/disco#info" node="theNode"></query></iq>
<iq id="B9tI0-5" to="pubsub.mymachine" type="get"><pubsub xmlns="http://jabber.org/protocol/pubsub"><items node='theNode'/></pubsub></iq>

One thought: it seems that the iq packet is sending a node for the request. Is this correct? When I look at the reference specs it says something like the following should be sent:

<iq type='get'
    from='notifyserver@mymachine'
    to='pubsub.mymachine'
    id='items1'>
  <query xmlns='http://jabber.org/protocol/disco#items'
         node='theNode'/>
</iq>

and when I send this directly to the server using the xml condole in psi I get back the proper results. Can anyone help with this? Thanks very much.

Can you post the full reply stanza. It will have reasons as to why it failed.

This method is used many times within the testcases for pubsub included within the Smack source code, and it runs fine there.

This is the stanza (as per the spec) for retrieving the items from a node.

<iq type='get'
    from='francisco@denmark.lit/barracks'
    to='pubsub.shakespeare.lit'
    id='items1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='princely_musings'/>
  </pubsub>
</iq>

The example you gave is for the generic discovery mechanism, which will also retrieve the list of items from the node as disco items, which is a standardized format for information defined in the Service Discovery specification. The results of this will not include pubsub item specifics, like the payload. The LeafNode.discoverItems() is what actually sends that particular stanza.

Thanks very much for your help with this. As you suggested I looked at the full response and it looks like I am getting an error because I need to send a subid. I tried this using something like the following in an xml console and it worked:

<iq type='get'
    from='notifyserver@mymachine'
    to='pubsub.mymachine'
    id='testhere'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <items node='theNode' subid="lXgiAsweVdJWOq1s0XqWP9QjYfrDVE32p7vHTHHH"/>
  </pubsub>
</iq>

It looks like I may need to add in the subid. I found that two places you can get the subid are:

  1. when the client subscribes to the node (this does not work for me because I may not be able to store that on the client machine at subscribe time)

  2. By using the following stanza:

<iq type='get'
    from='notifyserver@mymachine'
    to='pubsub.mymachine'
    id='subscriptions1'>
  <pubsub xmlns='http://jabber.org/protocol/pubsub'>
    <subscriptions/>
  </pubsub>
</iq>

Once you have the subid you can use it as above. However, is there a way to send the subid in the smack api? It looks like discoverItems does not take any parameters.

Thanks again for your help.

That’s because discoverItems doesn’t require an id, but getItems does when there is more than 1 subscription. What you want to use is the **LeafNode.getItems(Collection ids) **method.

Thank you for your answer. I think I am just missing something simple here. When I call LeafNode.getItems(ids) on my node (named theNode) the following stanza is sent to the server:

<iq id="65xFT" to="pubsub.mymachine" type="get"><pubsub xmlns="http://jabber.org/protocol/pubsub">
<items node='theNode'><item id='xsrrzmkDfK02sB701W9aiofpGwp4B'/></items></pubsub></iq>

This seems to pass the item with an id not a subid. I have tried passing the subid to getItems but I still get the following response:

<iq type="error" id="PklEW-5" from="pubsub.mymachine" to="notify@mymachine/Smack">
<pubsub xmlns="http://jabber.org/protocol/pubsub"><items node="theNode">
<item id="theNode"/></items>
</pubsub>
<error code="400" type="modify">
<bad-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
<subid-required xmlns="http://jabber.org/protocol/pubsub#errors"/>
</error></iq>

Instead of requesting specific items for a node I want to collect all items for a node within a specific subscription. What should I pass to the getItems to make this work?

Thanks very much for your help.

OK, I don’t know what I was smoking when I gave you that last answer

The method I referred to is for retrieving specific items by their id’s, it has nothing to do with subscriptions. That functionality is missing so I have added issue SMACK-289 to track it. I am going to try and fix a couple of these issues over the weekend.

Sorry for leading you down the wrong path.

No problem at all. Thanks very much for offering to help resolve this. Out of curiosity I also tried to turn off the system property xmpp.pubsub.multiple-subscriptions in the Openfire admin console to see if I could stop Openfire from requiring the subscription id. However, I could not turn this feature off. I tried setting it to both false and 0 but it still stayed active. I also restarted the server a number of times but still the feature was reported as on when I queried the features. I am not sure why it is even sending the subid back because I do not have a person subscribed to the node in multiple ways. I even verified this by deleting my entire Openfire installation and starting over from scratch.

Thanks again for your help.

OK, I logged that issue under OF-338. I am assuming that you mean the subId is in the message when you say the subId is sent back, even though you do not have multiple subscriptions.

I have noticed that when a node is created, the owner is automatically subscribed. So if you create a node and then subscribe to it, I am pretty sure you will end up being subscribed twice. This is already logged as OF-8.

This issue has been fixed in trunk.