19.3. AMQP Routing Key and Message Subject
Whenever you send a message using the Qpid Messaging API in Red Hat Enterprise Messaging, the
x-amqp-0-10.routing-key
property is set to the value of the message subject, with one exception.
Any message that has a subject explicitly set has its subject preserved and the AMQP routing key set to the message subject when it is sent.
When a message has no subject manually set, its subject is set by the sender, if the sender's destination address contains a subject.
Take for example, the following sender:
sender = session.sender('amq.topic/SubjectX')
Given these two messages:
msg1 = Message('A message with no subject') msg2 = Message('A message with a subject') msg2.subject = 'SubjectY'
msg1
has its subject and AMQP routing key set to 'SubjectX
'. msg2
retains its subject 'SubjectY
', and has its AMQP routing key set to 'SubjectY
'.
There are only two other cases.
The first is when a message with no subject is sent via a sender with no subject in its destination address. For example, in Python:
sender = session('amq.topic') msg = Message('No subject, and none assigned by the sender') sender.send(msg)
In this case the message is sent with a blank subject and a blank AMQP routing key.
The second, and only exceptional case, is when a message with a blank subject and a manually assigned AMQP routing key is sent via a sender with no subject in its destination address. For example, in Python:
sender = session('amq.topic') msg = Message('No subject, but a manually assigned AMQP routing key') msg.properties['x-amqp-0-10.routing-key'] = 'amqp-SubjectX' sender.send(msg)
In this case, the message is sent with a blank subject, and the arbitrary AMQP routing key assigned.
Note that in this case the message will not route in a Red Hat Enterprise Messaging topic exchange. The
amqp-0-10.routing-key
may be useful in an interoperability scenario, but in Red Hat Enterprise Messaging the message subject
is used for routing.
The following Python program demonstrates the various permutations of interaction between message subject, sender destination address subject, and message routing key:
import sys from qpid.messaging import * # This program demonstrates that the x-amqp-0-10.routing-key # (1) is (re)set to the message subject when the message has a subject or # is sent via a sender that has a subject # (2) is not a valid basis for routing in a topic exchange # - the topic exchange will not route a message to a queue def sendmsg(msg, note = ''): global rxplain, rxsubject, txplain, txsubject, ssn, testcount msg.properties['sender'] = 'Plain Sender' txplain.send(msg) msg.properties['sender'] = 'SubjectX Sender' txsubject.send(msg) if testcount > 0: x = raw_input('\nPress Enter for the next test message') print '\n================================================\n' testcount = testcount + 1 print '\nScenario ' + str(testcount) print '\nSent message:\n' subject = 'Blank' if msg.subject: subject = msg.subject print 'Subject:\t' + subject routekey = 'Blank' if 'x-amqp-0-10.routing-key' in msg.properties: routekey = msg.properties['x-amqp-0-10.routing-key'] print 'Routing Key:\t' + routekey msgcount = 0 print '\nThe queue listening for all messages received:' try: while True: rxmsg = rxplain.fetch(timeout = 1) subject ='Blank' if rxmsg.subject: subject = rxmsg.subject routekey = 'Blank' if 'x-amqp-0-10.routing-key' in rxmsg.properties: routekey = rxmsg.properties['x-amqp-0-10.routing-key'] print '\nSubject:\t' + subject print 'Routing Key:\t' + routekey print 'Sent via:\t' + rxmsg.properties['sender'] msgcount = 1 ssn.acknowledge(rxmsg) except: pass if msgcount == 0: print 'Nothing\n' else: msgcount = 0 print '\nThe queue listening for SubjectX messages received:' try: while True: rxmsg = rxsubject.fetch(timeout = 1) subject ='Blank' if rxmsg.subject: subject = rxmsg.subject routekey = 'Blank' if 'x-amqp-0-10.routing-key' in rxmsg.properties: routekey = rxmsg.properties['x-amqp-0-10.routing-key'] print '\nSubject:\t' + subject print 'Routing Key:\t' + routekey print 'Sent via:\t' + rxmsg.properties['sender'] msgcount = 1 ssn.acknowledge(rxmsg) except: pass if msgcount == 0: print 'Nothing\n' if note != '': print '\nNote: ' + note + "\n" connection = Connection("localhost:5672") connection.open() try: ssn = connection.session() # we create our receivers here so that queues are created to hold the messages sent rxplain = ssn.receiver("amq.topic") rxsubject = ssn.receiver("amq.topic/SubjectX") txplain = ssn.sender("amq.topic") txsubject = ssn.sender("amq.topic/SubjectX") testcount = 0 msg = Message("Plain message, no subject") sendmsg(msg, "a subject sender writes the subject and routing key when a message has no subject, a plain sender does not") msg = Message("Message with subject") msg.subject = "SubjectX" sendmsg(msg, "a plain sender writes the routing key if the message has a subject") msg = Message("Message with a different subject") msg.subject = "SubjectY" sendmsg(msg, "a subject sender does not rewrite a subject, both senders use the message subject to write routing key") msg = Message("Message with routing key") msg.properties["x-amqp-0-10.routing-key"] = "SubjectX" sendmsg(msg, "a routing key is not sufficient to route to a queue - the match is on subject") msg = Message("Message with different routing key") msg.properties["x-amqp-0-10.routing-key"] = "SubjectY" sendmsg(msg, "the only case where you can manually set a non-blank routing key is a message with a blank subject, sent via a plain sender") msg = Message("Message with different routing key and subject") msg.properties["x-amqp-0-10.routing-key"] = "SubjectY" msg.subject = "SubjectZ" sendmsg(msg, "all messages with subjects and all messages sent via a subject sender have their routing key rewritten") finally: connection.close()