How can I catch AmqpConnectException under Spring AMQP framework?

Viewed 1186

When I stop the rabbitmq server, the exception below will be thrown:

org.springframework.amqp.AmqpConnectException: java.net.ConnectException: Connection refused: connect
    at org.springframework.amqp.rabbit.support.RabbitExceptionTranslator.convertRabbitAccessException(RabbitExceptionTranslator.java:62) ~[spring-rabbit-1.6.6.RELEASE.jar:na]
    at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:306) ~[spring-rabbit-1.6.6.RELEASE.jar:na]
    at org.springframework.amqp.rabbit.connection.CachingConnectionFactory.createConnection(CachingConnectionFactory.java:547) ~[spring-rabbit-1.6.6.RELEASE.jar:na]
    at org.springframework.amqp.rabbit.core.RabbitTemplate.doExecute(RabbitTemplate.java:1411) ~[spring-rabbit-1.6.6.RELEASE.jar:na]
    at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1392) ~[spring-rabbit-1.6.6.RELEASE.jar:na]
    at org.springframework.amqp.rabbit.core.RabbitTemplate.execute(RabbitTemplate.java:1368) ~[spring-rabbit-1.6.6.RELEASE.jar:na]
    at org.springframework.amqp.rabbit.core.RabbitAdmin.getQueueProperties(RabbitAdmin.java:336) ~[spring-rabbit-1.6.6.RELEASE.jar:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.redeclareElementsIfNecessary(SimpleMessageListenerContainer.java:1123) [spring-rabbit-1.6.6.RELEASE.jar:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$800(SimpleMessageListenerContainer.java:98) [spring-rabbit-1.6.6.RELEASE.jar:na]
    at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1329) [spring-rabbit-1.6.6.RELEASE.jar:na]
    at java.lang.Thread.run(Unknown Source) [na:1.8.0_121]
Caused by: java.net.ConnectException: Connection refused: connect
    at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method) ~[na:1.8.0_121]
    at java.net.DualStackPlainSocketImpl.socketConnect(Unknown Source) ~[na:1.8.0_121]
    at java.net.AbstractPlainSocketImpl.doConnect(Unknown Source) ~[na:1.8.0_121]
    at java.net.AbstractPlainSocketImpl.connectToAddress(Unknown Source) ~[na:1.8.0_121]
    at java.net.AbstractPlainSocketImpl.connect(Unknown Source) ~[na:1.8.0_121]
    at java.net.PlainSocketImpl.connect(Unknown Source) ~[na:1.8.0_121]
    at java.net.SocksSocketImpl.connect(Unknown Source) ~[na:1.8.0_121]
    at java.net.Socket.connect(Unknown Source) ~[na:1.8.0_121]
    at com.rabbitmq.client.impl.FrameHandlerFactory.create(FrameHandlerFactory.java:47) ~[amqp-client-3.6.5.jar:na]
    at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:822) ~[amqp-client-3.6.5.jar:na]
    at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:778) ~[amqp-client-3.6.5.jar:na]
    at com.rabbitmq.client.ConnectionFactory.newConnection(ConnectionFactory.java:898) ~[amqp-client-3.6.5.jar:na]
    at org.springframework.amqp.rabbit.connection.AbstractConnectionFactory.createBareConnection(AbstractConnectionFactory.java:297) ~[spring-rabbit-1.6.6.RELEASE.jar:na]
    ... 9 common frames omitted

How can I catch this exception? Should I create or implement some handler?

2 Answers

I Had the same problem. When I run my application without running rabbitmq server I had these endless error messages. So, there are few solutions, depending on your needs.

  1. If you try to avoid endless messaging about the same error, you can configure RecoveryBackOff strategy for AbstractRabbitListenerContainerFactory.

    SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
    int maxAttempts = 3;
    FixedBackOff recoveryBackOff = new FixedBackOff(DEFAULT_INTERVAL, maxAttempts);
    factory.setRecoveryBackOff(recoveryBackOff);
    

    Here, maxAttemps it's max number of attempts to reconnect. And first parameter is interval between two attempts (DEFAULT_INTERVAL = 5000ms).

So, in this case SimpleMessageListenerContainer will try to reconnect three more times and will calm down.

  1. If you need to do something with these connection fails you cat implement spring ApplicationListener for ListenerContainerConsumerFailedEvent or even for more general - AmqpEvent as mentioned here

I made this way:

@Configuration
@EnableRabbit
public class AmqpConfiguration {

    @Bean
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        ExponentialBackOff recoveryBackOff = new ExponentialBackOff();
        factory.setRecoveryBackOff(recoveryBackOff);
        return factory;
    }
}

Using the BackOffExponencial class, your server will check whether rabbitMq is online. This service will check in exponential time.

Exemple:

For 10 attempts the sequence will be as follows:

request # ... back off

1 ................. 2000

2 ................. 3000

3 ................. 4500

4 ................. 6750

5 ................. 10125

6 ................. 15187

7 ................. 22780

8 ................. 30000

9 ................. 30000

10 ................. 30000

Related