From 685a195ba17be18479ab682f808b14d8c586b3fa Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Tue, 15 Feb 2022 14:28:50 +0100 Subject: [PATCH] Deprecate SocketUtils SocketUtils was introduced in Spring Framework 4.0, primarily to assist in writing integration tests which start an external server on an available random port. However, these utilities make no guarantee about the subsequent availability of a given port and are therefore unreliable. Instead of using SocketUtils to find an available local port for a server, it is recommended that users rely on a server's ability to start on a random port that it selects or is assigned by the operating system. To interact with that server, the user should query the server for the port it is currently using. SocketUtils is now deprecated in 5.3.16 and will be removed in 6.0. Closes gh-28052 --- .../access/MBeanClientInterceptorTests.java | 6 +- .../RemoteMBeanClientInterceptorTests.java | 7 +-- .../ConnectorServerFactoryBeanTests.java | 6 +- ...MBeanServerConnectionFactoryBeanTests.java | 6 +- .../org/springframework/util/SocketUtils.java | 14 ++++- .../util/SocketUtilsTests.java | 63 ++++++++++--------- .../ReactorNettyTcpStompClientTests.java | 6 +- ...erRelayMessageHandlerIntegrationTests.java | 6 +- .../remoting/caucho/CauchoRemotingTests.java | 5 +- .../client/WebClientIntegrationTests.java | 6 +- 10 files changed, 69 insertions(+), 56 deletions(-) diff --git a/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java b/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java index f98384c231ac..f9863819b447 100644 --- a/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/access/MBeanClientInterceptorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -39,7 +39,6 @@ import org.springframework.jmx.JmxTestBean; import org.springframework.jmx.export.MBeanExporter; import org.springframework.jmx.export.assembler.AbstractReflectiveMBeanInfoAssembler; -import org.springframework.util.SocketUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -177,7 +176,8 @@ void invokeUnexposedMethodWithException() throws Exception { void lazyConnectionToRemote() throws Exception { assumeTrue(runTests); - final int port = SocketUtils.findAvailableTcpPort(); + @SuppressWarnings("deprecation") + final int port = org.springframework.util.SocketUtils.findAvailableTcpPort(); JMXServiceURL url = new JMXServiceURL("service:jmx:jmxmp://localhost:" + port); JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, getServer()); diff --git a/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java b/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java index 5c4c4a3c0820..a617803188d7 100644 --- a/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/access/RemoteMBeanClientInterceptorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -28,8 +28,6 @@ import org.junit.jupiter.api.AfterEach; -import org.springframework.util.SocketUtils; - /** * @author Rob Harrop * @author Chris Beams @@ -37,7 +35,8 @@ */ class RemoteMBeanClientInterceptorTests extends MBeanClientInterceptorTests { - private final int servicePort = SocketUtils.findAvailableTcpPort(); + @SuppressWarnings("deprecation") + private final int servicePort = org.springframework.util.SocketUtils.findAvailableTcpPort(); private final String serviceUrl = "service:jmx:jmxmp://localhost:" + servicePort; diff --git a/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java b/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java index 111721d749b1..fad3ed40ec00 100644 --- a/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/support/ConnectorServerFactoryBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -31,7 +31,6 @@ import org.junit.jupiter.api.Test; import org.springframework.jmx.AbstractMBeanServerTests; -import org.springframework.util.SocketUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -47,7 +46,8 @@ class ConnectorServerFactoryBeanTests extends AbstractMBeanServerTests { private static final String OBJECT_NAME = "spring:type=connector,name=test"; - private final String serviceUrl = "service:jmx:jmxmp://localhost:" + SocketUtils.findAvailableTcpPort(); + @SuppressWarnings("deprecation") + private final String serviceUrl = "service:jmx:jmxmp://localhost:" + org.springframework.util.SocketUtils.findAvailableTcpPort(); @Test diff --git a/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java b/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java index faee0ae016c2..64159c6e5146 100644 --- a/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java +++ b/spring-context/src/test/java/org/springframework/jmx/support/MBeanServerConnectionFactoryBeanTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -25,7 +25,6 @@ import org.springframework.aop.support.AopUtils; import org.springframework.jmx.AbstractMBeanServerTests; -import org.springframework.util.SocketUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; @@ -39,7 +38,8 @@ */ class MBeanServerConnectionFactoryBeanTests extends AbstractMBeanServerTests { - private final String serviceUrl = "service:jmx:jmxmp://localhost:" + SocketUtils.findAvailableTcpPort(); + @SuppressWarnings("deprecation") + private final String serviceUrl = "service:jmx:jmxmp://localhost:" + org.springframework.util.SocketUtils.findAvailableTcpPort(); @Test diff --git a/spring-core/src/main/java/org/springframework/util/SocketUtils.java b/spring-core/src/main/java/org/springframework/util/SocketUtils.java index 557173e7e59c..a100bc6d8685 100644 --- a/spring-core/src/main/java/org/springframework/util/SocketUtils.java +++ b/spring-core/src/main/java/org/springframework/util/SocketUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -32,13 +32,25 @@ *

