You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@qpid.apache.org by Gordon Sim <gs...@redhat.com> on 2013/08/06 19:24:40 UTC

qpid::messaging and map- and list- message over AMQP 1.0

In AMQP 0-10 message content was  essentially always treated as raw 
data, with the content-type indicating how those bytes were to be 
interpreted. For map- and list- messages we used a content-type of 
amqp/map and amqp/list respectively.

In AMQP 1.0, though you can of course still send raw data (as a Data 
section) with a content-type specified in the properties, the preferred 
method of sending maps and lists is through an AmqpValue section with 
the type encoded in the bytes making up that section.

I've been working on support for map- and list- messages over 1.0 
through the c++ qpid::messaging API and have an approach ready for some 
feedback[1].

Over 0-10, the approach used was to have encode/decode functions that 
work with a Variant::Map or Variant::List. The application was 
responsible for encoding outgoing messages before sending them and 
checking the content-type on received messages and decoding them if 
appropriate.

Now that the content-type cannot be relied on to indicate the type of 
the message (indeed the specification encourages it *not* to be used, 
relying only on the type encoding in the AmqpValue section), a different 
approach is necessary.

I've added a method to Message to get the content as a Variant. This can 
be used for a whole range of different types of data including binary or 
maps and lists. All the existing methods for accessing content remain of 
course and in the case of structured data, they will return the raw bytes.

With this approach, the application doesn't directly encode or decode 
the data itself, but simply reads or manipulates the Variant typed 
content. E.g instead of:

   Message message;
   Variant::Map content;
   content["a"] = "bcd";
   encode(content, message);
   sender.send(message);

a map message would be sent like this:

   Message message;
   message.content() = Variant::Map();
   message.content()["a"] = "bcd";
   sender.send(message);

and instead of:

   Message message = receiver.receive();
   if (message.getContentType() == "amqp/map") {
      Variant::Map content;
      decode(message, content);
      //process content:
      std::string x = content["a"];	
   } else {
      //handle unexpected format
   }

receiving a map message would look like this:

   Message message = receiver.receive();
   if (message.content().getType() == VAR_MAP) {
      //process content:
      std::string x = message.content().asMap()["a"];	
   } else {
      //handle unexpected format
   }

The old approach will of course continue to work for 0-10 without 
modification, but in order to support the same pattern over both 
protocols I have modified the 0-10 path also. For sending, if you don't 
touch Message::content() then it will behave just like it did before. 
For receiving, map- and list- messages will by default be decoded 
automatically when fetched (and made available via Message::content()). 
This can if desired be disabled via a connection option; it doesn't 
break anything but if your application already explicitly tests the 
content type and decodes then its doing redundant work.

For 1.0 you can also of course continue to send raw bytes with an 
associated content-type if desired as well. I haven't actually exposed 
1.0 based encode and decode routines for this purpose though.

Any feedback on this as an approach is welcome. I'd be especially 
excited to hear from anyone who thinks they might want to send AMQP 1.0 
encoded structured content. A patch is available for those who want to 
see the gory details[1].

--Gordon.

[1] https://reviews.apache.org/r/13328/

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@qpid.apache.org
For additional commands, e-mail: users-help@qpid.apache.org