Reputation: 1505
I have recently started learning Spring and spring-amqp so this question might appear very basic so please excuse me for that.
I have multiple queues which are on different hosts and have different QueueName, RoutingKey, vhost, user, password. I am writing the publishing logic for these queues and was not able to decide if I should have one configuration class per queue or can it be done in XML.
The method of creating a class to have all the information about the queue (host, vhost, username etc) is working fine as described in this example. I created a @Configuration class and defined all the beans for that Queue. But then I need to do
ApplicationContext context = new AnnotationConfigApplicationContext(MyQueueConfiguration.class);
AmqpTemplate amqpTemplate = context.getBean(AmqpTemplate.class);
amqpTemplate.convertAndSend("Hello World!!");
So my requirement is:
So for each queue do I always need to do:
ApplicationContext context = new AnnotationConfigApplicationContext(HelloWorldConfiguration.class);
Or is there a way to Spring load the all my Queue configuration classes and just use the object like:
// calling code when I get a POST request
MyQueueConfigurationClass.publishMessage(payload, queueName);
// The implementation code
public boolean publishMessage(String payload, String queueName){
// Get Bean for the **queueName** somehow
AmqpTemplate amqpTemplate = context.getBean(AmqpTemplate.class);
// Use the bean to send the message
amqpTemplate.convertAndSend(payload);
}
new AnnotationConfigApplicationContext()
everytime?Upvotes: 2
Views: 3112
Reputation: 174554
You should not create a new context each time; that is very wasteful.
You can add multiple connection factories (one for each rabbit host) to the root (or web) context, and then use a Routing Connection Factory together with a sendConnectionFactorySelectorExpression
to select the proper host based on the message you are sending.
Or, you can simply wire up a different RabbitTemplate
for each server.
EDIT:
To use the SimpleRoutingConnectionFactory
, do something like...
try {
SimpleResourceHolder.bind(routingCF, keyForThisMessage);
rabbitTemplate.convertAndSend(message);
}
finally {
SimpleResourceHolder.unbind(routingCF);
}
(this will work with an unmodified RabbitTemplate
) or...
<rabbit:template id="routingTemplate"
connection-factory="rcf"
send-connection-factory-selector-expression="messageProperties.headers['cfKey']" />
<bean id="rcf" class="org.springframework.amqp.rabbit.connection.SimpleRoutingConnectionFactory">
<property name="targetConnectionFactories">
<map>
<entry key="foo" value-ref="cf1"/>
<entry key="bar" value-ref="cf2"/>
</map>
</property>
<property name="defaultTargetConnectionFactory" ref="defaultCF"/>
</bean>
...and then...
this.routingTemplate.convertAndSend("exchange", "routingKey", "xyz", new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setHeader("cfKey", "foo");
return message;
}
});
There's a complete test case here.
Upvotes: 3