Within this class, a TCP port refers to a port for a {@link ServerSocket}; * whereas, a UDP port refers to a port for a {@link DatagramSocket}. * + *

{@code SocketUtils} was introduced in Spring Framework 4.0, primarily to + * assist in writing integration tests which start an external server on an + * available random port. However, these utilities make no guarantee about the + * subsequent availability of a given port and are therefore unreliable. Instead + * of using {@code SocketUtils} to find an available local port for a server, it + * is recommended that you rely on a server's ability to start on a random port + * that it selects or is assigned by the operating system. To interact with that + * server, you should query the server for the port it is currently using. + * * @author Sam Brannen * @author Ben Hale * @author Arjen Poutsma * @author Gunnar Hillert * @author Gary Russell * @since 4.0 + * @deprecated as of Spring Framework 5.3.16, to be removed in 6.0; see + * {@link SocketUtils class-level Javadoc} for details. */ +@Deprecated public class SocketUtils { /** diff --git a/spring-core/src/test/java/org/springframework/util/SocketUtilsTests.java b/spring-core/src/test/java/org/springframework/util/SocketUtilsTests.java index d13e78e6c61b..c0f8748195be 100644 --- a/spring-core/src/test/java/org/springframework/util/SocketUtilsTests.java +++ b/spring-core/src/test/java/org/springframework/util/SocketUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -28,8 +28,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.springframework.util.SocketUtils.PORT_RANGE_MAX; -import static org.springframework.util.SocketUtils.PORT_RANGE_MIN; /** * Unit tests for {@link SocketUtils}. @@ -37,6 +35,7 @@ * @author Sam Brannen * @author Gary Russell */ +@SuppressWarnings("deprecation") class SocketUtilsTests { @Test @@ -44,7 +43,7 @@ void canBeInstantiated() { // Just making sure somebody doesn't try to make SocketUtils abstract, // since that would be a breaking change due to the intentional public // constructor. - new SocketUtils(); + new org.springframework.util.SocketUtils(); } // TCP @@ -52,36 +51,37 @@ void canBeInstantiated() { @Test void findAvailableTcpPortWithZeroMinPort() { assertThatIllegalArgumentException().isThrownBy(() -> - SocketUtils.findAvailableTcpPort(0)); + org.springframework.util.SocketUtils.findAvailableTcpPort(0)); } @Test void findAvailableTcpPortWithNegativeMinPort() { assertThatIllegalArgumentException().isThrownBy(() -> - SocketUtils.findAvailableTcpPort(-500)); + org.springframework.util.SocketUtils.findAvailableTcpPort(-500)); } @Test void findAvailableTcpPort() { - int port = SocketUtils.findAvailableTcpPort(); - assertPortInRange(port, PORT_RANGE_MIN, PORT_RANGE_MAX); + int port = org.springframework.util.SocketUtils.findAvailableTcpPort(); + assertPortInRange(port, org.springframework.util.SocketUtils.PORT_RANGE_MIN, + org.springframework.util.SocketUtils.PORT_RANGE_MAX); } @Test void findAvailableTcpPortWithMinPortEqualToMaxPort() { - int minMaxPort = SocketUtils.findAvailableTcpPort(); - int port = SocketUtils.findAvailableTcpPort(minMaxPort, minMaxPort); + int minMaxPort = org.springframework.util.SocketUtils.findAvailableTcpPort(); + int port = org.springframework.util.SocketUtils.findAvailableTcpPort(minMaxPort, minMaxPort); assertThat(port).isEqualTo(minMaxPort); } @Test void findAvailableTcpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception { - int port = SocketUtils.findAvailableTcpPort(); + int port = org.springframework.util.SocketUtils.findAvailableTcpPort(); try (ServerSocket socket = ServerSocketFactory.getDefault().createServerSocket(port, 1, InetAddress.getByName("localhost"))) { assertThat(socket).isNotNull(); // will only look for the exact port assertThatIllegalStateException().isThrownBy(() -> - SocketUtils.findAvailableTcpPort(port, port)) + org.springframework.util.SocketUtils.findAvailableTcpPort(port, port)) .withMessageStartingWith("Could not find an available TCP port") .withMessageEndingWith("after 1 attempts"); } @@ -89,15 +89,15 @@ void findAvailableTcpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exce @Test void findAvailableTcpPortWithMin() { - int port = SocketUtils.findAvailableTcpPort(50000); - assertPortInRange(port, 50000, PORT_RANGE_MAX); + int port = org.springframework.util.SocketUtils.findAvailableTcpPort(50000); + assertPortInRange(port, 50000, org.springframework.util.SocketUtils.PORT_RANGE_MAX); } @Test void findAvailableTcpPortInRange() { int minPort = 20000; int maxPort = minPort + 1000; - int port = SocketUtils.findAvailableTcpPort(minPort, maxPort); + int port = org.springframework.util.SocketUtils.findAvailableTcpPort(minPort, maxPort); assertPortInRange(port, minPort, maxPort); } @@ -133,29 +133,30 @@ void findAvailableTcpPortsWithRequestedNumberGreaterThanSizeOfRange() { @Test void findAvailableUdpPortWithZeroMinPort() { assertThatIllegalArgumentException().isThrownBy(() -> - SocketUtils.findAvailableUdpPort(0)); + org.springframework.util.SocketUtils.findAvailableUdpPort(0)); } @Test void findAvailableUdpPortWithNegativeMinPort() { assertThatIllegalArgumentException().isThrownBy(() -> - SocketUtils.findAvailableUdpPort(-500)); + org.springframework.util.SocketUtils.findAvailableUdpPort(-500)); } @Test void findAvailableUdpPort() { - int port = SocketUtils.findAvailableUdpPort(); - assertPortInRange(port, PORT_RANGE_MIN, PORT_RANGE_MAX); + int port = org.springframework.util.SocketUtils.findAvailableUdpPort(); + assertPortInRange(port, org.springframework.util.SocketUtils.PORT_RANGE_MIN, + org.springframework.util.SocketUtils.PORT_RANGE_MAX); } @Test void findAvailableUdpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exception { - int port = SocketUtils.findAvailableUdpPort(); + int port = org.springframework.util.SocketUtils.findAvailableUdpPort(); try (DatagramSocket socket = new DatagramSocket(port, InetAddress.getByName("localhost"))) { assertThat(socket).isNotNull(); // will only look for the exact port assertThatIllegalStateException().isThrownBy(() -> - SocketUtils.findAvailableUdpPort(port, port)) + org.springframework.util.SocketUtils.findAvailableUdpPort(port, port)) .withMessageStartingWith("Could not find an available UDP port") .withMessageEndingWith("after 1 attempts"); } @@ -163,15 +164,15 @@ void findAvailableUdpPortWhenPortOnLoopbackInterfaceIsNotAvailable() throws Exce @Test void findAvailableUdpPortWithMin() { - int port = SocketUtils.findAvailableUdpPort(50000); - assertPortInRange(port, 50000, PORT_RANGE_MAX); + int port = org.springframework.util.SocketUtils.findAvailableUdpPort(50000); + assertPortInRange(port, 50000, org.springframework.util.SocketUtils.PORT_RANGE_MAX); } @Test void findAvailableUdpPortInRange() { int minPort = 20000; int maxPort = minPort + 1000; - int port = SocketUtils.findAvailableUdpPort(minPort, maxPort); + int port = org.springframework.util.SocketUtils.findAvailableUdpPort(minPort, maxPort); assertPortInRange(port, minPort, maxPort); } @@ -205,22 +206,24 @@ void findAvailableUdpPortsWithRequestedNumberGreaterThanSizeOfRange() { // Helpers private void findAvailableTcpPorts(int numRequested) { - SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested); - assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); + SortedSet ports = org.springframework.util.SocketUtils.findAvailableTcpPorts(numRequested); + assertAvailablePorts(ports, numRequested, org.springframework.util.SocketUtils.PORT_RANGE_MIN, + org.springframework.util.SocketUtils.PORT_RANGE_MAX); } private void findAvailableTcpPorts(int numRequested, int minPort, int maxPort) { - SortedSet ports = SocketUtils.findAvailableTcpPorts(numRequested, minPort, maxPort); + SortedSet ports = org.springframework.util.SocketUtils.findAvailableTcpPorts(numRequested, minPort, maxPort); assertAvailablePorts(ports, numRequested, minPort, maxPort); } private void findAvailableUdpPorts(int numRequested) { - SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested); - assertAvailablePorts(ports, numRequested, PORT_RANGE_MIN, PORT_RANGE_MAX); + SortedSet ports = org.springframework.util.SocketUtils.findAvailableUdpPorts(numRequested); + assertAvailablePorts(ports, numRequested, org.springframework.util.SocketUtils.PORT_RANGE_MIN, + org.springframework.util.SocketUtils.PORT_RANGE_MAX); } private void findAvailableUdpPorts(int numRequested, int minPort, int maxPort) { - SortedSet ports = SocketUtils.findAvailableUdpPorts(numRequested, minPort, maxPort); + SortedSet ports = org.springframework.util.SocketUtils.findAvailableUdpPorts(numRequested, minPort, maxPort); assertAvailablePorts(ports, numRequested, minPort, maxPort); } private void assertPortInRange(int port, int minPort, int maxPort) { diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/ReactorNettyTcpStompClientTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/ReactorNettyTcpStompClientTests.java index 90985f35d79b..502969e4d5de 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/ReactorNettyTcpStompClientTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/ReactorNettyTcpStompClientTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -36,7 +36,6 @@ import org.springframework.messaging.simp.stomp.StompSession.Subscription; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.util.Assert; -import org.springframework.util.SocketUtils; import org.springframework.util.concurrent.ListenableFuture; import static org.assertj.core.api.Assertions.assertThat; @@ -61,7 +60,8 @@ public class ReactorNettyTcpStompClientTests { public void setup(TestInfo testInfo) throws Exception { logger.debug("Setting up before '" + testInfo.getTestMethod().get().getName() + "'"); - int port = SocketUtils.findAvailableTcpPort(61613); + @SuppressWarnings("deprecation") + int port = org.springframework.util.SocketUtils.findAvailableTcpPort(61613); this.activeMQBroker = new BrokerService(); this.activeMQBroker.addConnector("stomp://127.0.0.1:" + port); diff --git a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandlerIntegrationTests.java b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandlerIntegrationTests.java index c3c0d0293466..835cb47f769d 100644 --- a/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandlerIntegrationTests.java +++ b/spring-messaging/src/test/java/org/springframework/messaging/simp/stomp/StompBrokerRelayMessageHandlerIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -46,7 +46,6 @@ import org.springframework.messaging.support.ExecutorSubscribableChannel; import org.springframework.messaging.support.MessageBuilder; import org.springframework.util.Assert; -import org.springframework.util.SocketUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -75,10 +74,11 @@ public class StompBrokerRelayMessageHandlerIntegrationTests { @BeforeEach + @SuppressWarnings("deprecation") public void setup(TestInfo testInfo) throws Exception { logger.debug("Setting up before '" + testInfo.getTestMethod().get().getName() + "'"); - this.port = SocketUtils.findAvailableTcpPort(61613); + this.port = org.springframework.util.SocketUtils.findAvailableTcpPort(61613); this.responseChannel = new ExecutorSubscribableChannel(); this.responseHandler = new TestMessageHandler(); this.responseChannel.subscribe(this.responseHandler); diff --git a/spring-web/src/test/java/org/springframework/remoting/caucho/CauchoRemotingTests.java b/spring-web/src/test/java/org/springframework/remoting/caucho/CauchoRemotingTests.java index 58d1846bcf4a..e76b992d2c33 100644 --- a/spring-web/src/test/java/org/springframework/remoting/caucho/CauchoRemotingTests.java +++ b/spring-web/src/test/java/org/springframework/remoting/caucho/CauchoRemotingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -27,7 +27,6 @@ import org.springframework.beans.testfixture.beans.ITestBean; import org.springframework.beans.testfixture.beans.TestBean; import org.springframework.remoting.RemoteAccessException; -import org.springframework.util.SocketUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; @@ -109,7 +108,7 @@ public void hessianProxyFactoryBeanWithCustomProxyFactory() throws Exception { @Test @SuppressWarnings("deprecation") public void simpleHessianServiceExporter() throws IOException { - final int port = SocketUtils.findAvailableTcpPort(); + final int port = org.springframework.util.SocketUtils.findAvailableTcpPort(); TestBean tb = new TestBean("tb"); SimpleHessianServiceExporter exporter = new SimpleHessianServiceExporter(); diff --git a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java index e7fa002ff51b..4410e2102266 100644 --- a/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java +++ b/spring-webflux/src/test/java/org/springframework/web/reactive/function/client/WebClientIntegrationTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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. @@ -69,7 +69,6 @@ import org.springframework.http.client.reactive.HttpComponentsClientHttpConnector; import org.springframework.http.client.reactive.JettyClientHttpConnector; import org.springframework.http.client.reactive.ReactorClientHttpConnector; -import org.springframework.util.SocketUtils; import org.springframework.web.reactive.function.BodyExtractors; import org.springframework.web.reactive.function.client.WebClient.ResponseSpec; import org.springframework.web.testfixture.xml.Pojo; @@ -1245,7 +1244,8 @@ void malformedResponseChunksOnEntityWithBody(ClientHttpConnector connector) { private Mono doMalformedChunkedResponseTest( ClientHttpConnector connector, Function> handler) { - int port = SocketUtils.findAvailableTcpPort(); + @SuppressWarnings("deprecation") + int port = org.springframework.util.SocketUtils.findAvailableTcpPort(); Thread serverThread = new Thread(() -> { // No way to simulate a malformed chunked response through MockWebServer.