Reputation: 21
I have a spring-boot application with ActiveMQ JMS. I have a queue in the application which will get messages with a string property say color. Value of color can be red, green or blue. Application has a Rest service where it will get list of color(s) { one or more } which should be used as a SELECTOR when listening for the messages on the queue. Over the lifetime of the application, this might change, so the value of SELECTOR can look like "color='red'", "color='blue' OR color='red'" or "color='green'".
@Bean
MessageListenerAdapter adapter() {
return new MessageListenerAdapter(new Object() {
// message handler
});
}
@Bean
DefaultMessageListenerContainer container(ConnectionFactory cf) throws Exception {
DefaultMessageListenerContainer c = new DefaultMessageListenerContainer();
c.setMessageListener(adapter());
c.setConcurrency(this.concurrency);
c.setMessageSelector(this.selector);
c.setConnectionFactory(cf);
c.setDestinationName(this.q);
return c;
}
Was planning to use above code to achieve this; code works fine to start with initial selector, however when selector needs to change following code does not work.
c.stop();
// modify value of selector
c.setMessageSelector(this.selector);
c.start();
Looks like, I have a working solution. I put @Scope("prototype") on top of method container() and have a method which instantiates a new DefaultMessageListenerContainer whenever selector changes.
public void xx(String selector) {
this.selector = selector;
DefaultMessageListenerContainer c =
context.getBean("container", DefaultMessageListenerContainer.class);
c.start();
}
Is this the right way to go about this? Also, when selector changes and I instantiate a new DefaultMessageListenerContainer, what's the correct way to shutdown/stop existing DefaultMessageListenerContainer?
regards, Yogi
Upvotes: 0
Views: 2328
Reputation: 33091
The prototype thing looks a very bad idea to me.
MessageListenerContainer
is meant to be a singleton that is responsible to handle listeners for a particular queue or topic configuration. The selector is a JMS spec so you basically need to reconfigure the listener container at runtime which will require you to fully stop the listener, change its configuration and restart it. I haven't seen your code but I don't see a reason why it wouldn't work.
Having said that, why are you using a selector for this? If the selector changes during the lifetime of your application, wouldn't it be better to actually perform that selection in your own logic? Having a selector at the JMS level is interesting if you have several message types on the same queue and you want different thread pools for them (i.e. you want 5 concurrent listeners for "red" and only 2 for green for instance). If you don't have that requirement having a generic route that filters the incoming message is probably a better idea.
If you do have that requirement, stopping the container, changing its config and restarting it should work. Unfortunately it doesn't so I've created SPR-14604 to track this issue.
Upvotes: 1