Handling Custom exception for rabbitmq listener connectivity issues - rabbitmq

I have a listener which consumes the messages from the third party producer.I need to send the custom error message in case of the queue connection issues
I'm new to rabbit mq .May I know what are the ways to handle the custom exception here

You can use a ConnectionListener callback and inject it into a org.springframework.amqp.rabbit.connection.ConnectionFactory configuration:
void addConnectionListener(ConnectionListener listener);
https://docs.spring.io/spring-amqp/docs/current/reference/html/#connection-channel-listeners

Related

Create RabbitMQ queue using spring cloud stream without a consumer or without an active consumer

Is there a way to create a RabbitMQ queue using spring cloud stream without having a consumer for the queue.
Our scenario is that we want to use the delay messaging strategy, so messages coming to the first queue would be held until expired and moved to a DLQ.
The application would be consuming the messages from the DLQ.
Wanted to check if there is a way we can use spring cloud stream to configure the queues, when we do not have a consumer for the first queue and it's just there to hold messages till expiry.
Yes; simply add a Queue bean (and binding if needed).
Boot auto configures a RabbitAdmin which will detect such beans when the connection is first established.
https://docs.spring.io/spring-amqp/docs/current/reference/html/#broker-configuration
#Bean
public Queue queue() {
return QueueBuilder.nonDurable("foo")
.autoDelete()
.exclusive()
.withArgument("foo", "bar")
.build();
}

ActiveMQ broker error "Setup of JMS message listener invoker failed for destination trying to recover. Cause: The Consumer is closed"

We have observed in our enviornment as consumer from ActiveMQ UI get removed. We have very low traffic and observed as initially we have 3 consumer and those got each of them removed after interval of couple hours and once we restart our consumer it again refresh connection for couple more hours, we dont see any error in logs except:
Setup of JMS message listener invoker failed for destination 'queue-1' - trying to recover. Cause: The Consumer is closed
I use AWS ActiveMQ broker and don't see any error in the broker logs.
We use PoolConnectionFactory with ActiveMQConnectionFactory for creating pool of connection for our consumer as recommended. we are using ActiveMQ 5.15
#Bean
public PooledConnectionFactory pooledConnectionFactory() {
ActiveMQConnectionFactory activeMQConnectionFactory =
new ActiveMQConnectionFactory();
activeMQConnectionFactory.setBrokerURL(brokerUrl);
activeMQConnectionFactory.setUserName(username);
activeMQConnectionFactory.setPassword(password);
activeMQConnectionFactory.setTrustAllPackages(true);
ActiveMQPrefetchPolicy activeMQPrefetchPolicy = new ActiveMQPrefetchPolicy();
activeMQPrefetchPolicy.setQueuePrefetch(100);
//activeMQPrefetchPolicy.setQueuePrefetch();
activeMQConnectionFactory.setPrefetchPolicy(activeMQPrefetchPolicy);
PooledConnectionFactory pooledConnectionFactory = new PooledConnectionFactory(activeMQConnectionFactory);
pooledConnectionFactory.setMaxConnections(poolSize);
return pooledConnectionFactory;
}
#Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() {
DefaultJmsListenerContainerFactory factory =
new DefaultJmsListenerContainerFactory();
factory.setConnectionFactory(pooledConnectionFactory());
factory.setMessageConverter(jacksonJmsMessageConverter());
factory.setSessionAcknowledgeMode(Session.CLIENT_ACKNOWLEDGE);
factory.setConcurrency("1-1");
factory.setErrorHandler(ActiveMQErrorHandler());
return factory;
}
#Bean
public JmsTemplate jmsTemplate() {
JmsTemplate jmsTemplate = new JmsTemplate(pooledConnectionFactory());
jmsTemplate.setMessageConverter(jacksonJmsMessageConverter());
return jmsTemplate;
}
#Bean
public Queue queue() {
return new ActiveMQQueue(queueName);
}
#Bean
public ErrorHandler ActiveMQErrorHandler() {
return t -> {
LOGGER.error("JMS_LISTENER_ERROR");
};
}
Given the information provided it sounds as though either the connection is dropping and the client isn't reporting that or the remote is closing the consumer on it's end which the pool will likely not notice until some user action is performed.
This is one of the gotchas of using a JMS pool which is that the pool doesn't have complete insight into what is going on with the client and therefore checking out a connection that's been sitting in the pool can result in obtaining a stale and no longer active connection due to the IO interruption that doesn't bubble up to the pool layer. One means of working around this would be to use the ActiveMQ client failover transport to allow it to automatically reconnect to the broker if the connection is dropped.
Another option you could try is to use the PooledJMS JMS connection pooling library which has some additional work done to attempt to validate failed connections and or closed resources sooner and match that with a ConnectionFactory that creates ActiveMQ connection's that use failover so that remotely closed resources like consumers could be caught in some cases.
Ultimately though your code will still need to deal with potential failure cases out of the JMS resources and retry where needed such as senders seeing security exceptions etc. The pooling bits don't make all your troubles go away, and in some cases they just introduce new one's you hadn't thought of yet.

Spring AMQP RabbitMQ - Error Handling for Direct reply-to

I am trying to handle exceptions that are resulting from a amq.rabbitmq.reply-to queue specificially things like: "org.springframework.amqp.AmqpRejectAndDontRequeueException: Reply received after timeout". How can I configure something so I can handle these exceptions? I have tried setting the setErrorHandler properity, but it appears to do nothing. If I get an error on my input queue the handler works, but not with the RPC response queue. Any ideas?
Thanks in advance,
Brian
As discussed in Spring AMQP RabbitMQ RPC - Handle response exceptions you need an explicit reply container to handle replies with more sophistication; you can wire an error handler into that container.
There is currently no support for adding an error handler to the built-in direct reply-to container.
Consider opening a new feature issue.
This would be a rather trivial enhancement.

Check if BeginPeek is still Subscribed

I am using BeginPeek() /no params/ to subscribe to messages coming in to my private queue. This is being done in a service hosted in NServiceBus host. When NServiceBus encounters transport connection timeout exception (i'm seeing circuit breaker armed logs and timeout exception logs), the peek event subscription seems get lost. When database connectivity becomes stable and new messages come in to my queue, the service is no longer notified.
Any ideas or suggestions on how to address this?

Storm to read message from RabbitMq using Spring AMQP

I want to consume the messages in my Storm Spout from a rabbitMq Queue.
Now , we are using Spring AMQP to send and receive messages from RabbitMq asynchronously.
Spring AMQP provides mechanism(either creating a listener or using annotation #RabbitListner) to read message from the queue .
The problem is I can have a Listener to read the message from the Queue. But how do I send this message to my Storm Spout which is running on storm cluster ?
The topology will start a cluster, but in my nextTuple() method of my spout , I need to read message from this Queue. Can Spring AMQP be used here ?
I have a listener configured to read message from the queue:
#RabbitListener(queues = "queueName")
public void processMessage(QueueMessage message) {
}
How can the above message received at the listener be sent to my spout running on a cluster .
Alternatively , how can a spout's nextTuple() method have this method inside it ? Is it possible
I am using Java as a language here.
You can read messages on-demand (rather than being message-driven) by using one of the RabbitTemplate receive or receiveAndConvert methods.
By default, they will return null if there is no message in the queue.
EDIT:
If you set the receiveTimeout (available in version 1.5 or above), the receive methods will block for that time (it uses an async consumer internally and does not poll).
But it's still not as efficient as the listener because a new consumer is created for each method; to use a listener you would need to use some internal blocking mechanism in nextTuple() (e.g. a BlockingQueue) to wait for messages.