INT-1150 Support java serialization over TCPNet* adapters and Simple TCP gateways.

This commit is contained in:
Gary Russell
2010-05-29 16:56:50 +00:00
parent 3b7696449b
commit 4fa1483e42
31 changed files with 435 additions and 116 deletions

View File

@@ -91,6 +91,19 @@
so-timeout="32"
/>
<ip:inbound-channel-adapter id="testInTcpNetSerialized"
channel="tcpChannel"
check-length="true"
message-format="serialized"
pool-size="27"
port="#{tcpIpUtils.findAvailableServerSocket(5450)}"
protocol="tcp"
receive-buffer-size="29"
so-keep-alive="true"
so-receive-buffer-size="30"
so-timeout="32"
/>
<ip:outbound-channel-adapter id="testOutUdp"
ack-host="somehost"
ack-port="#{tcpIpUtils.findAvailableUdpSocket(7000)}"
@@ -175,6 +188,20 @@
so-traffic-class="27"
/>
<ip:outbound-channel-adapter id="testOutTcpNetSerialized"
channel="tcpChannel"
host="localhost"
port="#{tcpIpUtils.findAvailableServerSocket(6450)}"
protocol="tcp"
so-send-buffer-size="53"
so-timeout="54"
message-format="serialized"
so-keep-alive="true"
so-linger="3"
so-tcp-no-delay="true"
so-traffic-class="27"
/>
<ip:inbound-gateway id="simpleInGateway"
request-channel="tcpChannel"
reply-channel="replyChannel"

View File

