@Test
  public void test() throws Exception {
    int port = SocketUtils.findAvailableServerSocket();
    TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(port);
    server.registerListener(
        new TcpListener() {
          public boolean onMessage(Message<?> message) {
            return false;
          }
        });
    TcpNetClientConnectionFactory client = new TcpNetClientConnectionFactory("localhost", port);
    client.registerSender(
        new TcpSender() {
          public void addNewConnection(TcpConnection connection) {}

          public void removeDeadConnection(TcpConnection connection) {}
        });
    client.registerListener(
        new TcpListener() {
          public boolean onMessage(Message<?> message) {
            return false;
          }
        });
    server.start();
    TestingUtilities.waitListening(server, null);
    client.start();
    TcpConnection connection = client.getConnection();
    Socket socket = TestUtils.getPropertyValue(connection, "socket", Socket.class);
    // should default to 0 (infinite) timeout
    assertEquals(0, socket.getSoTimeout());
    connection.close();
    server.stop();
    client.stop();
  }
 private void testCloseOnTimeoutGuts(AbstractClientConnectionFactory cf) throws Exception {
   TestingUtilities.waitListening(serverCf, null);
   cf.setSoTimeout(100);
   CachingClientConnectionFactory cccf = new CachingClientConnectionFactory(cf, 1);
   cccf.start();
   TcpConnection connection = cccf.getConnection();
   int n = 0;
   while (n++ < 100 && connection.isOpen()) {
     Thread.sleep(100);
   }
   assertFalse(connection.isOpen());
   cccf.stop();
 }
  @Test
  public void integrationTest() throws Exception {
    TestingUtilities.waitListening(serverCf, null);
    outbound.send(new GenericMessage<String>("Hello, world!"));
    Message<?> m = inbound.receive(1000);
    assertNotNull(m);
    String connectionId = m.getHeaders().get(IpHeaders.CONNECTION_ID, String.class);

    // assert we use the same connection from the pool
    outbound.send(new GenericMessage<String>("Hello, world!"));
    m = inbound.receive(1000);
    assertNotNull(m);
    assertEquals(connectionId, m.getHeaders().get(IpHeaders.CONNECTION_ID, String.class));
  }
  @Test
  public void gatewayIntegrationTest() throws Exception {
    final List<String> connectionIds = new ArrayList<String>();
    final AtomicBoolean okToRun = new AtomicBoolean(true);
    Executors.newSingleThreadExecutor()
        .execute(
            new Runnable() {
              @Override
              public void run() {
                while (okToRun.get()) {
                  Message<?> m = inbound.receive(1000);
                  if (m != null) {
                    connectionIds.add((String) m.getHeaders().get(IpHeaders.CONNECTION_ID));
                    replies.send(
                        MessageBuilder.withPayload("foo:" + new String((byte[]) m.getPayload()))
                            .copyHeaders(m.getHeaders())
                            .build());
                  }
                }
              }
            });
    TestingUtilities.waitListening(serverCf, null);
    toGateway.send(new GenericMessage<String>("Hello, world!"));
    Message<?> m = fromGateway.receive(1000);
    assertNotNull(m);
    assertEquals("foo:" + "Hello, world!", new String((byte[]) m.getPayload()));

    // wait a short time to allow the connection to be returned to the pool
    Thread.sleep(1000);

    // assert we use the same connection from the pool
    toGateway.send(new GenericMessage<String>("Hello, world2!"));
    m = fromGateway.receive(1000);
    assertNotNull(m);
    assertEquals("foo:" + "Hello, world2!", new String((byte[]) m.getPayload()));

    assertEquals(2, connectionIds.size());
    assertEquals(connectionIds.get(0), connectionIds.get(1));

    okToRun.set(false);
  }
  private void testRealGuts(
      AbstractClientConnectionFactory client1,
      AbstractClientConnectionFactory client2,
      AbstractServerConnectionFactory server1,
      AbstractServerConnectionFactory server2)
      throws Exception {
    int port1;
    int port2;
    Executor exec = Executors.newCachedThreadPool();
    client1.setTaskExecutor(exec);
    client2.setTaskExecutor(exec);
    server1.setTaskExecutor(exec);
    server2.setTaskExecutor(exec);
    ApplicationEventPublisher pub =
        new ApplicationEventPublisher() {

          @Override
          public void publishEvent(ApplicationEvent event) {}
        };
    client1.setApplicationEventPublisher(pub);
    client2.setApplicationEventPublisher(pub);
    server1.setApplicationEventPublisher(pub);
    server2.setApplicationEventPublisher(pub);
    TcpInboundGateway gateway1 = new TcpInboundGateway();
    gateway1.setConnectionFactory(server1);
    SubscribableChannel channel = new DirectChannel();
    final AtomicReference<String> connectionId = new AtomicReference<String>();
    channel.subscribe(
        new MessageHandler() {
          public void handleMessage(Message<?> message) throws MessagingException {
            connectionId.set((String) message.getHeaders().get(IpHeaders.CONNECTION_ID));
            ((MessageChannel) message.getHeaders().getReplyChannel()).send(message);
          }
        });
    gateway1.setRequestChannel(channel);
    gateway1.start();
    TcpInboundGateway gateway2 = new TcpInboundGateway();
    gateway2.setConnectionFactory(server2);
    gateway2.setRequestChannel(channel);
    gateway2.start();
    TestingUtilities.waitListening(server1, null);
    TestingUtilities.waitListening(server2, null);
    List<AbstractClientConnectionFactory> factories =
        new ArrayList<AbstractClientConnectionFactory>();
    factories.add(client1);
    factories.add(client2);
    FailoverClientConnectionFactory failFactory = new FailoverClientConnectionFactory(factories);
    boolean singleUse = client1.isSingleUse();
    failFactory.setSingleUse(singleUse);
    failFactory.afterPropertiesSet();
    TcpOutboundGateway outGateway = new TcpOutboundGateway();
    outGateway.setConnectionFactory(failFactory);
    outGateway.start();
    QueueChannel replyChannel = new QueueChannel();
    outGateway.setReplyChannel(replyChannel);
    Message<String> message = new GenericMessage<String>("foo");
    outGateway.setRemoteTimeout(120000);
    outGateway.handleMessage(message);
    Socket socket = getSocket(client1);
    port1 = socket.getLocalPort();
    assertTrue(singleUse | connectionId.get().contains(Integer.toString(port1)));
    Message<?> replyMessage = replyChannel.receive(10000);
    assertNotNull(replyMessage);
    server1.stop();
    TestingUtilities.waitUntilFactoryHasThisNumberOfConnections(client1, 0);
    outGateway.handleMessage(message);
    socket = getSocket(client2);
    port2 = socket.getLocalPort();
    assertTrue(singleUse | connectionId.get().contains(Integer.toString(port2)));
    replyMessage = replyChannel.receive(10000);
    assertNotNull(replyMessage);
    gateway2.stop();
    outGateway.stop();
  }