powered by Jive Software

Problem with Service Discovery

Hi Everyone,

I am using smack to build a custom java chat application, with a very specific purpose. The problem I am currently facing is that when I ask call the discoverItem(JID, “astronomy”) method from the ServiceDiscoveryManager class, the response contains two responses with the same ID (As shown below)

Hi Everyone,

I am using smack to build a custom java chat application, with a very specific purpose. The problem I am currently facing is that when I ask call the discoverItem(JID, “astronomy”) method from the ServiceDiscoveryManager class, the response contains two responses with the same ID (As shown below)

<iq id="m2u7h-5" to="userA@service.com" type="error" from="userB@service.com"><query node="astronomy" xmlns="http://jabber.org/protocol/disco#items"/><error code="404" type="CANCEL"><item-not-found xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/></error></iq> <iq id="m2u7h-5" to="userA@service.com" type="result" from="userB@service.com"><query node="astronomy" xmlns="http://jabber.org/protocol/disco#items"><item jid="0" name="c8/topcat/samp.app.ping" action="update"/></query></iq>

Some times the order of the two responses is changed but I always get two responses to one call. The code I am using to discover item is given below.

private void Disco() {
        ServiceDiscoveryManager discoManager = new ServiceDiscoveryManager(Connection.getInstance().getConnection());
        Iterator<DiscoverItems.Item> it = discoManager.discoverItems(JID, "astronomy").getItems();
            while(it.hasNext()){
                DiscoverItems.Item individualItem = (DiscoverItems.Item)it.next();
                // Do Something .....
                }
            }     }

I am using a custom PacketListener to build the response.

public XMPPConnection register(final XMPPConnection connection) {
        PacketFilter packetFilter = new PacketTypeFilter(DiscoverItems.class);
        PacketListener packetListener = new PacketListener() {             public void processPacket(Packet packet) {
                DiscoverItems discoverItems = (DiscoverItems) packet;
                // Send back the items defined in the client if the request is of type GET
                if (discoverItems != null && discoverItems.getType() == IQ.Type.GET) {
                    DiscoverItems response = new DiscoverItems();
                    response.setType(IQ.Type.RESULT);
                    response.setTo(discoverItems.getFrom());
                    response.setPacketID(discoverItems.getPacketID());
                    response.setNode("astronomy");                    NodeInformationProvider nodeInformationProvider = getNodeInformationProvider(discoverItems.getNode());
                    if (nodeInformationProvider != null) {
                        List<DiscoverItems.Item> items = nodeInformationProvider.getNodeItems();
                        if (items != null) {
                            for (DiscoverItems.Item item : items) {
                                response.addItem(item);
                            }
                        }
                    } else {
                        response.setType(IQ.Type.ERROR);
                        response.setError(new XMPPError(XMPPError.Condition.item_not_found));
                        System.out.println("Setting Error Response");
                    }
                    connection.sendPacket(response);
                }
            }
        };
        connection.addPacketListener(packetListener, packetFilter);
        return connection;     }

I either need to know how to stop this behaviour or ignore the IQ XML if the first result is of type Error.

Any help will be appreciated.

Regards

Ali Khalid.

Hi,

you can’t use a custom PacketListener to answer to discover item requests because if you do both your custom PacketListener and the PacketListener of the ServiceDiscoveryManager will reply to every item discovery request. So your custom listener responds with the correct item and the ServiceDiscoveryManager responds with an item-not-found error because there is no registered NodeInformationProvider for the node “astronomy”.

The right way to do it is to register a NodeInformationProvider via ServiceDiscoveryManager#setNodeInformationProvider(String, NodeInformationProvider).

And another thing … always use ServiceDiscoveryManager.getInstanceFor(Connection) to get the discovery manager associated to a connection. Never use “new ServiceDiscoveryManager” because if you do you will register multiple instances of the discovery manager and any features that were already registered to the discovery manager may get lost.

Greets,

Henning