From a0398ac4f4fe0e06b0bf62c735f6e8c6b54fc66a Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Tue, 14 Mar 2023 15:33:49 -0400 Subject: [PATCH] GH-2425: Fix NPE in ACFactory.shutdownCompleted Resolves https://github.com/spring-projects/spring-amqp/issues/2425 Assume connection problem when no cause. **cherry-pick to 2.4.x** --- .../connection/AbstractConnectionFactory.java | 8 +++-- .../AbstractConnectionFactoryTests.java | 2 +- .../CachingConnectionFactoryTests.java | 35 +++++++++++++++++++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/connection/AbstractConnectionFactory.java b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/connection/AbstractConnectionFactory.java index e6ebec08..0735a691 100644 --- a/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/connection/AbstractConnectionFactory.java +++ b/spring-rabbit/src/main/java/org/springframework/amqp/rabbit/connection/AbstractConnectionFactory.java @@ -55,6 +55,7 @@ import org.springframework.util.StringUtils; import com.rabbitmq.client.Address; import com.rabbitmq.client.AddressResolver; import com.rabbitmq.client.BlockedListener; +import com.rabbitmq.client.Method; import com.rabbitmq.client.Recoverable; import com.rabbitmq.client.RecoveryListener; import com.rabbitmq.client.ShutdownListener; @@ -660,7 +661,11 @@ public abstract class AbstractConnectionFactory implements ConnectionFactory, Di @Override public void shutdownCompleted(ShutdownSignalException cause) { - int protocolClassId = cause.getReason().protocolClassId(); + Method reason = cause.getReason(); + int protocolClassId = RabbitUtils.CONNECTION_PROTOCOL_CLASS_ID_10; + if (reason != null) { + protocolClassId = reason.protocolClassId(); + } if (protocolClassId == RabbitUtils.CHANNEL_PROTOCOL_CLASS_ID_20) { this.closeExceptionLogger.log(this.logger, "Shutdown Signal", cause); getChannelListener().onShutDown(cause); @@ -668,7 +673,6 @@ public abstract class AbstractConnectionFactory implements ConnectionFactory, Di else if (protocolClassId == RabbitUtils.CONNECTION_PROTOCOL_CLASS_ID_10) { getConnectionListener().onShutDown(cause); } - } @Override diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/connection/AbstractConnectionFactoryTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/connection/AbstractConnectionFactoryTests.java index cab3e670..60e2591b 100644 --- a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/connection/AbstractConnectionFactoryTests.java +++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/connection/AbstractConnectionFactoryTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2010-2022 the original author or authors. + * Copyright 2010-2023 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/connection/CachingConnectionFactoryTests.java b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/connection/CachingConnectionFactoryTests.java index 5d8165ac..530e93f3 100644 --- a/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/connection/CachingConnectionFactoryTests.java +++ b/spring-rabbit/src/test/java/org/springframework/amqp/rabbit/connection/CachingConnectionFactoryTests.java @@ -1932,4 +1932,39 @@ public class CachingConnectionFactoryTests extends AbstractConnectionFactoryTest verify(mockConnectionFactory).newConnection(any(ExecutorService.class), eq(resolver), anyString()); } + @Test + void nullShutdownCause() { + com.rabbitmq.client.ConnectionFactory mockConnectionFactory = mock(com.rabbitmq.client.ConnectionFactory.class); + AbstractConnectionFactory cf = createConnectionFactory(mockConnectionFactory); + AtomicBoolean connShutDown = new AtomicBoolean(); + cf.addConnectionListener(new ConnectionListener() { + + @Override + public void onCreate(Connection connection) { + } + + @Override + public void onShutDown(ShutdownSignalException signal) { + connShutDown.set(true); + } + + }); + AtomicBoolean chanShutDown = new AtomicBoolean(); + cf.addChannelListener(new ChannelListener() { + + @Override + public void onCreate(Channel channel, boolean transactional) { + } + + @Override + public void onShutDown(ShutdownSignalException signal) { + chanShutDown.set(true); + } + + }); + cf.shutdownCompleted(new ShutdownSignalException(false, false, null, chanShutDown)); + assertThat(connShutDown.get()).isTrue(); + assertThat(chanShutDown.get()).isFalse(); + } + }