skip to content

How do the exchange and routing key arguments to convertAndSend interact with exchange types?

level: middleimportance: should knowfreq 40%

answer

  1. direct = exact binding-key match
  2. topic = dot words, * one word, # zero-or-more
  3. fanout = ignores routing key, broadcast
  4. headers = matches on headers not key
  5. no match -> silently dropped unless mandatory + ReturnsCallback

basics

~20 s

The exchange receives the message; the routing key is matched against the exchange's bindings to pick queues. Direct exchanges need an exact key match, topic exchanges use wildcard patterns, and fanout exchanges ignore the routing key entirely.

solid answer

~40 s

convertAndSend(exchange, routingKey, payload) publishes to the named exchange; how the routing key selects queues depends on the exchange type. A direct exchange delivers to queues whose binding key exactly equals the routing key. A topic exchange matches the routing key (dot-separated words) against binding patterns with wildcards: * matches exactly one word, # matches zero or more words. A fanout exchange ignores the routing key and broadcasts to every bound queue. A headers exchange ignores the routing key and matches on message headers instead. If the routing key matches no binding, the message is unroutable and silently dropped — unless you publish with the mandatory flag and register a ReturnsCallback, in which case the broker returns it. The empty-string exchange is the default direct exchange where each queue is bound by its own name.

code

java · 14 lines
java
// Topic routing: consumers bind with patterns, producer sends specific keys.
@Configuration
public class TopicTopology {
    @Bean TopicExchange orders() { return new TopicExchange("orders.topic"); }
    @Bean Queue euOrders() { return new Queue("orders.eu"); }
    @Bean Binding euBinding(Queue euOrders, TopicExchange orders) {
        // '*' = exactly one word -> matches order.eu.created, not order.created
        return BindingBuilder.bind(euOrders).to(orders).with("order.*.created");
    }
}

// Producer:
// rabbitTemplate.convertAndSend("orders.topic", "order.eu.created", event);
// -> routed to orders.eu queue

go deeper

for a junior

Know the exchange gets the message and the routing key helps pick the queue.

for a middle

Explain direct/topic/fanout behavior and topic wildcards * and #.

for a senior

Cover unroutable-message handling with mandatory + ReturnsCallback and alternate exchanges.

for a principal

Choose exchange topology to match consumer subscription needs and design for undeliverable-message safety.

## Recap of the model The producer's two routing inputs are the **exchange name** and the **routing key** (a string). The exchange's **type** governs how it uses the routing key together with its **bindings** (rules created with a binding key linking exchange→queue). ## Exchange types - **Direct exchange:** delivers a message to queues whose **binding key exactly equals** the message's routing key. Example: a queue bound with key `order.created` receives messages sent with routing key `order.created` only. Good for simple point-to-point-by-key routing. - **Topic exchange:** the routing key is a list of **dot-separated words** (e.g., `order.eu.created`). Bindings use patterns with two wildcards: `*` matches **exactly one word**, `#` matches **zero or more words**. So `order.*.created` matches `order.eu.created` but not `order.created`; `order.#` matches `order`, `order.created`, and `order.eu.created`. Ideal for flexible, hierarchical routing. - **Fanout exchange:** **ignores the routing key entirely** and broadcasts a copy to every bound queue. Used for pub/sub broadcast (e.g., cache-invalidation events). You still pass a routing key argument to convertAndSend, but it has no effect. - **Headers exchange:** also ignores the routing key; it routes on **message header attributes** matched against binding arguments (`x-match=all|any`). Less common. ## Default exchange The empty-string exchange `""` is a special pre-declared **direct** exchange to which every queue is automatically bound using its **queue name** as the binding key. Hence `convertAndSend("", "audit.queue", payload)` goes straight to the queue named `audit.queue`. This is why beginners think 'routing key = queue name' — true only here. ## Unroutable messages — a critical gotcha If no binding matches the exchange/routing-key, the message is **silently discarded** by default. To detect this, publish with the **mandatory** flag (`rabbitTemplate.setMandatory(true)` or per-message) and register a `ReturnsCallback` (`setReturnsCallback`) — the broker then *returns* the unroutable message to the producer instead of dropping it. Without this, a typo in the routing key causes silent message loss. **Alternate exchanges:** an exchange can be configured with an *alternate-exchange* so unroutable messages go there instead of being dropped — a broker-side safety net complementary to mandatory/returns. ## Declaring topology convertAndSend does **not** create exchanges, queues, or bindings. You declare them with `@Bean` definitions of `Exchange`/`Queue`/`Binding` (Spring AMQP auto-declares them via a `RabbitAdmin`) or externally. Publishing to a non-existent exchange raises a channel error (with confirms) — not a silent drop like the unroutable-queue case. ## When to choose which - **direct** for exact-key routing; - **topic** for hierarchical/selective subscriptions; - **fanout** for broadcast; - **headers** for attribute-based routing. Match the exchange type to how consumers want to subscribe.

  • You send a message with a routing key that matches no binding. What happens and how do you detect it?
    By default it's silently discarded. Enable the mandatory flag and register a ReturnsCallback so the broker returns the unroutable message to the producer; alternatively configure an alternate-exchange on the broker.
  • In a topic exchange, what's the difference between * and # in a binding pattern?
    * matches exactly one dot-separated word; # matches zero or more words. So order.# also matches plain 'order', while order.* requires exactly one word after 'order'.

saying these in an interview costs you the question

  • Thinking fanout still uses the routing key
  • Assuming an unroutable message errors or is retried (it's silently dropped by default)
  • Believing convertAndSend declares the exchange/queue/binding for you

context