11

I'm using the Smack API in Java to connect to my XMPP server.

I want to send a customized message packet like this:

<message to="you@MyServer.com" type="chat" MYFIELD="custom stuff">
    <body> hi </body>
    <CUSTOM_STANZA A="..." B="..."> 
        C="..." 
        D="..."
    </CUSTOM_STANZA>
</message>

I'm guessing that I create implement my own Packet with that returns this XML in it's toXML() method. But that doesn't seem to work.

Any help would be appreciated.

Flow
  • 23,572
  • 15
  • 99
  • 156
BinRoot
  • 694
  • 2
  • 8
  • 21
  • As [mentioned by Robin](http://stackoverflow.com/a/6390037/194894): Never add custom attributes to top level stanza elements. See also [XEP-134](http://xmpp.org/extensions/xep-0134.html#xmpp). This is a mistake often made. – Flow Dec 03 '14 at 09:37
  • The how is not important, the why is. YOU SHOULD NEVER DO THIS! – Robin Mar 09 '15 at 20:23

4 Answers4

7

i don't know why you want to add custom attributes to the message. This will be problematic on the client and may cause issues on the server as well since it will not match the schema for the message stanza.

The message content, on the other hand is easily handled as @Femi said with a packet extension. You need to create a MyExtension which extends PacketExtension, and the toXML() in that class will return your custom stanza.

You can create and send your custom message by:

Message message = new Message();
message.addExtension(new MyExtension());
chat.sendMessage(message);

To read the stanza, you will want to register a provider, which will create and return your custom PacketExtension. You should take a look at the EmbeddedExtensionProvider for this as it handles the tag parsing for you, thus simplifying the process.

Robin
  • 24,062
  • 5
  • 49
  • 58
  • 1
    I'd like to point in this context to http://xmpp.org/extensions/xep-0134.html#xmpp which explains why it's a bad idea to add custom message attributes. – Flow Dec 03 '14 at 09:27
  • 1
    hi robin , can i know what is this new MyExtension()? can provide that class – NareshRavva Apr 02 '15 at 06:21
4

I recently found out how to add custom stanza to your message. Its was quite easy once I figured it out. I just needed to extend the standard Message Class with my custom message class.

public class CustomMessage extends org.jivesoftware.smack.packet.Message {
  public CustomMessage() {
    super();
  }

  private String customStanza;

  /**
   * @param customStanza
   *            the customStanza to set
   */
  public void setCustomStanza(String customStanza) {
    this.customStanza = customStanza;
  }

  @Override
  public String toXML() {
    String XMLMessage = super.toXML();
    String XMLMessage1 = XMLMessage.substring(0, XMLMessage.indexOf(">"));
    String XMLMessage2 = XMLMessage.substring(XMLMessage.indexOf(">"));
    if (this.customStanza != null) {
      XMLMessage1 += " CustomStanza=\"" + this.customStanza + "\"";
    }

    return XMLMessage1 + XMLMessage2;
  }
}

Then use the custom class to send messages like this:

CustomMessage message = new CustomMessage();
message.setCustomStanza("my data here");
System.out.println(message.toXML());
muc.sendMessage(message);

Your XML message would then look like this:

<message id="ee7Y7-8" CustomStanza="my data here"></message>
Marvin Pinto
  • 30,138
  • 7
  • 37
  • 54
ngoa
  • 65
  • 1
  • 1
    This is the best answer to understand custom stanza creation. Helped me lot...Thnx buddies. – Abhishek Jun 21 '13 at 09:02
  • 5
    **Never** subclass Smack's `Message`. If you think you need to do so, you are doing something wrong. `Message` is meant to be extended by using [PacketExtension](https://www.igniterealtime.org/builds/smack/docs/latest/javadoc/org/jivesoftware/smack/packet/PacketExtension.html) – Flow Dec 03 '14 at 09:33
  • 2
    `org.jivesoftware.smack.packet.Message` is Final class now. ... `public final class Message extends Stanza implements TypedCloneable`. – SRB Bans Oct 15 '16 at 12:31
2

You can use a packet extension for this: unfortunately there is no good documentation or examples for using packet extensions. I've previously looked at this unresolved question which has example code but I was unable to get it working: I got no exceptions but it simply didn't work as my extension wasn't called and I moved on to just encoding my data in the body of a Message.

EDIT: for posterity, I managed to get the following code working. It uses the DOM4J classes DocumentHelper and Element.

Presence np, packet = new Presence();
        packet.setID(sessionManager.nextStreamID().toString());
        packet.setFrom(server.createJID(operator, null));
        if(!available) packet.setType(Presence.Type.unavailable);
        else packet.setType(null);

        // add the custom XML
        Element xml = DocumentHelper.createElement(QName.get("custom", "http://www.custom.com/xmpp"));
        xml.addAttribute("type", "presenceupdate");
        packet.addExtension(new PacketExtension(xml));

Mildly humorous: I ran into my own answer a year later while actually trying to solve this problem for a real project (as opposed to tinkering like I did before) and since I couldn't just abandon it I had to figure it out. I figure I'll need this answer again so here it is. SO: my memory in the sky.

EDIT: found an even simpler way of doing this:

        Element xml = packet.addChildElement("custom", "http://www.custom.com/xmpp");
        xml.addAttribute("type", "presenceupdate");

Thing to note: trying to add certain things (in my case, trying to add a delay element) resulted in the packet not being routed. Something in Openfire swallowed it, so this is something to watch for.

Femi
  • 64,273
  • 8
  • 118
  • 148
  • When I add a packet extension, I can add my `` so that's fine and working. But what I really want to do is edit the message stanza to have a `MYFIELD="custom stuff"`. For the life of my I can't figure out how to customize this message header to also include my custom field. – BinRoot Jun 17 '11 at 15:48
  • Openfire seems to drop some packets with empty bodies. Add some non-whitespace text to the body. – Bjorn Roche Oct 25 '12 at 20:44
1

You need to define a custom class that should implements ExtensionElement (as menitioned by @Flow)

A very detailed explanation that produces the following stanza is available in this answer

<message id='923442621149' type='chat'><body>shanraisshan</body>
<reply xmlns='shayan:reply' rText='this is custom attribute'/>
</message>

where reply is a custom extension, which contains

  1. Element (reply)
  2. Namespace (shayan:reply)

the list of default xmpp namespaces are available at Official XMPP website

Community
  • 1
  • 1
shanraisshan
  • 3,521
  • 2
  • 21
  • 44