@@ -74,6 +74,10 @@ public class ParserUnitTests {
@Qualifier(value="testInTcpNet")
TcpNetReceivingChannelAdapter tcpInNet;
@Autowired
@Qualifier(value="testInTcpNetSerialized")
TcpNetReceivingChannelAdapter tcpInNetSerialized;
@Autowired
@Qualifier(value="org.springframework.integration.ip.udp.UnicastSendingMessageHandler#0")
UnicastSendingMessageHandler udpOut;
@@ -94,6 +98,10 @@ public class ParserUnitTests {
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler#0")
TcpNetSendingMessageHandler tcpOutNet;
@Autowired
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler#1")
TcpNetSendingMessageHandler tcpOutNetSerialized;
@Autowired
@Qualifier(value="simpleInGateway")
SimpleTcpNetInboundGateway simpleTcpNetInboundGateway;
@@ -177,6 +185,19 @@ public class ParserUnitTests {
assertEquals(false, dfa.getPropertyValue("close"));
}
@Test
public void testInTcpNetSerialized() {
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpInNetSerialized);
assertTrue(tcpInNetSerialized.getPort() >= 5450);
assertEquals(MessageFormats.FORMAT_JAVA_SERIALIZED, dfa.getPropertyValue("messageFormat"));
assertEquals(27, dfa.getPropertyValue("poolSize"));
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
assertEquals(29, dfa.getPropertyValue("receiveBufferSize"));
assertEquals(30, dfa.getPropertyValue("soReceiveBufferSize"));
assertEquals(32, dfa.getPropertyValue("soTimeout"));
assertEquals(false, dfa.getPropertyValue("close"));
}
@Test
public void testOutUdp() {
DirectFieldAccessor dfa = new DirectFieldAccessor(udpOut);
@@ -260,6 +281,19 @@ public class ParserUnitTests {
assertEquals(54, dfa.getPropertyValue("soTimeout"));
}
@Test
public void testOutTcpNetSerialized() {
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpOutNetSerialized);
assertTrue(tcpOutNetSerialized.getPort() >= 6450);
assertEquals(MessageFormats.FORMAT_JAVA_SERIALIZED, dfa.getPropertyValue("messageFormat"));
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
assertEquals(3, dfa.getPropertyValue("soLinger"));
assertEquals(true, dfa.getPropertyValue("soTcpNoDelay"));
assertEquals(27, dfa.getPropertyValue("soTrafficClass"));
assertEquals(53, dfa.getPropertyValue("soSendBufferSize"));
assertEquals(54, dfa.getPropertyValue("soTimeout"));
}
@Test
public void testInGateway() {
DirectFieldAccessor dfa = new DirectFieldAccessor(simpleTcpNetInboundGateway);

View File

@@ -36,7 +36,16 @@ public class CustomNetSocketWriter extends NetSocketWriter {
* @see org.springframework.integration.ip.tcp.NetSocketWriter#writeCustomFormat(byte[])
*/
@Override
protected void writeCustomFormat(byte[] bytes) throws IOException {
protected void writeCustomFormat(Object object) throws IOException {
byte[] bytes;
if (object instanceof byte[]) {
bytes = (byte[]) object;
} else if (object instanceof String) {
bytes = ((String) object).getBytes();
} else {
throw new UnsupportedOperationException("Only supports String and byte[]");
}
if (bytes.length > 24) {
socket.getOutputStream().write(bytes, 0, 24);
return;

View File

@@ -41,7 +41,16 @@ public class CustomNioSocketWriter extends NioSocketWriter {
* @see org.springframework.integration.ip.tcp.NetSocketWriter#writeCustomFormat(byte[])
*/
@Override
protected void writeCustomFormat(byte[] bytes) throws IOException {
protected void writeCustomFormat(Object object) throws IOException {
byte[] bytes;
if (object instanceof byte[]) {
bytes = (byte[]) object;
} else if (object instanceof String) {
bytes = ((String) object).getBytes();
} else {
throw new UnsupportedOperationException("Only supports String and byte[]");
}
ByteBuffer data = ByteBuffer.wrap(bytes);
if (bytes.length > 24) {
data.limit(24);

View File

@@ -47,14 +47,14 @@ public class NetSocketReaderTests {
NetSocketReader reader = new NetSocketReader(socket);
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
new String(reader.getAssembledData()));
new String((byte[]) reader.getAssembledData()));
}
else {
fail("Failed to assemble first message");
}
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
new String(reader.getAssembledData()));
new String((byte[]) reader.getAssembledData()));
}
else {
fail("Failed to assemble second message");
@@ -77,14 +77,14 @@ public class NetSocketReaderTests {
reader.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
new String(reader.getAssembledData()));
new String((byte[]) reader.getAssembledData()));
}
else {
fail("Failed to assemble first message");
}
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
new String(reader.getAssembledData()));
new String((byte[]) reader.getAssembledData()));
}
else {
fail("Failed to assemble second message");
@@ -107,14 +107,44 @@ public class NetSocketReaderTests {
reader.setMessageFormat(MessageFormats.FORMAT_CRLF);
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
new String(reader.getAssembledData()));
new String((byte[]) reader.getAssembledData()));
}
else {
fail("Failed to assemble first message");
}
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
new String(reader.getAssembledData()));
new String((byte[]) reader.getAssembledData()));
}
else {
fail("Failed to assemble second message");
}
server.close();
}
/**
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader#readFully()},
* using STX&lt;message&gt;ETX
*/
@Test
public void testReadSerialized() throws Exception {
int port = SocketUtils.findAvailableServerSocket();
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
SocketUtils.testSendSerialized(port);
Socket socket = server.accept();
socket.setSoTimeout(5000);
NetSocketReader reader = new NetSocketReader(socket);
reader.setMessageFormat(MessageFormats.FORMAT_JAVA_SERIALIZED);
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", SocketUtils.TEST_STRING,
reader.getAssembledData());
}
else {
fail("Failed to assemble first message");
}
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", SocketUtils.TEST_STRING,
reader.getAssembledData());
}
else {
fail("Failed to assemble second message");

View File

@@ -19,6 +19,7 @@ import static org.junit.Assert.*;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
@@ -131,6 +132,35 @@ public class NetSocketWriterTests {
server.close();
}
@Test
public void testWriteSerialized() throws Exception {
final int port = SocketUtils.findAvailableServerSocket();
final String testString = "abcdef";
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
Thread t = new Thread(new Runnable() {
public void run() {
try {
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
NetSocketWriter writer = new NetSocketWriter(socket);
writer.setMessageFormat(MessageFormats.FORMAT_JAVA_SERIALIZED);
writer.write(testString);
writer.write(testString);
Thread.sleep(1000000000L);
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.setDaemon(true);
t.start();
Socket socket = server.accept();
InputStream is = socket.getInputStream();
ObjectInputStream ois = new ObjectInputStream(is);
assertEquals(testString, ois.readObject());
assertEquals(testString, ois.readObject());
server.close();
}
/**
* @param is
* @param buff

View File

@@ -84,7 +84,7 @@ public class NioSocketReaderTests {
assertEquals(channel, key.channel());
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
new String(reader.getAssembledData()));
new String((byte[]) reader.getAssembledData()));
count++;
}
latch.countDown();
@@ -140,7 +140,7 @@ public class NioSocketReaderTests {
assertEquals(channel, key.channel());
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", "xx",
new String(reader.getAssembledData()));
new String((byte[]) reader.getAssembledData()));
done = true;
}
latch.countDown();
@@ -200,7 +200,7 @@ public class NioSocketReaderTests {
assertEquals(channel, key.channel());
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
new String(reader.getAssembledData()));
new String((byte[]) reader.getAssembledData()));
count++;
}
latch.countDown();
@@ -260,7 +260,7 @@ public class NioSocketReaderTests {
assertEquals(channel, key.channel());
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
new String(reader.getAssembledData()));
new String((byte[]) reader.getAssembledData()));
count++;
}
latch.countDown();

View File

@@ -27,6 +27,11 @@
request-channel="toSA"
message-format="length-header" />
<ip:inbound-gateway id="gatewaySerialized"
port="#{tcpIpUtils.findAvailableServerSocket(5450)}"
request-channel="toSA"
message-format="serialized" />
<ip:inbound-gateway id="gatewayCustom"
port="#{tcpIpUtils.findAvailableServerSocket(5500)}"
request-channel="toSA"

View File

@@ -17,6 +17,8 @@ package org.springframework.integration.ip.tcp;
import static org.junit.Assert.assertEquals;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import javax.net.SocketFactory;
@@ -50,14 +52,17 @@ public class SimpleTcpNetInboundGatewayTests {
@Qualifier(value="gatewayLength")
SimpleTcpNetInboundGateway gatewayLength;
@Autowired
@Qualifier(value="gatewaySerialized")
SimpleTcpNetInboundGateway gatewaySerialized;
@Autowired
@Qualifier(value="gatewayCustom")
SimpleTcpNetInboundGateway gatewayCustom;
@Test
public void testCrLf() throws Exception {
Thread.sleep(startup);
startup = 0;
waitListening(gatewayCrLf);
Socket socket = SocketFactory.getDefault().createSocket("localhost", gatewayCrLf.getPort());
String greetings = "Hello World!";
socket.getOutputStream().write((greetings + "\r\n").getBytes());
@@ -75,8 +80,7 @@ public class SimpleTcpNetInboundGatewayTests {
@Test
public void testStxEtx() throws Exception {
Thread.sleep(startup);
startup = 0;
waitListening(gatewayStxEtx);
Socket socket = SocketFactory.getDefault().createSocket("localhost", gatewayStxEtx.getPort());
String greetings = "Hello World!";
socket.getOutputStream().write(MessageFormats.STX);
@@ -97,10 +101,19 @@ public class SimpleTcpNetInboundGatewayTests {
assertEquals("echo:" + greetings, sb.toString());
}
@Test
public void testSerialized() throws Exception {
waitListening(gatewaySerialized);
Socket socket = SocketFactory.getDefault().createSocket("localhost", gatewaySerialized.getPort());
String greetings = "Hello World!";
new ObjectOutputStream(socket.getOutputStream()).writeObject(greetings);
String echo = (String) new ObjectInputStream(socket.getInputStream()).readObject();
assertEquals("echo:" + greetings, echo);
}
@Test
public void testLength() throws Exception {
Thread.sleep(startup);
startup = 0;
waitListening(gatewayLength);
Socket socket = SocketFactory.getDefault().createSocket("localhost", gatewayLength.getPort());
String greetings = "Hello World!";
byte[] header = new byte[4];
@@ -130,8 +143,7 @@ public class SimpleTcpNetInboundGatewayTests {
@Test
public void testCustom() throws Exception {
Thread.sleep(startup);
startup = 0;
waitListening(gatewayCustom);
Socket socket = SocketFactory.getDefault().createSocket("localhost", gatewayCustom.getPort());
String greetings = "Hello World!";
String pad = " ";
@@ -150,4 +162,16 @@ public class SimpleTcpNetInboundGatewayTests {
}
assertEquals("echo:" + greetings, sb.toString().trim());
}
private void waitListening(SimpleTcpNetInboundGateway gateway) throws Exception {
int n = 0;
while (!gateway.isListening()) {
Thread.sleep(100);
if (n++ > 100) {
throw new Exception("Gateway failed to listen");
}
}
}
}

View File

@@ -56,6 +56,10 @@ public class SimpleTcpNetOutboundGatewayTests {
@Qualifier("gatewayLength")
private SimpleTcpNetInboundGateway inboundGatewayLength;
@Autowired
@Qualifier("gatewaySerialized")
private SimpleTcpNetInboundGateway inboundGatewaySerialized;
@Autowired
@Qualifier("gatewayCustom")
private SimpleTcpNetInboundGateway inboundGatewayCustom;
@@ -101,6 +105,17 @@ public class SimpleTcpNetOutboundGatewayTests {
assertEquals("echo:test", new String(bytes));
}
@Test
public void testOutboundSerialized() throws Exception {
SimpleTcpNetOutboundGateway gateway = new SimpleTcpNetOutboundGateway
("localhost", inboundGatewaySerialized.getPort());
gateway.setMessageFormat(MessageFormats.FORMAT_JAVA_SERIALIZED);
waitListening(inboundGatewaySerialized);
Message<String> message = MessageBuilder.withPayload("test").build();
Object response = gateway.handleRequestMessage(message);
assertEquals("echo:test", response);
}
@Test
public void testOutboundLength() throws Exception {
SimpleTcpNetOutboundGateway gateway = new SimpleTcpNetOutboundGateway

View File

@@ -45,8 +45,8 @@ public class SocketMessageMapperTests {
@Test
public void testToMessage() throws Exception {
SocketMessageMapper mapper = new SocketMessageMapper();
Message<byte[]> message = mapper.toMessage(new StubSocketReader());
assertEquals(TEST_PAYLOAD, new String(message.getPayload()));
Message<Object> message = mapper.toMessage(new StubSocketReader());
assertEquals(TEST_PAYLOAD, new String((byte[]) message.getPayload()));
assertEquals(InetAddress.getLocalHost().getHostName(), message
.getHeaders().get(IpHeaders.HOSTNAME));
assertEquals(InetAddress.getLocalHost().getHostAddress(), message
@@ -64,7 +64,7 @@ public class SocketMessageMapperTests {
String s = "test";
Message<String> message = MessageBuilder.withPayload(s).build();
SocketMessageMapper mapper = new SocketMessageMapper();
byte[] bArray = mapper.fromMessage(message);
byte[] bArray = (byte[]) mapper.fromMessage(message);
assertEquals(s, new String(bArray));
}

View File

@@ -26,4 +26,9 @@ public class TestService {
public String test(byte[] bytes) {
return "echo:" + new String(bytes);
}
public String test(String s) {
return "echo:" + s;
}
}

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.integration.ip.util;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.DatagramSocket;
import java.net.InetAddress;
@@ -250,6 +251,31 @@ public class SocketUtils {
thread.start();
}
/**
* Sends two serialized objects over the same socket.
* @param port
*/
public static void testSendSerialized(final int port) {
Thread thread = new Thread(new Runnable() {
public void run() {
try {
Socket socket = new Socket(InetAddress.getByName("localhost"), port);
OutputStream outputStream = socket.getOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(outputStream);
oos.writeObject(TEST_STRING);
oos.flush();
oos.writeObject(TEST_STRING);
oos.flush();
Thread.sleep(1000000000L); // wait forever, but we're a daemon
} catch (Exception e) {
e.printStackTrace();
}
}
});
thread.setDaemon(true);
thread.start();
}
/**
* Sends a large CRLF message with no CRLF.
*/