Reputation: 51
I am setting up a TCP client by Spring Integration, send Message with String as payload, return is not expected. Perhaps serializer/deserializer is not working correctly? Sorry I am learning Spring integration.
I can connect to an external TCP server by oepnssl:
---
# DC API Test System: microstrategy
sessions.list.
.
response
,status_code,1
,status_message,Unrecognised operation
,time,2019-02-15 07:08:08 (+1000)
.
The command I need to sent is "sessions.list\n.\n".
Now I built a tcp client trying to connect to the server:
spring-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:int="http://www.springframework.org/schema/integration"
xmlns:int-ip="http://www.springframework.org/schema/integration/ip"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip-5.1.xsd
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-5.1.xsd">
<bean id="integrationConversionService"
class="org.springframework.context.support.ConversionServiceFactoryBean">
<property name="converters">
<list>
<bean class="com.microstrategy.example.ByteArrayToStringConverter"/>
</list>
</property>
</bean>
<bean id="customeSerilizerDeserlizer" class="com.microstrategy.example.CustomSerializerDeserializer" />
<int:gateway service-interface="com.microstrategy.example.SimpleGateway"
default-request-channel="output"
default-reply-channel="reply"/>
<int:channel id="output"/>
<int:channel id="reply" datatype="java.lang.String"/>
<int-ip:tcp-connection-factory
id="clientFactory"
type="client"
host="server"
port="15099"
serializer="customeSerilizerDeserlizer"
single-use="true"
so-timeout="10000"/>
<int-ip:tcp-outbound-gateway
request-channel="output"
reply-channel="reply"
connection-factory="clientFactory"
request-timeout="10000"
reply-timeout="10000"/>
</beans>
So following this repo, the string should convert to byte[].
I am using exactly the same converter as the repo, so I just copy here to save your time:
import java.io.UnsupportedEncodingException;
import org.springframework.core.convert.converter.Converter;
public class ByteArrayToStringConverter implements Converter<byte[], String> {
private String charSet = "UTF-8";
public String convert(byte[] bytes) {
try {
return new String(bytes, this.charSet);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
System.out.println("caught excepton in converter");
return new String(bytes);
}
}
/**
* @return the charSet
*/
public String getCharSet() {
return charSet;
}
/**
* @param charSet the charSet to set
*/
public void setCharSet(String charSet) {
this.charSet = charSet;
}
}
public interface SimpleGateway {
public String send(Message message);
}
I made a custom serializer:
package com.microstrategy.example;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.springframework.integration.ip.tcp.serializer.AbstractByteArraySerializer;
public class CustomSerializerDeserializer extends AbstractByteArraySerializer {
@Override
public void serialize(byte[] bytes, OutputStream outputStream) throws IOException {
outputStream.write(bytes);
}
@Override
public byte[] deserialize(InputStream inputStream) throws IOException {
// TODO Auto-generated method stub
return null;
}
}
My main function:
Message<String> message = MessageBuilder.withPayload("sessions.list").build();
String replyMessage = simpleGateway.send(message);
Message<String> message2 = MessageBuilder.withPayload(".").build();
String replyMessage2 = simpleGateway.send(message2);
System.out.println(replyMessage2);
The replyMessage is
# DC API Test System: microstrategy
It seems I successfully connected to the server by sending message, but the message is not correctly recognized by the server. Any useful suggestions will be appreciated, thanks!
Update 1:
I add output to serializer:
public class CustomSerializerDeserializer extends AbstractByteArraySerializer {
@Override
public void serialize(byte[] bytes, OutputStream outputStream) throws IOException {
System.out.println("inside serialize");
System.out.println(System.currentTimeMillis());
String string = new String(bytes);
System.out.println("byte[] in serialize is " + string);
outputStream.write(bytes);
}
@Override
public byte[] deserialize(InputStream inputStream) throws IOException {
// TODO Auto-generated method stub
System.out.println("inside deserialize");
System.out.println(System.currentTimeMillis());
return null;
}
}
inside serialize
1550182834431
byte[] in serialize is sessions.list
.
# DC API Test System: microstrategy
2019-02-14 17:21:35.185 INFO 91620 --- [ Thread-1] o.s.i.endpoint.EventDrive
The output shows byte[] seems correct, then why server is not return as expected?
Update 2: I changed the main function (has been updated) because the framework will add "\n" at the end of each message. Is it right?
The output is
inside serialize
1550184564485
byte[] in serialize is sessions.list
inside serialize
1550184565003
byte[] in serialize is .
2019-02-14 17:49:35.013 ERROR 91740 --- [ main] o.s.i.ip.tcp.TcpOutboundGateway : Tcp Gateway exception
org.springframework.integration.MessageTimeoutException: Timed out waiting for response
No response?
Update 3: I am able to open the connection by sending an empty message. But why other message is not working?
Message<String> message = MessageBuilder.withPayload("").build();
String replyMessage = simpleGateway.send(message);
System.out.println(replyMessage);
Any helps thanks?
This is my update before I solved the issue, which is deleted by admin:
I got the response from server now, but it comes with error:
Cannot correlate response - no pending reply for server:15099:49469:0fdce5c4-432f-4ce4-b878-2e08d0e96419
inside serialize
1550189909340
byte[] in serialize is sessions.list
.
GenericMessage [payload=byte[35], headers={ip_tcp_remotePort=15099, ip_connectionId=server:15099:49550:a3bc44fa-7d36-483c-a1b8-f91eea62d839, ip_localInetAddress=/10.21.66.115, ip_address=217.78.6.17, id=3a6ff696-f12f-6328-da1a-5d613d37a4b2, ip_hostname=server, timestamp=1550189909764}]
2019-02-14 19:18:29.850 ERROR 92282 --- [pool-1-thread-1] o.s.i.ip.tcp.TcpOutboundGateway : Cannot correlate response - no pending reply for server:15099:49550:a3bc44fa-7d36-483c-a1b8-f91eea62d839
2019-02-14 19:18:29.851 ERROR 92282 --- [pool-1-thread-1] o.s.i.ip.tcp.TcpOutboundGateway : Cannot correlate response - no pending reply for server:15099:49550:a3bc44fa-7d36-483c-a1b8-f91eea62d839
2019-02-14 19:18:29.851 ERROR 92282 --- [pool-1-thread-1] o.s.i.ip.tcp.TcpOutboundGateway : Cannot correlate response - no pending reply for server:15099:49550:a3bc44fa-7d36-483c-a1b8-f91eea62d839
2019-02-14 19:18:29.851 ERROR 92282 --- [pool-1-thread-1] o.s.i.ip.tcp.TcpOutboundGateway : Cannot correlate response - no pending reply for server:15099:49550:a3bc44fa-7d36-483c-a1b8-f91eea62d839
2019-02-14 19:18:29.852 ERROR 92282 --- [pool-1-thread-1] o.s.i.ip.tcp.TcpOutboundGateway : Cannot correlate response - no pending reply for server:15099:49550:a3bc44fa-7d36-483c-a1b8-f91eea62d839
2019-02-14 19:18:29.852 ERROR 92282 --- [pool-1-thread-1] o.s.i.ip.tcp.TcpOutboundGateway
The main function is
message = new GenericMessage<String>("sessions.list\n.\n");
replyMessage = simpleGateway.send(message);
System.out.println(replyMessage);
I tried to remove the last "\n"
message = new GenericMessage<String>("sessions.list\n.");
It does not work, got time-out exception. How can I remove these "Cannot correlate response" errors?
Update 1:
I think the server responses with several lines of message:
sessions.list
.
response
,status_code,0
,status_message,OK
,time,2019-02-16 00:10:49 (+1000)
sessions
.
I need to capture all responses until ".".
Upvotes: 0
Views: 945
Reputation: 51
Finally it got solved. I will post my solution for others' reference.
My TCP client send multiple line commands which ends with ".", and expects multiple line response which also ends with "." from the external server. So I need to write custom serializer and deserializer. The default CRLF serializer/deserializer does not meet my case.
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.springframework.core.serializer.Deserializer;
import org.springframework.core.serializer.Serializer;
public class CustomSerializerDeserializer implements Serializer<String>, Deserializer<String> {
@Override
public String deserialize(InputStream inputStream) throws IOException {
// TODO Auto-generated method stub
StringBuilder builder = new StringBuilder();
int c;
while (true) {
c = inputStream.read();
builder.append((char)c);
if ((char)c == '.') {
break;
}
}
return builder.toString();
}
@Override
public void serialize(String object, OutputStream outputStream) throws IOException {
// TODO Auto-generated method stub
outputStream.write(object.getBytes());
outputStream.flush();
}
}
The xml configuration is
<int-ip:tcp-connection-factory
id="clientFactory"
type="client"
host="server"
port="15099"
ssl-context-support="sslContext"
serializer="customeSerilizerDeserlizer"
deserializer="customeSerilizerDeserlizer"
single-use="true"
so-timeout="10000"/>
Upvotes: 0
Reputation: 174494
If you are not expecting a reply you should use an outbound-channel-adapter instead of a gateway.
Upvotes: 1