Search code examples
javaspringspring-integration

How to get reply from the remote source using Spring Integration?


I'm implementing a simple request-reply pattern to communicate with remote source using Spring integration. i could see it can send request to the source and also the source send back the reply through Wireshark.

But i can't get reply message in my application. Once i configured my application using outboundGateway i could see the reply message has no EOF delimiter and since default ouboundGateway uses ByteArrayCrLfSerializer it throws TimeoutEXception So i re-configured my application to use ChannelAdapter setting ByteArrayRawSerializer so that client can get reply.

@Bean
public AbstractClientConnectionFactory clientConnectionFactory() {
    TcpNioClientConnectionFactory connectionFactory = new TcpNioClientConnectionFactory(host, port);
    connectionFactory.setUsingDirectBuffers(true);
    connectionFactory.setSerializer(new ByteArrayRawSerializer());
    connectionFactory.setSerializer(new ByteArrayRawSerializer());
    connectionFactory.setApplicationEventPublisher(eventPublisher);

    return new CachingClientConnectionFactory(connectionFactory, poolSize);
}

@Bean
public MessageChannel requestChannel() {
    return new DirectChannel();
}

@Bean
@ServiceActivator(inputChannel = "requestChannel", outputChannel = "responseChannel", requiresReply = "true")
public TcpSendingMessageHandler requestHandler() {
    TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
    handler.setConnectionFactory(clientConnectionFactory());

    return handler;
}


@Bean
public MessageChannel responseChannel() {
    return new DirectChannel();
}

@Bean
public IntegrationFlow responseFlow() {
    return IntegrationFlow.from(responseChannel())
        .handle(message -> {
            log.info("Reply: {}", message.getPayload());
        })
        .get();
}

This is my setup i expected that if i specify the outputChannel on @ServiceActivator i can get the reply in that channel but i can't.

The examples out there shows the default client and server connection but since the reply come through the port that client opened and the server only reply when client request i don't think i need a server connection in this case.

Please let me know if i misunderstood or missed something. Thanks in advance🙇


Solution

  • TCP is a streaming protocol; you need some mechanism (e.g. CRLF, LF, etc) to delimit messages within the stream. The ByteArrayRawSerializer uses the socket close to determine when all the data has been received. It sounds like your server is not closing the socket.

    You need to determine which mechanism the server is using the delimit messages within the stream and select an appropriate deserializer; either one of the standard ones, or a custom one.

    https://docs.spring.io/spring-integration/docs/current/reference/html/ip.html#tcp-codecs