title: Spring Integration - Load Balance across multiple TCP outbound gateways
body: <p>I have a (legacy) TCP service that has multiple processes. Each process runs on the same host, but on a different port. The service is single threaded, so the way to increase throughput is to round-robin each request across each of the ports.</p>
  
  <p>I am providing an AMQP exposure to this legacy application. Its very simple - take a string off the AMQP queue, pass it to the application, and return the response string to the AMQP reply queue.</p>
  
  <p>This works great on a single port. However, i'd like to fan out the requests across all the ports.</p>
  
  <p>Spring Integration seems to only provide <code>AbstractClientConnectionFactory</code> implementations that either connect directly to a single host/port (<code>TcpNetClientConnectionFactory</code>) or maintain a pool of connections to a single host/port (<code>CachingClientConnectionFactory</code>). There arent any that pool connections between a single host and <em>multiple</em> ports.</p>
  
  <p>I have attempted to write my own <code>AbstractClientConnectionFactory</code> that maintains a pool of <code>AbstractClientConnectionFactory</code> objects and round-robins between them. However, I have struck several issues to do with handing the TCP connections when the target service goes away or the network is interrupted that I have not been able to solve.</p>
  
  <p>There is also the approach taken by this question: <a href="https://stackoverflow.com/questions/25264395/spring-integration-4-configuring-a-loadbalancingstrategy-in-java-dsl">Spring Integration 4 - configuring a LoadBalancingStrategy in Java DSL</a> but the solution to that was to hardcode the number of endpoints. In my case, the number of endpoints is only known at runtime and is a user-configurable setting.</p>
  
  <p>So, basically I need to create a <code>TcpOutboundGateway</code> per port <em>dynamically</em> at runtime and somehow register it in my <code>IntegrationFlow</code>. I have attempted the following:</p>
  
  <pre><code>@Bean
  public IntegrationFlow xmlQueryWorkerIntegrationFlow() {
      SimpleMessageListenerContainer inboundQueue = getMessageListenerContainer();
  
      DirectChannel rabbitReplyChannel = MessageChannels.direct().get();
  
      IntegrationFlowBuilder builder = IntegrationFlows
              .from(Amqp.inboundGateway(inboundQueue)
                        .replyChannel(rabbitReplyChannel))    
              /* SOMEHOW DO THE ROUND ROBIN HERE */
              //I have tried:
              .channel(handlerChannel()) //doesnt work, the gateways dont get started and the message doesnt get sent to the gateway
              //and I have also tried:
              .handle(gateway1)
              .handle(gateway2) //doesnt work, it chains the handlers instead of round-robining between them
              //
              .transform(new ObjectToStringTransformer())
              .channel(rabbitReplyChannel); 
  
      return builder.get();
  
  }
  
  @Bean
  //my attempt at dynamically adding handlers to the same channel and load balancing between them
  public DirectChannel handlerChannel() {
      DirectChannel channel = MessageChannels.direct().loadBalancer(new RoundRobinLoadBalancingStrategy()).get();
      for (AbstractClientConnectionFactory factory : generateConnections()) {
          channel.subscribe(generateTcpOutboundGateway(factory));
      }
      return channel;
  }
  </code></pre>
  
  <p>Does anyone know how I can solve this problem?</p>