How to change SimpleMessageListenerContainer's connectionFactory - spring-rabbit

I want to change the connectionFactory of SimpleMessageListenerContainer at runtime,in other words,I want to modify the RabbitMQ's connection without restarting the app. although it provided a method "setConnectionFactory",I don't know if I can only do this.What should I do if I want to achieve my goal?

Call stop() on the listener container, then setConnectionFactory(), then start().
You might want to call resetConnection() on the old factory to close its connection.

Related

How to customize lettuce connection factory settings?

It seems that, at the moment, spring data redis has no out-of-the-box sentinel password.
For this reason I'd like to intercept the redis connection factory and set it manually. Would that be possible?
Have you tried with the setPassword method of RedisSentinelConfiguration?
RedisSentinelConfiguration.setPassword()
and the unit test
RedisSentinelConfiguration sentinelConfig = new RedisSentinelConfiguration().master("master);
redisProperties.getSentinel().getNodes().forEach(...);
sentinelConfig.setPassword(RedisPassword.of(password));
return new LettuceConnectionFactory(sentinelConfig);

DefaultJmsListenerContainer using BeanFactoryPostProcessor

I am currently trying to support dynamic multiple jms provider scenario in my application. So far I did achieved to create DefaultMessageListenerContainer using post processor. Cool part is that the DefaultMessageContainerListener has destinationName property where you can easily set the queue to be listened/sent for messages.
However, the DefaultJmsListenerContainerFactory has no such method to set the queue name. I do reached at around the SimpleJmsListenerEndpoint that the DefaultJmsListenerContainerFactory using to initiate the container. But I am unable to find how to set it. Please see below what I did so far.
beanDefinitionRegistry.registerBeanDefinition("messageListenerContainer",
BeanDefinitionBuilder.rootBeanDefinition(DefaultJmsListenerContainerFactory.class)
.addPropertyReference("connectionFactory", "queueConnectionFactory")
.addPropertyReference("destinationResolver", "jndiDestinationResolver")
.addPropertyValue("concurrency", concurrency)
.addPropertyValue("sessionAcknowledgeMode", Session.AUTO_ACKNOWLEDGE)
.getBeanDefinition()
);
But as you can see I can not set the queue endpoint for listening. How can I do that from here?

How to pause/resume individual Spring JMS message listeners

My Spring Boot JMS application is consuming messages from several SQS queues. Each queue needs to connect to a different external resource in order to process its messages. If there's an external resource failure I expect the consumer requiring that resource will rapidly drain the queue to a DLQ and that's no fun.
I need to be able to suspend (pause) the message listener for each consumer independently when my code detects that its resource is offline (e.g. comms exception calling REST endpoint).
How can I do this?
After searching for platform support for this, I found the AbstractJmsListeningContainer which (via the Lifecycle interface) supports stop() and start() methodsm though it doesn't document whether start can be invoked following a stop call.
My concern is that there appears to be one shared instance among my multiple #JmsListener annotated consumers; so stopping one queue stops them all and I don't want that.
How can I achieve my end goal of pausing individual consumers?
I have seen references to using multiple bean definitions like so:
#Bean
SimpleMessageListenerContainer container1(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
// snip
}
#Bean
SimpleMessageListenerContainer container2(ConnectionFactory connectionFactory,
MessageListenerAdapter listenerAdapter) {
// snip
}
...but never seen any explanation stating how and when one will be used versus the other.
See my answer to this question.
Yes, you can call start() after stop().
Note that stop() only stops the threads; the connection remains open.
If you want to shut everything down, call shutDown() after stop() and then initialize() before start().
You should not call stop() on a listener thread, though - hand it off to another thread and wait until isRunning() is false.

How to unsubscribe from file channel in Spring Integration?

I would like to know how to unsubscribe from file channel. I was trying to direct channel and invoke unsubscribe method in my service but I don't have access to message handler and I was using FileReadingMessageSource. Any thoughts?
You need to show your configuration but generally you want to stop the SourcePollingChannelAdapter that references the source to stop the adapter. You don't want to unsubscribe, that will cause errors unless the adapter is stopped.
EDIT
With your configuration, if the inbound adapter is in a class called IntegrationCongfig, it's bean name will be integrationConfig.test.inboundChannelAdapter (note lower case i)...
#Autowired
#Qualifier("integrationConfig.test.inboundChannelAdapter")
private SourcePollingChannelAdapter test;
#Autowired
private StandardIntegrationFlow processFileFlow;
...
this.test.stop(); // stop the adapter
this.processFileFlow.stop(); // stops all components in the flow
Stopping the flow will unsubscribe the handler from the channel; but you MUST stop the adapter first.

Prevent use of CachingConnectionFactory with DefaultJmsListenerContainerFactory

I am working on a brand new project in which I need to have listeners that will consume messages from several queues (no need to have producer for now).
Starting from scratch, I am using the last Spring JMS version (4.1.2).
Here is an extract of my configuration file:
<bean id="cachedConnectionFactory"
class="org.springframework.jms.connection.CachingConnectionFactory"
p:targetConnectionFactory-ref="jmsConnectionFactory"
p:sessionCacheSize="3" />
<bean id="jmsListenerContainerFactory"
class="org.springframework.jms.config.DefaultJmsListenerContainerFactory"
p:connectionFactory-ref="cachedConnectionFactory"
p:destinationResolver-ref="jndiDestinationResolver"
p:concurrency="3-5"
p:receiveTimeout="5000" />
But I think I may be wrong since DefaultJmsListenerContainerFactory will build regular DefaultMessageListenerContainerS. And, as stated in the doc, CachingConnectionFactory should not be used with a message listener container...
Even if I am using the new Spring 4.1 DefaultJmsListenerContainerFactory class the answer from post is still valid (cacheConsumers = true can be an issue + don't need to cache sessions for listener containers because the sessions are long lived) , right?
Instead of using the CachingConnectionFactory, I should use the SingleConnectionFactory (and not directly the broker implementation one)?
If the SingleConnectionFactory class should indeed be used, is the "reconnectOnException" property should be set to true (as it is done in the CachingConnectionFactory) or does the new "setBackOff" method (from DefaultJmsListenerContainerFactory) deals with the same kind of issues?
Thanks for any tips
Correct.
There's not really much benefit in using a SingleConnectionFactory unless you want to share a single connection across multiple containers; the DMLC will use a single connection from the vendor factory by default for all consumer threads (cacheLevel >= CACHE_CONNECTION), unless a TransactionManager is configured.
The container(s) will handle reconnection - even before the 'new' backOff property - backOff just adds more sophistication to the reconnection algorithm - it used to just retry every n seconds (5 by default).
As stated in the answer you cited, it's ok to use a CCF as long as you disable consumer caching.
Correction: Yes, when using the SingleConnectionFactory, you do need to set reconnectOnException to true in order for the container to properly recover its connection. Otherwise, it simply hands out the stale connection.

Resources