powered by Jive Software

Still can't get customIQ to work even after implementing CustomIqHandler


#1

Hey,
I’m trying to make a xmpp client that can recieve and respond to a custom iq that looks like this:

<iq type="set" id="light-1" to="admin">
  <query xmlns="custom:iq:provider">ON</query>
</iq>

So i made a custom iq handler class:

class CustomIqHandler extends AbstractIqRequestHandler {
		protected CustomIqHandler(String element, String namespace, org.jivesoftware.smack.packet.IQ.Type type, Mode mode) {
			super(element, namespace, type, mode);
		}

		@Override
		public IQ handleIQRequest(IQ iqRequest) {
                        //return any iq right now, just for testing
			IQ iqResponse = IQ.createResultIQ(iqRequest);
			return iqResponse;
		}    	
    }

And then i register it like this :

iqRequestHandler = new CustomIqHandler("query", "custom:iq:provider", IQ.Type.set, IQRequestHandler.Mode.async);
    	connection.registerIQRequestHandler(iqRequestHandler);

But still when i send a raw xml from jmeter it doesn’t work. I also have IncomingChatMessageListener implemented and that works fine when i send a message from jmeter to the client. I’m using a debugger to check if any packets are being recieved and when i send a custom iq stanza no packets are received. Am i missing a class or something that has to be implemented for custom iq request/response to work ?


#2

Did you create and setup a provider for you custom IQ?


#3

Yes, here it is :

public class CustomIqProvider extends IQProvider<CustomIq> {
	@Override
	public CustomIq parse(XmlPullParser parser, int initialDepth) throws Exception {
		String state = null;
		
		outerloop: while(true) {
			int eventType = parser.next();
			switch(eventType) {
				case XmlPullParser.START_TAG:
					String elementName = parser.getName();
					state = parser.nextText();
					break;
				case XmlPullParser.END_TAG:
					if(parser.getDepth() == initialDepth) break outerloop;
					break;
			}
		}
		return new CustomIq(state);
	}

This is my CustomIq class:

public class CustomIq extends IQ {
	protected String state;
	
	protected CustomIq(String state) {
		super("query", "custom:iq:provider");
		this.state = state;
	}

	public String getState() {
		return state;
	}
	
	public void setState(String state) {
		this.state = state;
	}

	@Override
	protected IQChildElementXmlStringBuilder getIQChildElementBuilder(IQChildElementXmlStringBuilder xml) {
		xml.rightAngleBracket();
		xml.element("state", state);
		return xml;
	}
}

And i added this line of code in my XmppController class where i create and manage my connection:

ProviderManager.addIQProvider("query", "custom:iq:provider", new CustomIqProvider());

Maybe i made a mistake there somewhere ?


#4

Probably, but it isn’t an obvious one then. Next step would be to simply debug the issue. Follow the white rabbit path of the IQ stanza through Smack, this will lead you to the cause why the handler is not invoked.


#7

Ok i figured out what my problem was. I sent it to the full jid and now it works. But i get an Exception in thread “AWT-EventQueue-0” java.lang.NullPointerException. This is where it throws an exception:

protected void processStanza(final Stanza stanza) throws InterruptedException {
        assert (stanza != null);

        final SmackDebugger debugger = this.debugger;
        if (debugger != null) {
            debugger.onIncomingStreamElement(stanza);
        }
`        lastStanzaReceived = System.currentTimeMillis();`
        // Deliver the incoming packet to listeners.
        invokeStanzaCollectorsAndNotifyRecvListeners(stanza);
    }

When it calls lastStanzaReceived = System.currentTimeMillis(); an exception is thrown.
Stanza has String state = null at the time the exception was thrown. Could that be the issue?


#8

That would be surprisingly if this where true.

You should always include the full stacktrace of the exception when reporting a exception. Also please create new topic as this appears to be an unrelated issue to this topic.


#9