How to send custom response

Hi,
I am using Smack-3.2.2.

What I am trying to do is add and implement some features and then by using xmlns, wanting to get them.

Main.java

**
**

public class Main {   public static void main(String args[]) throws Throwable   {
     //create Connection and connect
             System.out.println(":::Adding Feature:::");
    ServiceDiscoveryManager.getInstanceFor(connection).addFeature("http://jabber.org/protocol/disco#info");
    ServiceDiscoveryManager.getInstanceFor(connection).addFeature("my:test:feature");      // create listener
    connection.addPacketListener(
            new MyCustomPacketListener(connection), new PacketFilter()
            {
              public boolean accept(Packet packet)               {
                if (packet.getXmlns().equals("my:test:feature"))                 {
                  return true;
                }
                return false;
              }
            });     // main method does not terminate
    while (true)     {
      Thread.sleep(Long.MAX_VALUE);
    }

MyCustomPacketListener.java

public class MyCustomPacketListener implements PacketListener {
   // some code   public void processPacket(Packet packet)   {
    IQ response = new IQ()     {
      @Override
      public String getChildElementXML()       {
        return new StringBuilder()
                .append("<query xmlns=\"my:test:feature\">")
                  .append("<name>")
                    .append("testApp")
                  .append("</name>")
                  .append("<type>")
                    .append("someType")
                  .append("</type>")                               .append("</query>")
                .toString();
      }
    };
        response.setTo("some@jid");
    response.setType(IQ.Type.RESULT);
    response.setPacketID(packet.getPacketID());
    connection.sendPacket(response);
  }
}

From PSI, when I send:**
**

<iq type="get" to="some@jid" id="info-1"> <query xmlns='http://jabber.org/protocol/disco#info'/>
</iq>

I get the correct response, which have my added feature.

<iq from="some@jid/Smack" type="result" id="info-1" to="jid@some/PSI">
  <query xmlns="http://jabber.org/protocol/disco#info">
    <identity category="client" type="typeName" name="someName"/>
    <feature var="http://jabber.org/protocol/xhtml-im"/>
    <feature var="my:test:feature"/>
    <feature var="http://jabber.org/protocol/disco#info"/>
  </query>
</iq>

But when I send:

<iq type="get" to="some@jid" id="ded3"> <query xmlns='my:test:feature'/>
</iq>

I get this error message that:

<iq from="some@jid/Smack" type="error" id="ded3" to="some@jid/Psi1">
<error type="CANCEL" code="501">
<feature-not-implemented xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
</error>
</iq>

Please can anyone tell me, what I am doing wrong here?

Thanks.

Any help ?

You need to read up on the provider architecture.

Basically Smack doesn’t know how to handle the IQ request that you are sending, so it replies with an error. You will have to create and register a provider to handle this IQ type.

Thanks for the replay.

I am kinda newbie to this, so can you please help me in creating the example, explained in the Provider Architecture.

So far what I understood is that,

  • I have to create a new Java project.
  • Create smack.providers.xml file **META-INF **folder.
<?xml version="1.0"?> <smackProviders>
     <iqProvider>
         <elementName>query</elementName>
         <namespace>jabber:iq:time</namespace>
         <className>com.test.Time</className>
     </iqProvider> </smackProviders>
  • Create a class Time in com.test package and extend it with IQ class.
  • Add setter methods** **in Time class
public class Time extends IQ
{
  @Override
  public String getChildElementXML()   {
    throw new UnsupportedOperationException("Not supported yet.");
  }      // define setter methods
     // setUtc(String), setTz(String), and setDisplay(String)
}

After that I am lost. I don’t know what to do after this?

Thanks in advance.

The simplest thing to do is to register your provider with the ProviderManager in your code, instead of using the smack.providers.xml file.

I have always taken the approach of writing an actual IQProvider, as it is more flexible then the bean approach (I have never actually tried that approach). I would suggest you check the smack source for many examples of providers so you can figure out how to write your own for your custom IQ packet.

One example is the DiscoverItemsProvider.

@rcollier sorry, but I am still lost here.

I have checked out the examples in smack source, but not been able to figure out how to implement it.

The example in Provider Architecture is when:

<iq type='get' from='joe@example.com' to='mary@example.com' id='time_1'>
  <query xmlns='jabber:iq:time' />
</iq>

is sent, then the following response is sent back.

<iq type='result' to='joe@example.com' from='mary@example.com' id='time_1'>
  <query xmlns='jabber:iq:time'>
  <utc>20020910T17:58:35</utc>
  <tz>MDT</tz>
  <display>Tue Sep 10 12:58:35 2002</display>
  </query>
</iq>

It would be very helpful if you can please tell me, how can I register this provider using IQProvider.

The smack.providers.xml file doesn’t seem to work. I’ve tried it with both smack.providers and smack.providers.xml, and my providers never seem to be registered.

Only be manually adding my providers with ProviderManager.getInstance().addExtensionProvider am I able to add my providers.

The issue is that only 1 providers file is read and it is from the specific location it is stored in the jar file. You can’t simply add a new one with just your own configuration, which is why I mentioned it is easier to simply use the ProviderManager to add new providers.

You can do it with the providers file, if you have control of the classpath loading order, which is not always possible depending on your environment. For a simple java app, you can add a custom providers file in a meta-inf directory on the classpath BEFORE the smack jar. This way your file will get loaded INSTEAD of the one in the jar. I emphasize instead, because it means you have to have the content of the file embedded within the jar in your cusom provider file, as smack relies on those mappings to work properly.

The simplest thing to do in this case is to copy the providers file from the jar and then add your own provider configs to it.

SMACK-286