Brief Tutorial on IQ Providers

Version 2

    Problem which was to be solved:

    I wanted to implement a bot which receives custom  IQ Stanzas and puts the data into a database.

    On the other end was a client which was sending the IQ Stanza.

    Both sides (the client as well as the bot) are developed using the SMACK API

     

    Here is how I did it:

     


    1: Client: Sending the IQ Stanza

    First create a new class which extends the IQ class und overwrites the getChildElementXML:

     

    public class CustomIQ extends IQ {

                   float myData;

                   public String getChildElementXML() {

                                   String request = "<query xmlns='myxmlns’>"

                                                                   + "< myData >"+ myData + "</ myData >"

                                                                   + "</query>";

                                   return request;

                    }

    }

     

    Init your IQ and send it:

     

    CustomIQ  myIQ = new CustomIQ();

    myIQ. setType(IQ.Type.GET); //or use instead SET

    myIQ.setTo(“jid@bot”); //replace it with the receiver jid

    connection.sendPacket(myIQ); //connection is an instance of XMMPConnection

     

    2. Setup the Bot

    First you have to set up a so called IQProvider. An IQProvider transforms the data of the XML child data into an IQ Object and returns it. It does not perform any actions on the data except for setting up the values of an IQ Object. This IQ can later on be processed by a PacketListener or PacketCollector.

    So let us set up the Provider:

     

    public class customIQProvider implements IQProvider {

    CustomIQ  myIQ = new CustomIQ();

    int eventType = parser.next();

                                   while ( eventType == XmlPullParser.START_TAG) {

                                                   name = parser.getName();

     

                                                   switch (parser.getEventType()){

                                                   case XmlPullParser.START_TAG:

                                                   {

                                                                                   if (name.equals("myData")){

                                                                                  myIQ.setmyData(Float.parseFloat(parser.nextText()));

     

                                                                   }

                                                   }

                                   return myIQ;

                    }

    }

     

    Once the provider is implemented, you have to add it to the connection:

     

    ProviderManager.getInstance().addIQProvider("query", " myxmlns ", new customIQProvider());

     

    So now all the custom IQ Stanzas which have a “query” and the myxmlns namespace are handled to the provider. The provider then parsese the XML and sets the values of the IQ Classes.

    So now all which still has to be done is to implement a PacketListener or PacketCollector to process the IQ. Here is my suggestion:

    First set up a filter which returns “true” on all the Custom IQ Stanzas:

     

    public class myIQFilter implements PacketFilter{

     

                    public myIQFilter() {

                    }

                    @Override

                    public boolean accept(Packet packet) {

                                   boolean CustomIQReceived = false;

                                   if (packet instanceof CustomIQ){

                                                   CustomIQReceived = true;

                                   }

                                   return CustomIQReceived;

                    }

    }

     

    Now set up a PacketListener:

     

    public class myIQListener implements PacketListener{

                   CustomIQ reply = new CustomIQ();

                    XMPPConnection connection;


                        public myIQListener(XMPPConnection con) {

                                   connection = con;

                         }

     

                        public void processPacket(Packet packet) {

                                    //Do all the processing here like accessing a database and so on..

                                    //Now return the result IQ..

                                   reply. setType(IQ.Type.RESULT)

                                   reply.setPacketID(packet.getPacketID());

                                   reply.setFrom(packet.getTo());

                                   reply.setTo(packet.getFrom());

                                   connection.sendPacket(reply);

                          }

    }


    And now all you still have to do is to register the PacketListener (main thread):

     

    connection.addPacketListener((new myIQListener(connection)),new myIQFilter()) ; //connection is an instance of the XMPPConnection.