This page last changed on Mar 09, 2009 by jonathan.robie@redhat.com.

This page compares C++ and Python code samples from our examples, looking for arbitrary discrepancies in the API. I suggest that we add proposals to fix these discrepancies inline for each example.

Opening and closing connections and sessions

C++

 
Connection connection;
try {
    connection.open(host, port);
    Session session =  connection.newSession();
    ...
    connection.close();
    return 0;
} catch(const std::exception& error) {
    std::cout << error.what() << std::endl;
}
return 1;

Python

 
host="127.0.0.1"
port=5672
user="guest"
password="guest"

socket = connect(host, port)
connection = Connection (sock=socket, username=user, password=password)
connection.start()
session = connection.session(str(uuid4()))
...
session.close(timeout=10)

Discrepancies

  • Python uses a socket object, not needed in the C++ API. I suggest that Python follow C++ here.
  • Python requires the user to provide a UUID instead of creating one for him. I suggest that Python provide the UUID automagically, as does C++.
  • Our Python examples end by closing the session, our C++ examples end by closing the connection. If both APIs allow both approaches, we should fix the examples; if not, we should make the APIs consistent.

Subscribing to a Queue

C++

LocalQueue local_queue;
SubscriptionManager subscriptions(session);
subscriptions.subscribe(local_queue, string("message_queue"));
subscriptions.run();

Python

local_queue_name = "local_queue"
queue = session.incoming(local_queue_name)
session.message_subscribe(queue="message_queue", destination=local_queue_name)
queue.start()

Discrepancies

  • C++ local queues are created as standalone objects, then subscribed. Python retrieves a local queue from the server using the session.incoming() method.
  • Python starts delivery using the local queue's start() method. C++ begins delivery using the SubscriptionManger.run() or Session.run() method.
  • Naming: Python calls the method "message_subscribe", which corresponds to the AMQP name, but it's odd naming: it does not subscribe to a message, nor does it subscribe a message to anything else.

Setting Delivery Properties, Message Properties

C++

 
message.getDeliveryProperties().setRoutingKey("routing_key");

Python

 
delivery_props = session.delivery_properties(routing_key="routing_key")

Discrepancies

  • Python requires the programmer to create the delivery property object for a new message using a session object. That seems strange - it would be better to create it using the message, since it pertains to a message's delivery properties.
  • This same discrepancy affects message properties

SubscriptionManager

Discrepancies

  • Python does not have a SubscriptionManager. This would be very useful once Python supports async mode.

Message Listeners

C++

 
// A message listener:

class Listener : public MessageListener{
  private:
    SubscriptionManager& subscriptions;
  public:
    Listener(SubscriptionManager& subscriptions);
    virtual void received(Message& message);
};

void Listener::received(Message& message) {
    std::cout << "Message: " << message.getData() << std::endl;
    if (endCondition(message)) {
       subscriptions.cancel(message.getDestination());
    }
}

// Using a message listener with a subscription manager:

SubscriptionManager subscriptions(session);

Listener listener(subscriptions);
subscriptions.subscribe(listener, "message_queue");
subscriptions.run();

Python

 
#----- Message Receive Handler -----------------------------
class Receiver:
  def __init__ (self):
    self.finalReceived = False

  def isFinal (self):
    return self.finalReceived

  def Handler (self, message):
    content = message.body
    session.message_accept(RangedSet(message.id))
    print content
    if content == "That's all, folks!":
      self.finalReceived = True

# Call message_subscribe() to tell the broker to deliver messages
# from the AMQP queue to this local client queue. The broker will
# start delivering messages as soon as message_subscribe() is called.

session.message_subscribe(queue="message_queue", destination=local_queue_name)
queue.start()

# Register a message listener with the queue

receiver = Receiver()
queue.listen (receiver.Handler)

while not receiver.isFinal() :
  sleep (1)

Discrepancies

  • In Python, a message handler is registered with a local queue, and the local queue is subscribed to the remote queue. In C+, a message listener is subscribed to using a Session or a Subscription Manager. I prefer the C+ approach here.

Synchronous / Asynchronous Modes

Discrepancies

  • C++ supports both synchronous and asynchronous modes. Python supports only synchronous mode. Python should support both.

Getting and Setting Message Contents

C++

 
// getData()

std::cout << "Response: " << message.getData() << std::endl;

// setData()

message.setData("That's all, folks!");

// appendData()

message.appendData(" ... let's add a bit more ...");

Python

 
message = queue.get(timeout=10)
content = message.body

Discrepancies

  • C++ calls this "message data" and accesses it via methods, Python calls it the message body and provides direct access. They are completely different

Other issues

  • Both languages should support streaming data into and out of messages
  • The C++ interface has consistently confused people who work with binary data

Getting and Setting Application Headers

C++

 
message.getHeaders().getString("control");

message.getHeaders().setString("control","continue");

Python

 
message_properties = message.get("message_properties")
message_properties.application_headers["control"] = "continue"

Discrepancies

  • Different data model. C++ has a message, which has headers. Python has a message, which has message properties, including application headers.
  • Python supports via a dictionary, which is very nice. Can I do this in C++?
Document generated by Confluence on May 26, 2010 10:31