Fix One More Address already in use Issue

https://build.spring.io/browse/INT-MASTER-350

There are so much other similar `SocketUtils` usage and it doesn't look so quickly to fix them all
Let's do that on demand!
Or just live with rebuild forever to believe that it was just a bad luck...

Fix race condition when we assign the `port` for client before server actually has obtained the real port from OS
This commit is contained in:
Artem Bilan
2016-09-01 11:15:47 -04:00
committed by Gary Russell
parent 514e693f49
commit 67332ad93a
2 changed files with 34 additions and 22 deletions

View File

@@ -7,13 +7,11 @@
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="tcpIpUtils" class="org.springframework.integration.test.util.SocketUtils" />
<int-ip:tcp-connection-factory
id="scf"
type="server"
so-timeout="60000"
port="#{tcpIpUtils.findAvailableServerSocket(0)}"/>
id="scf"
type="server"
so-timeout="60000"
port="0" />
<int-ip:tcp-inbound-channel-adapter
connection-factory="scf"
@@ -29,14 +27,14 @@
<int:channel id="replies" />
<!-- Since we use OS-assigning port in the server, this definition is for example.
The real port is assigned to client in test code via reflection. -->
<int-ip:tcp-connection-factory
id="ccf"
type="client"
host="localhost"
port="#{scf.port}"
so-timeout="60000"
/>
id="ccf"
type="client"
host="localhost"
port="#{scf.port}"
so-timeout="60000" />
<bean id="caching.ccf" class="org.springframework.integration.ip.tcp.connection.CachingClientConnectionFactory">
<constructor-arg ref="ccf" />
@@ -50,6 +48,8 @@
<int:channel id="outbound" />
<!-- Since we use OS-assigning port in the server, this definition is for example.
The real port is assigned to client in test code via reflection. -->
<int-ip:tcp-connection-factory
id="gateway.ccf"
type="client"

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -89,6 +89,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
/**
* @author Gary Russell
* @author Artem Bilan
* @since 2.2
*
*/
@@ -117,7 +118,15 @@ public class CachingClientConnectionFactoryTests {
@Autowired
@Qualifier("gateway.caching.ccf")
CachingClientConnectionFactory gatewayCF;
private CachingClientConnectionFactory gatewayCF;
@Autowired
@Qualifier("gateway.ccf")
private AbstractClientConnectionFactory clientGatewayCf;
@Autowired
@Qualifier("ccf")
private AbstractClientConnectionFactory clientAdapterCf;
@Test
public void testReuse() throws Exception {
@@ -446,7 +455,9 @@ public class CachingClientConnectionFactoryTests {
@Test
public void integrationTest() throws Exception {
TestingUtilities.waitListening(serverCf, null);
outbound.send(new GenericMessage<String>("Hello, world!"));
new DirectFieldAccessor(this.clientAdapterCf).setPropertyValue("port", this.serverCf.getPort());
this.outbound.send(new GenericMessage<>("Hello, world!"));
Message<?> m = inbound.receive(10000);
assertNotNull(m);
String connectionId = m.getHeaders().get(IpHeaders.CONNECTION_ID, String.class);
@@ -480,7 +491,9 @@ public class CachingClientConnectionFactoryTests {
});
TestingUtilities.waitListening(serverCf, null);
toGateway.send(new GenericMessage<String>("Hello, world!"));
new DirectFieldAccessor(this.clientGatewayCf).setPropertyValue("port", this.serverCf.getPort());
this.toGateway.send(new GenericMessage<>("Hello, world!"));
Message<?> m = fromGateway.receive(1000);
assertNotNull(m);
assertEquals("foo:" + "Hello, world!", new String((byte[]) m.getPayload()));
@@ -507,18 +520,17 @@ public class CachingClientConnectionFactoryTests {
@Test
public void testCloseOnTimeoutNet() throws Exception {
TcpNetClientConnectionFactory cf = new TcpNetClientConnectionFactory("localhost", serverCf.getPort());
testCloseOnTimeoutGuts(cf);
TestingUtilities.waitListening(serverCf, null);
testCloseOnTimeoutGuts(new TcpNetClientConnectionFactory("localhost", serverCf.getPort()));
}
@Test
public void testCloseOnTimeoutNio() throws Exception {
TcpNioClientConnectionFactory cf = new TcpNioClientConnectionFactory("localhost", serverCf.getPort());
testCloseOnTimeoutGuts(cf);
TestingUtilities.waitListening(serverCf, null);
testCloseOnTimeoutGuts(new TcpNioClientConnectionFactory("localhost", serverCf.getPort()));
}
private void testCloseOnTimeoutGuts(AbstractClientConnectionFactory cf) throws Exception {
TestingUtilities.waitListening(serverCf, null);
cf.setSoTimeout(100);
CachingClientConnectionFactory cccf = new CachingClientConnectionFactory(cf, 1);
cccf.start();