powered by Jive Software

Receiving custom elements in custom IQ response

Hello everyone,

Using Smack 4.1.3

Code is here: https://gist.github.com/blacklightknight/8894b20cf68c3a288b91809b77f0ba2a
Stacktrace in the same gist as well.

My Question ->
I am trying to send a custom iq to ejabberd server (I was successful in that) and then perform some custom operations on the server (also done) and then send a response from server to android client with custom parameters/attributes(Also done, but after getting this result in android is where I am stuck). Example:
I am sending this iq

SENT (1): <iq to='example.com' id='D2IDi-16' type='get'><query xmlns='ns:custom'><a/></query></iq>

And I am getting this result

RECV (1): <iq to='testing7@example.com/Smack' from='example.com' type='result' id='D2IDi-16'><query xmlns='ns:custom'><response op='sum' val='4'/></query></iq><r xmlns='urn:xmpp:sm:3'/>

But I wanted this response in some variable or something on Android side for further computation but somehow I haven’t been able to achieve it.
I have searched for it a really long time now and I have found most of the example outdated, or should i say smack have grown from then.
To be specific my code gives compilation error at line

saying that "There is no default constructor available in ‘org.jivesoftware.smack.packet.IQ’ " where as in all the examples I have seen this line runs fine.

So what am I missing ? If this is wrong approach then how can I correct it?
Please help me out with some examples.
Thank you.

A look into IQ.java reveals, that there is indeed no default constructor available. Here you have to call one of the three available constructors of the super class, eg super(childElementName, childElementNamespace);.

Edit: Some little nits:
I would name the IQCustom class IQCustomAuthProvider.
Also I would change this line to public class IQCustom extends IQProvider<IQCustomAuth> {, so that its clear that the Provider returns a IQCustomAuth object, not an IQ.

1 Like

it will also helpful to get info directly from the getter’s and we need to do make any extra effort form there.

Thanks @Paul_Schaub and @Hiren1, for your comments. I did the change

you have to call one of the three available constructors of the super class, eg super(childElementName, childElementNamespace);.

and

I would change this line to public class IQCustom extends IQProvider {, so that its clear that the Provider returns a IQCustomAuth object, not an IQ.

But the line https://gist.github.com/blacklightknight/8894b20cf68c3a288b91809b77f0ba2a#file-mainactivity-L61 still gives result as null as:
"I/Send IQ with Response: ****** message null"
Can anybody help me out here please?

you can’t do it like this it will always be null let you can cast to IQCustomAuth and then you can get the value using getters.

@Hiren1 sorry but I am not able to completely understand your point. Can you please give a example?
What I did after reading your point was created a object of class IQCustomAuth like this in the Main Activity

final IQCustomAuth iqcustomauth = new IQCustomAuth("testing7@example.com", “example.com”);

and then

iqcustomauth.getExtension(“response”,“ns:custom”)

but it was still null.

Here you are creating a new object and then trying to get data from it. It should be clear, that this cannot work :smiley:

What @Hiren1 suggested was, that you cast the incoming packet instead of creating a new one.

@Paul_Schaub I did try it

final IQCustomAuth iqcustomauth = new IQCustomAuth("testing7@example.com", "example.com");
                try {
                    connection.sendIqWithResponseCallback(iqcustomauth, new PacketListener() {
                        @Override
                        public void processPacket(Stanza packet) throws SmackException.NotConnectedException {
                            IQCustomAuth IQ    =   (IQCustomAuth)packet;
                            System.out.println("################# Custom packet received"+IQ.getServerTime_Local() +" "+IQ.getServerTime_UTC());

                        }
                    });
                } catch (SmackException.NotConnectedException e) {
                    e.printStackTrace();
                }

But with no success

05-23 18:06:07.909 26557-26780/com.example.admin.erl_chat E/AbstractXMPPConnection: Exception in async packet listener
java.lang.ClassCastException: org.jivesoftware.smack.packet.UnparsedIQ cannot be cast to com.example.admin.erl_chat.IQCustomAuth
at com.example.admin.erl_chat.MainActivity$1.processPacket(MainActivity.java:114)
at org.jivesoftware.smack.AbstractXMPPConnection$5.processPacket(AbstractXMPPConnection.java:1424)
at org.jivesoftware.smack.AbstractXMPPConnection$3.run(AbstractXMPPConnection.java:1101)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
at java.lang.Thread.run(Thread.java:818)

where MainActivity.java:114 is

IQCustomAuth IQ = (IQCustomAuth)packet;
What did I do wrong?

Have you registered your Provider class?

Yes I have using

ProviderManager.addExtensionProvider("response", "ns:custom", new IQCustom());

In the gist It was done inside the on click listener of the button but I shifted it to the onCreate() method.
And the above exception occurred after I had done all this already.
??

any luck with your problem else i will upload my sample file for your refrence.

Thank you Hiren for your kind response. But Actually I understood your suggestion and made a class with getters and setters and got it working.So a big thank you :slight_smile: