powered by Jive Software

Receiving custom elements in custom IQ response


#1

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.


#2

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.


#3

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


#4

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?


#5

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.


#6

@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.


#7

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.


#8

@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?


#9

Have you registered your Provider class?


#10

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.
??


#11

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


#12

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: