Using the XML Exchange

The XML Exchange allows routing decisions to be made using XQuery. It is used primarily for two things:

  • XML Content-based Routing - a queue can be bound to an exchange using an XQuery that identifies “interesting” messages. This is particularly useful when the message publisher does not know what information a message consumer may use to decide whether to route the message, since the publisher and consumer do not need to agree on a set of headers.
  • Queries on Headers - the XML Exchange can query headers using XQuery whether or not the message content is in XML, so this provides query capability analogous to Java JMS Selectors. And the same query may use data from both headers and message content.

In this post, I will focus on XML content-based routing. Suppose a message publisher sends weather report data to an XML Exchange using the routing key “weather”. It might use the National Weather Service’s XML format - here’s an example of a report in this format:

http://www.weather.gov/xml/current_obs/KRDU.xml

Here’s a simpler version that we will use in our sample program:

<weather>
    <station>Raleigh-Durham International Airport (KRDU)</station>
    <wind_speed_mph>16</wind_speed_mph>
    <temperature_f>70</temperature_f>
    <dewpoint>35</dewpoint>
</weather>

Now I want to write a message consumer that tells me when there is good weather for sailing. In this post I will show how to route messages to a queue - the complete program is one of the Apache Qpid examples, and is covered in Red Hat’s MRG Messaging Tutorial.

In my little sailboat, I don’t like wind above 20 mph, and it’s a lot more fun when there’s at least 7 mph wind. Rain isn’t a big issue, but it’s a little nicer when it’s not raining, so I’d like to be 5 degrees above dewpoint or so. And I don’t usually sail when it’s colder than 50 degrees, which makes me a bit of a wimp. Here is an XQuery that tests a message to see if it meets these criteria:

   let $w := ./weather
   return $w/station = 'Raleigh-Durham International Airport (KRDU)'
      and $w/temperature_f > 50
      and $w/temperature_f - $w/dewpoint > 5
      and $w/wind_speed_mph > 7
      and $w/wind_speed_mph < 20

Now I can take that query and bind it to the XML Exchange, asking that it be used to decide whether to route messages with the routing key “weather”. In Python, that looks like this:

session.queue_declare(queue="message_queue")

binding = {}
binding["xquery"] = """
   let $w := ./weather
   return $w/station = 'Raleigh-Durham International Airport (KRDU)'
      and $w/temperature_f > 50
      and $w/temperature_f - $w/dewpoint > 5
      and $w/wind_speed_mph > 7
      and $w/wind_speed_mph < 20 """

session.exchange_bind(exchange="xml", queue="message_queue", binding_key="weather", arguments=binding)

As you can see, the XML Exchange allows message consumers to use sophisticated queries to decide which messages are interesting, and the message producer does not need to do anything special to provide the data used for these routing decisions. And it’s very simple to use!

Leave a Reply