Jan 23rd, 2012, 12:48 PM
Setting a binding and a queue programatically
I need to be able to set the routing key on an exchange dynamically. AFTER the spring container is brought up (and presumably bound to the broker), I want to set the routing key in a binding based on a value in the request that came in.
I understand that the AmqpAdmin implementation is a Listener. But how can I make that listener listen in on non-life cycle events (container start/stop) like a request being placed on a queue, for instance?
So if I get RabbitAdmin from the spring context and issue:
Queue xyzQueue = new Queue("xyzQueue");
rabbitAdmin.declareBinding( BindingBuilder.bind(xyzQueue).to(someExchange()).w ith("xyzRoutingKey"));
will that binding be effective on the broker from that point on?
Jan 23rd, 2012, 01:40 PM
It will be, but the queue and binding will not automatically be recreated on reconnect. I created an alternate implementation of AmqpAdmin which delegates to RabbitAdmin provided in spring-amqp and maintains maps of declared Amqp objects on the broker. It does not currently shutdown correctly with the container because for some reason the ConnectionListener.onCreate keeps getting called. This may have something to do with how we are shutting down the CachingConnectionFactory though.
Sorry for the scala. It sould be easy to rewrite in java though. I removed a lot of the spring wireup because we were not using it. It only supports ctor injection and does not look for beans during reconnect for instance.
If you notice anything wrong, let me know
Jan 24th, 2012, 02:05 PM
You are right! The container does register the newly created queues and bindings. So that's good for my use case. In fact I do NOT want the queues and bindings to survive a container crash.
But thanks for sharing your code!
Jan 24th, 2012, 02:13 PM
A listner for programatically started queues!
On a related subject.. now that I have queues registered using rabbitAdmin.declareQueue(...) and bindings via declareBinding(...).
On the receiving end, I'd like to listen to queues that were programatically created. The SimpleMessageListenerContainer, by implementing SmartLifecycle, is instantiated when the container starts up. How can I make IT to listen to the just created queues (since I do not know their names at container startup).
I maintained a map of all the programatically created queues and tried using the setQueues(queueArrayFromMap) api, but that doesn't work.
Basically, I'd like to asynchrously listen to programatically created queues.
Any help will be great!
Jan 24th, 2012, 02:33 PM
I think you would be better off creating only one queue when starting up and dynamically creating and deleting bindings.
Jan 24th, 2012, 03:02 PM
onley one queue
If I had only one queue and changed bindings on it, then what would happen to an object that is placed on the queue but not yet consumed, and it's binding is changed for the next object to be placed on the same queue.
I think that may mess things up, don't you think so?
Jan 24th, 2012, 03:10 PM
I mean one queue per consumer (unless you need to split load across multiple instances). If you need to send new messages to this consumer, add a new binding which matches the routing key for new message. If you want this consumer to stop receiving these messages, remove the binding and it will no longer receive message sent which match the routing key.