Using XMPP in Apache Axis2

Hi There

We (Apache Axis2 team ) are trying to support XMPP , so I found Smack is XMPP client and its release under apache license as well therefore Smack is a good candidate for us.

Our use case is to send and receive SOAP over XMPP not just string. If I want to use user API i have to add SOAP message as a string value to Message , IQ ect… , but its a big performance hit. Is there any possibility of supporting streaming like API where Message will be given the output stream and he can write any thing he want , with that approach we do not need to store SOAP message as a string.

I think it is very useful if you guys can comment on this thing , and I can be a volunteer implement this and send you guys a patch.

Hey Deepal,

Welcome! I’'m not sure I quite understand where the performance problem is and your proposed solution, could you perhaps go into some more detail about your use case? Maybe some code snippets of what you are hoping to acomplish?

Alex

Note that there’'s a standard for SOAP over XMPP:

http://www.jabber.org/jeps/jep-0072.html

You should follow this one. This requires a class that implements the interface org.jivesoftware.smack.packet.PacketExtension.

With this approach, you only have to generate the string when it’'s actually needed (when toXML() is called).

If this isn’‘t enough, you would need to add a feature that the packet extension could return a java.io.Writer-subclass instead, but I’'m not quite sure this would help much.

I think you know about Apache Axis2 , there we can support any kind of transports, So we are thinking of supporting XMPP.

In Axis2 is a SOAP processing engine and performance is a big concern. If I am going to use existing Smack I have to convert SOAP message into string and set that as the message body. As far as Axis2 is concern its not the best way to do that and in other transport implementations we directly write to the output stream rather than converting SOAP message into string (we use StAX streaming API)

So what I want is some other way to write the Message content rather than converting that to a string.

I am talking about something like following ;

public void serialize(OutputStream out) throws Exception{

try {

out.write(SOAPMessage);

out.flush();

} catch (Exception e) {

}

}

Message was edited by: deepal

The JEP pointed out by Anlumo would likely be a good one to use.

I do have some similar code currently. Though, the message is built as a string so I am not sure if it will fit your purposes, but it is in the direction of what I believe you are looking for and could be likely generalized in some manner. The code I wrote allows you to transfer files over the XMPP stream, this is done transparently to the client using the API though as all they see is an output stream that handles the work of building the packets and sending.

Here is the code I currently have, it is available in Smack in IBBTransferNegotiator:

private class IBBOutputStream extends OutputStream {

protected byte[] buffer;

protected int count = 0;

protected int seq = 0;

final String userID;

final private IQ closePacket;

private String messageID;

private String sid;

IBBOutputStream(String userID, String sid, int blockSize) {

if (blockSize <= 0) {

throw new IllegalArgumentException(“Buffer size <= 0”);

}

buffer = new byte[blockSize];

this.userID = userID;

Message template = new Message(userID);

messageID = template.getPacketID();

this.sid = sid;

closePacket = createClosePacket(userID, sid);

}

private IQ createClosePacket(String userID, String sid) {

IQ packet = new IBBExtensions.Close(sid);

packet.setTo(userID);

packet.setType(IQ.Type.SET);

return packet;

}

public void write(int b) throws IOException {

if (count >= buffer.length) {

flushBuffer();

}

buffer[count++] = (byte) b;

}

public synchronized void write(byte b[], int off, int len)

throws IOException {

if (len >= buffer.length) {

// “byte” off the first chunck to write out

writeOut(b, off, buffer.length);

// recursivly call this method again with the lesser amount subtracted.

write(b, off + buffer.length, len - buffer.length);

} else {

writeOut(b, off, len);

}

}

private void writeOut(byte b[], int off, int len) {

if (len > buffer.length - count) {

flushBuffer();

}

System.arraycopy(b, off, buffer, count, len);

count += len;

}

private void flushBuffer() {

writeToXML(buffer, 0, count);

count = 0;

}

private synchronized void writeToXML(byte[] buffer, int offset, int len) {

Message template = createTemplate(messageID + “_” + seq);

IBBExtensions.Data ext = new IBBExtensions.Data(sid);

template.addExtension(ext);

String enc = StringUtils.encodeBase64(buffer, offset, len, false);

ext.setData(enc);

ext.setSeq(seq);

synchronized (this) {

try {

this.wait(100);

}

catch (InterruptedException e) {

/* Do Nothing */

}

}

connection.sendPacket(template);

seq = (seq + 1 == 65535 ? 0 : seq + 1);

}

public void close() throws IOException {

connection.sendPacket(closePacket);

}

public void flush() throws IOException {

flushBuffer();

}

public void write(byte[] b) throws IOException {

write(b, 0, b.length);

}

public Message createTemplate(String messageID) {

Message template = new Message(userID);

template.setPacketID(messageID);

return template;

}

}

/code

Let me know what you think,

Alex