0

I have a Spring Integration + spring batch requirement where i have to establish a TCP client connection with remote server and send the request consisting of thousands of records processed from spring batch. I'm using MessageBuilder for the payload and message channel to send the data. We send all the records and then send the request for response message payload to start receiving the response from server. Server respond back with response data which is processed using the transformer and added to queuechannel to read later.

@Configuration
@EnableIntegration
public class GatewayConfig {

    private static final Logger logger = LoggerFactory.getLogger(GatewayConfig.class);
    @Autowired
    private GatewayProperties properties;
    
    /**Abstract class for client connection factories.
     * 
     * @return AbstractClientConnectionFactory
     * @throws Exception 
     */
    
    @Bean
    public AbstractClientConnectionFactory clientCF() {
        AbstractClientConnectionFactory factory = new TcpNetClientConnectionFactory( "138.25.189.110",5030);
        factory.setSoKeepAlive(true);
        factory.setDeserializer(new ByteArraySingleTerminatorSerializer((byte) 13));
        return factory;
    }
    
    
    
    /**
     * Receives messages over TCP.
     * Specify the MessageChannel to which produced Messages should be sent.
     * @param connectionFactory
     * @return TcpReceivingChannelAdapter
     */
    @Bean
    public TcpReceivingChannelAdapter inboundAdapterClient(@Qualifier("clientCF")AbstractClientConnectionFactory connectionFactory) {
        TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
    //  adapter.setOutputChannelName(GatewayConstants.AGGREGATOR_PRE_INPUT_CHANNEL);
        adapter.setOutputChannelName(GatewayConstants.PRETRANSFORM_CHANNEL);
        adapter.setErrorChannelName(GatewayConstants.TCP_ERROR);
        adapter.setClientMode(true);
        adapter.setConnectionFactory(connectionFactory);
        return adapter;
    }

    
    @Bean(GatewayConstants.RECEIVE_CHANNEL_NAME)
    public QueueChannel receivingChannel() {
        
        return new QueueChannel();
    }
    
    @Bean
    @Transformer(inputChannel = GatewayConstants.PRETRANSFORM_CHANNEL, outputChannel = GatewayConstants.RECEIVE_CHANNEL_NAME)
    public Pretransform pretransformMet() {
        return new Pretransform();
    }
    
    
    /**
     * Sends messages over TCP
     * @param connectionFactory
     * @return
     */
    @Bean
    @ServiceActivator(inputChannel = GatewayConstants.SEND_TO_VENDOR_CHANNEL_NAME)
    public TcpSendingMessageHandler messageHandlerClient(@Qualifier("clientCF")AbstractClientConnectionFactory connectionFactory) {
        TcpSendingMessageHandler sendingHandler = new TcpSendingMessageHandler();
        sendingHandler.setConnectionFactory(connectionFactory);
        sendingHandler.setClientMode(true);
        
        return sendingHandler;
    }
    
    /**
     * 
     * @return
     */
    @Bean(GatewayConstants.TCP_ERROR)
    public MessageChannel tcpErrrorChannel() {
        return new DirectChannel();
    }
    
    @Bean(GatewayConstants.PRETRANSFORM_CHANNEL)
    public MessageChannel preReceiveChannel() {
        return new DirectChannel();
    }
    
    @Bean(GatewayConstants.BATCH_SEND_CHANNEL_NAME)
    public MessageChannel sendchannel() {
        return new DirectChannel();
    }
    
    /**
     * 
     * @return
     */
    @Bean(GatewayConstants.SEND_TO_VENDOR_CHANNEL_NAME)
    public MessageChannel sendToVendorChannel() {
        return new DirectChannel();
    }

The batch job runs midnight everyday. After the application started/deployed the request is sent and response received successfully but the next day the server is not receiving any data. There are no tcp connection exceptions when sending the request but server is not receiving any data on it's end.

I even set singleuse to true but getting run time excpetion that client cannot set sing use to true. Is there a way i can log whenever the connection establish and status of tcp connection before sending the request and after receiving the response? Appreciate your help and thank you in advance.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
Pradyp
  • 33
  • 1
  • 3

1 Answers1

0

You can add an ApplicationListener bean (or @EventListener method) to receive all kinds of TcpConnectionEvents (open, close etc).

See the documentation.

EDIT

Simply add this to one of your beans...

@EventListener
public void connectionEvent(TcpConnectionEvent event) {
    ...
}
Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • Do we have any EventListener implemenation examples for TCP client connection events. – Pradyp Sep 15 '20 at 15:08
  • Thank you Gary. I see thespring integration debug logs that TCP socket connection open and close for every 1 min. I did not set singleuse true, but why the connection is closed and opened for every minute.`ClientCF: Added new connection: localhost:5030:52994:7af4a20b-7cc6-4989-b5ee-d9d1259c8ec3 ClientCF: Removed closed connection: localhost:5030:52987:3e541599-ad5c-4ca2-9a93-506894874dd5 Connection localhost:5030:52994:7af4a20b-7cc6-4989-b5ee-d9d1259c8ec3 established Available to read:0 Connection localhost:5030:52994:7af4a20b-7cc6-4989-b5ee-d9d1259c8ec3 established` – Pradyp Sep 15 '20 at 16:24
  • Don't put stuff like that in comments; edit the question instead and comment that you have done so. Most likely the server is closing an idle connection. A network trace (e.g. Wireshark) will confirm. – Gary Russell Sep 15 '20 at 16:32
  • Sure Gary, will make sure of it. I used the event listener and able to capture the TCP connection open and close. Can i manually reset the connection? – Pradyp Sep 30 '20 at 14:06
  • You can call `closeConnection()` on the connection factory using the connection's `connectionId` property. – Gary Russell Oct 01 '20 at 13:07
  • Thank you Gary. When required i can open the connection by using getconnection right? – Pradyp Oct 01 '20 at 18:15
  • Yes, you can, but since you have `adapter.setClientMode(true);`, the adapter will re-open the connection based on the `retryInterval`. Sending a message to the outbound adapter will also open a connection if needed. – Gary Russell Oct 01 '20 at 19:08