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()
Red Hat logoGithubRedditYoutubeTwitter

Learn

Try, buy, & sell

Communities

About Red Hat Documentation

We help Red Hat users innovate and achieve their goals with our products and services with content they can trust.

Making open source more inclusive

Red Hat is committed to replacing problematic language in our code, documentation, and web properties. For more details, see the Red Hat Blog.

About Red Hat

We deliver hardened solutions that make it easier for enterprises to work across platforms and environments, from the core datacenter to the network edge.

© 2024 Red Hat, Inc.