Problems with new IQ-API in 4.1.0-alpha7-SNAPSHOT

I have found a solution to make Smack full OSGi-compliant with minimum interference. I am currently migrating my code to 4.1.0-alpha7-SNAPSHOT, but I am confronted with a serious problem concerning the new IQ-API. I am using JAXB and put an extension to my IQs. At the moment I cannot find a possibility to create an IQ without defining the child element. It is part of the extension itself provided by JAXB. If I pass the child element name of the extension via the constructor the extension gets enclosed twice which breaks everything. Is there a way to return the whole extension as a valid XML string? This is my old code from 4.0.5 which did the job:

import org.jivesoftware.smack.packet.IQ;

import org.jivesoftware.smack.packet.Packet;

import org.jivesoftware.smack.packet.PacketExtension;

import org.jxmpp.jid.Jid;

public class JaxbMessageIQ extends IQ {

private final PacketExtension payload;

private JaxbMessageIQ(Builder builder) {

payload = builder.payload;

addExtension(payload);

}

@Override

public CharSequence getChildElementXML() {

return payload.toXML();

}

public static Builder create() {

return new Builder();

}

public static Builder error() {

return new Builder(IQ.Type.ERROR);

}

public static Builder get() {

return new Builder(IQ.Type.GET);

}

public static Builder result() {

return new Builder(IQ.Type.RESULT);

}

public static Builder set() {

return new Builder(IQ.Type.SET);

}

public static class Builder {

private PacketExtension payload;

private IQ.Type type;

private String to;

private String from;

private String packetId;

private Builder() {

init();

}

private void init() {

type = IQ.Type.GET;

}

private Builder(IQ.Type type) {

this.type = type;

}

public Builder payload(PacketExtension payload) {

this.payload = payload;

return this;

}

public Builder type(IQ.Type type) {

this.type = type;

return this;

}

public Builder to(Jid to) {

return to(to.asUnescapedString());

}

public Builder to(String to) {

this.to = to;

return this;

}

public Builder from(String from) {

this.from = from;

return this;

}

public Builder packetId(String packetId) {

this.packetId = packetId;

return this;

}

public Builder response(Packet request) {

to(request.getFrom());

from(request.getTo());

packetId(request.getPacketID());

return this;

}

public JaxbMessageIQ build() {

JaxbMessageIQ iq = new JaxbMessageIQ(this);

if (type != null)

iq.setType(type);

if (to != null)

iq.setTo(to);

if (from != null)

iq.setFrom(from);

if (packetId != null)

iq.setPacketID(packetId);

return iq;

}

}

}

Regards,

Jens

IQs now use IQChildElementXmlStringBuilder which is basically an “top element aware” XmlStringBuilder that does not close the top element. This is so that packet extensions can be added before the element is closed. You IQ subclass must also be aware of it’s element name and namespace, but this is done via IQs (String, String) constructor. Using your approach of wraping a PacketExtension within a IQ won’t work this way, because the IQs element name and namespace must be known statically.

Is there no way for supporting me? I can extract the namespace and the root element name via reflection from my JAXBPacketExtension. It is actually a composite that is responsible for all the (un-)marshalling stuff.

I just made a small modification… The messages are transfered correctly if I am able to overwrite the method “getChildElementXML()”. But it is final. Isn’t it possible to remove the final classifier of this method? Otherwise migration becomes impossible for me. All my Dto classes are shared between different implementations (Smack is only one of them).

If this is solved, I am now confronted with the problem that I am not able to get a specific (leaf) node from the PubSubManager. I must evaluate where the problem comes from.

I can extract the namespace and the root element name via reflection from my JAXBPacketExtension.
The PacketExtension interface defines the getNamepsace() and getElementName() methods. So there is no need to use reflection.

I think that if you replace PacketExtension in your code from your original post, with IQChildElementxmlStringBuilder and manage to somehow maintain the element name and namespace information to call IQ constructor correctly, then it should work.

I don’t have an overview of how your environment looks like. And I believe that this is best discussed in a realtime fashion, instead of using the forums. They are great for reports, like your pubsub namespace bug report, but non-trivial design decisions are better solved in MUC/IRC (of course, this requires some will to idle around, since we often may not be available at the same time).

Thank you very much…

If someone is interested in the result: Flow and me decided that it is better to switch from “IQs” to “Messages” and add the JAXBPacketExtension as extension to the Message.