2
votes

I'm developing a chat system based on xmpp (smack+openfire). I'm having issues when i try to send, along with a normal message, some "extra data". When preparing the message I do the following:

MyData myObject = new MyData("some text");

Message msg = new Message("a@me", Message.Type.chat);

DefaultPacketExtension dpe = new DefaultPacketExtension("packetName", "http://namespace.stuff");
dpe.setValue("dataTag", myObject.toXMLString());

msg.addExtension(dpe);
msg.setBody("Hello World!");

The myObject.toXmlString() returns an XML representation (using dom4j) of the MyData object. After this I proceed with the sending of this message:

Chat personalChat = chatmanager.createChat(msg.getTo(),new MessageListener() {
        @Override
        public void processMessage(Chat chat, Message message) {
            System.out.println("MESSAGE RECEIVED:");
            System.out.println("From: "+message.getFrom());
            System.out.println(message);
        }
});

personalChat.sendMessage(msg);

The debug client reports the following messages.

Out message:

<message id="Fx5bQ-4" to="a@me" from="a@me/Smack" type="chat">
     <body>Hello World!</body>
     <thread>ef9632e3-6d27-4fea-a5c8-b3f7c85052d8</thread>
     <packetName xmlns="http://namespace.stuff">
         <dataTag>
             <myData xmlns:me="namespace">
                 <name>some text</name>
                 <points>0</points>
                 <res>0</res>
                 <contract/>
                 <bonuses/>
                 <position>0</position>
                 <secret/>
             </myData>
         </dataTag>
     </packetName>
</message>

In message:

<message id="Fx5bQ-4" to="a@me" from="a@me/Smack" type="chat">
     <body>Hello World!</body>
     <thread>ef9632e3-6d27-4fea-a5c8-b3f7c85052d8</thread>
     <packetName xmlns="http://namespace.stuff">
          <bonuses/>
          <name>some text</name>
          <res>0</res>
          <contract/>
          <position>0</position>
          <secret/>
          <points>0</points>
     </packetName>
</message>

As you can see there has been "a loss" of some data. In fact "dataTag" and "myData" simply are logged as part of the outgoing message but does not appear in the incoming one! Is this meant to be (performance stuff..."useless" to send "empty" nodes) or is there something wrong with openfire setup?

This is just a small example...in the real project I have 1000+ lines of a "myData" object in the outgoing message and in the incoming one most of them are missing (like 90% of the packetExtension is lost, and is not just "empty" nodes of the xml)!

1
What server are you using? Is this the actual XML that you're using, or an attempt at generating an example? For instance, your xmlns:me namespace declaration is not actually used.Joe Hildebrand

1 Answers

2
votes

The reason is you lack a specific packetExtensionProvider and therefore when your packet arrives the DefaultPacketExtensionProvider cannot parse it correctly. Indeed, this DefaultPacketExtensionProvider is very simple and can parse only simple XML with 1 level child or so.

For your case you need to define something like:

class MyExtensionProvider implements PacketExtensionProvider{
    @Override
    public PacketExtension parseExtension(XmlPullParser parser)throws Exception {
        LOGGER.info("[parseExtension] Executing parseExtension()");

        DefaultPacketExtension extension = new DefaultPacketExtension(MyExtension.ELEMENT_NAME,MyExtension.NAMESPACE);

        boolean done = false;

        int eventType = parser.getEventType();

        while (!done) {
            System.out.println(parser.getText());

            if (eventType == XmlPullParser.START_TAG) {

                String name = parser.getName();
                System.out.println(name);

                // If an empty element, set the value with the empty string.
                if (parser.isEmptyElementTag()) {
                    extension.setValue(name,"");
                }else {
                    eventType = parser.next();
                    if (eventType == XmlPullParser.TEXT) {
                        String value = parser.getText();
                        System.out.println(value);
                        extension.setValue(name, value);
                        done=true;
                    }
                }
            }

            eventType = parser.next();
        }
        return extension;
    }
}

This is a simple one so you want to define your own. Then you need to register your provider with:

ProviderManager providerManager = ProviderManager.getInstance();     
    providerManager.addExtensionProvider(MyExtension.ELEMENT_NAME, MyExtension.NAMESPACE,new MyExtensionProvider());

REMEMBER: when you send the message it has to have MyExtension.ELEMENT_NAME and MyExtension.NAMESPACE set correctly otherwise it will not work. The ProviderManager will not recognize the packet and will not call the proper PacketExtensionProvider.