Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I change spring parameters on execution?

I have an application which uses dynamic consumers. I'm using Spring Framework with RabbitMQ.

I have parameters like concurrentConsumers and maxConcurrentConsumers.

This is a example:

@Bean 
public SimpleMessageListenerContainer container(ConnectionFactory connection) {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();

    container.setMaxConcurrentConsumers(8);
    container.setConcurrentConsumers(1);

    return container;
}

Can I change the values when the application is running? For example, if I want 5 maxConcurrentConsumers instead of 8, can I change the value on a terminal or something like this while the application is running?

like image 682
Maverick94 Avatar asked Nov 07 '22 23:11

Maverick94


1 Answers

Your bean is a singleton and should be stateless (at least, immutable or effectively stateless) to ensure thread-safety and correctness.

As a rule, you should use the prototype scope for all stateful beans and the singleton scope for stateless beans.

Spring documentation

Sometimes, the creation of a bean is quite expensive, so it's more reasonable to construct an instance once and then guarantee that all possible changes made on this object will be permeated in a safe and correct fashion over all its consumers.

I advise building a simple event-driven mechanism.

There are

  • a MessageListenerContainerEvent extends ApplicationEvent which represents the changes made to the MessageListenerContainer bean;
  • a MessageListenerContainerChanger implements ApplicationListener<MessageListenerContainerEvent> who is the one listener who modifies the state of the bean, and guarantees that everything works properly;
  • other listeners who are class that use the bean and are interested in keeping it up-to-date. It's not necessary to send the changes to bean consumers, you could just notify them with no message. For them, it means that some properties of the bean they use locally might be out-of-date.
  • a publisher which could be an HTTP endpoint, or a @ShellMethod.

It might look too complex, you always can simplify it to

// somewhere in your code
synchronized(bean) {
    bean.setConcurrentConsumers(10);
}

but bear in mind the correctness this snippet propagates.

like image 64
Andrew Tobilko Avatar answered Nov 12 '22 22:11

Andrew Tobilko