diff --git a/basic/tcp-client-server/src/main/java/org/springframework/integration/samples/tcpclientserver/TelnetServer.java b/basic/tcp-client-server/src/main/java/org/springframework/integration/samples/tcpclientserver/TelnetServer.java index 4d471ad0..3b7490a1 100644 --- a/basic/tcp-client-server/src/main/java/org/springframework/integration/samples/tcpclientserver/TelnetServer.java +++ b/basic/tcp-client-server/src/main/java/org/springframework/integration/samples/tcpclientserver/TelnetServer.java @@ -15,7 +15,12 @@ */ package org.springframework.integration.samples.tcpclientserver; +import java.util.HashMap; +import java.util.Map; + +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; +import org.springframework.core.env.MapPropertySource; /** * The configured inbound gateway uses CRLF delimited messages which means @@ -23,15 +28,31 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; * telnet localhost 11111 - each time you hit enter you should see your input * echoed back, preceded by 'echo:'. * + * Alternatively, you can also customize the port by providing an additional system + * property at startup e.g. -DavailableServerSocket=7777 + * * @author Gary Russell + * @author Gunnar Hillert * */ public class TelnetServer { public static void main(String[] args) throws Exception { - new ClassPathXmlApplicationContext("/META-INF/spring/integration/tcpClientServerDemo-context.xml"); + + ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"/META-INF/spring/integration/tcpClientServerDemo-context.xml"}, false); + + final Map sockets = new HashMap(); + sockets.put("availableServerSocket", 11111); + + final MapPropertySource propertySource = new MapPropertySource("sockets", sockets); + + context.getEnvironment().getPropertySources().addLast(propertySource); + context.refresh(); + + System.out.println("Use telnet and connect to port: " + context.getEnvironment().getProperty("availableServerSocket")); System.out.println("Press Enter/Return in the console to exit"); System.in.read(); + System.out.println("exiting application...bye.\n\n"); System.exit(0); } diff --git a/basic/tcp-client-server/src/main/java/org/springframework/integration/samples/tcpclientserver/support/SocketUtils.java b/basic/tcp-client-server/src/main/java/org/springframework/integration/samples/tcpclientserver/support/SocketUtils.java new file mode 100644 index 00000000..cf0bec8b --- /dev/null +++ b/basic/tcp-client-server/src/main/java/org/springframework/integration/samples/tcpclientserver/support/SocketUtils.java @@ -0,0 +1,44 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.samples.tcpclientserver.support; + +import java.net.ServerSocket; + +import javax.net.ServerSocketFactory; + +/** + * + * @author Gunnar Hillert + * + */ +public final class SocketUtils { + + public static int findAvailableServerSocket(int seed) { + for (int i = seed; i < seed+200; i++) { + try { + ServerSocket sock = ServerSocketFactory.getDefault().createServerSocket(i); + sock.close(); + return i; + } catch (Exception e) { } + } + throw new RuntimeException("Cannot find a free server socket"); + } + + public static int findAvailableServerSocket() { + return findAvailableServerSocket(5678); + } + +} diff --git a/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpClientServerDemo-context.xml b/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpClientServerDemo-context.xml index e4d865c9..c9c6e66d 100644 --- a/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpClientServerDemo-context.xml +++ b/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpClientServerDemo-context.xml @@ -1,68 +1,69 @@ - - - - + - + + + + - - - - + + + + + reply-timeout="10000"/> - - + - - - - + + - - - + - - - + + + + - - - - + + diff --git a/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpClientServerDemo-conversion-context.xml b/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpClientServerDemo-conversion-context.xml index fd5d0cda..b836cdff 100644 --- a/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpClientServerDemo-conversion-context.xml +++ b/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpClientServerDemo-conversion-context.xml @@ -1,39 +1,48 @@ - - + This version demonstrates the use of a conversion service and channel 'dataType' instead of explicit transformers to convert from byte array to String. - + - - - + + + + + + + + + - + - - + - - + - + port="${availableServerSocket}"/> - - + - - - - + + diff --git a/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpServerConnectionDeserialize-context.xml b/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpServerConnectionDeserialize-context.xml index 174bf73e..12188ecc 100644 --- a/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpServerConnectionDeserialize-context.xml +++ b/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpServerConnectionDeserialize-context.xml @@ -1,27 +1,32 @@ + 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" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd + http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd + http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd"> - + + + + service-interface="org.springframework.integration.samples.tcpclientserver.SimpleGateway" + default-request-channel="input"/> - + + deserializer="connectionSerializeDeserialize"/> @@ -30,27 +35,26 @@ reply-channel="clientBytes2StringChannel" connection-factory="client" request-timeout="10000" - reply-timeout="10000" - /> + reply-timeout="10000"/> - + - - - + + + port="${availableServerSocket}" + serializer="connectionSerializeDeserialize" + deserializer="connectionSerializeDeserialize"/> - + - + \ No newline at end of file diff --git a/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpServerCustomSerialize-context.xml b/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpServerCustomSerialize-context.xml index 32887a62..a01d88b9 100644 --- a/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpServerCustomSerialize-context.xml +++ b/basic/tcp-client-server/src/main/resources/META-INF/spring/integration/tcpServerCustomSerialize-context.xml @@ -1,34 +1,39 @@ + 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" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd + http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd + http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd + http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd"> + - - + + + port="${availableServerSocket}" + single-use="true" + so-linger="10000" + serializer="connectionSerializeDeserialize" + deserializer="connectionSerializeDeserialize"/> - + - + - \ No newline at end of file + diff --git a/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpClientServerDemoTest.java b/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpClientServerDemoTest.java index bdff84ea..48f6e488 100644 --- a/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpClientServerDemoTest.java +++ b/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpClientServerDemoTest.java @@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.samples.tcpclientserver.support.CustomTestContextLoader; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -32,17 +33,14 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * echo service and the echoed response comes back over tcp and is returned to * the test case for verification. * - * The alternate configuration shows how the conversion service can be used - * instead of explicit transformers to convert the byte array payloads to + * The test uses explicit transformers to convert the byte array payloads to * Strings. * * @author Gary Russell * */ // This one uses transformers -@ContextConfiguration("/META-INF/spring/integration/tcpClientServerDemo-context.xml") -// This one uses the conversion service -//@ContextConfiguration("/META-INF/spring/integration/tcpClientServerDemo-conversion-context.xml") +@ContextConfiguration(loader=CustomTestContextLoader.class, locations={"/META-INF/spring/integration/tcpClientServerDemo-context.xml"}) @RunWith(SpringJUnit4ClassRunner.class) @DirtiesContext public class TcpClientServerDemoTest { diff --git a/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpClientServerDemoWithConversionServiceTest.java b/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpClientServerDemoWithConversionServiceTest.java new file mode 100644 index 00000000..440efd0f --- /dev/null +++ b/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpClientServerDemoWithConversionServiceTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.samples.tcpclientserver; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.samples.tcpclientserver.support.CustomTestContextLoader; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + + +/** + * Demonstrates the use of a gateway as an entry point into the integration flow. + * The message generated by the gateway is sent over tcp by the outbound gateway + * to the inbound gateway. In turn the inbound gateway sends the message to an + * echo service and the echoed response comes back over tcp and is returned to + * the test case for verification. + * + * This version shows how the conversion service can be used + * instead of explicit transformers to convert the byte array payloads to + * Strings. + * + * @author Gary Russell + * + */ +@ContextConfiguration(loader=CustomTestContextLoader.class, locations={"/META-INF/spring/integration/tcpClientServerDemo-conversion-context.xml"}) +@RunWith(SpringJUnit4ClassRunner.class) +@DirtiesContext +public class TcpClientServerDemoWithConversionServiceTest { + + @Autowired + SimpleGateway gw; + + @Test + public void testHappyDay() { + String result = gw.send("Hello world!"); + System.out.println(result); + assertEquals("echo:Hello world!", result); + } + + @Test + public void testZeroLength() { + String result = gw.send(""); + System.out.println(result); + assertEquals("echo:", result); + } + + @Test + public void testFail() { + String result = gw.send("FAIL"); + System.out.println(result); + assertEquals("FAIL:Failure Demonstration", result); + } + +} diff --git a/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpServerConnectionDeserializeTest.java b/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpServerConnectionDeserializeTest.java index 335197c9..ebd6dbe0 100644 --- a/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpServerConnectionDeserializeTest.java +++ b/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpServerConnectionDeserializeTest.java @@ -24,6 +24,7 @@ import org.springframework.integration.MessageChannel; import org.springframework.integration.core.SubscribableChannel; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; import org.springframework.integration.ip.tcp.serializer.ByteArrayStxEtxSerializer; +import org.springframework.integration.samples.tcpclientserver.support.CustomTestContextLoader; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -43,7 +44,8 @@ import static org.junit.Assert.assertEquals; * @author: ceposta */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/META-INF/spring/integration/tcpServerConnectionDeserialize-context.xml"}) +@ContextConfiguration(loader=CustomTestContextLoader.class, + locations = {"/META-INF/spring/integration/tcpServerConnectionDeserialize-context.xml"}) @DirtiesContext public class TcpServerConnectionDeserializeTest { diff --git a/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpServerCustomSerializerTest.java b/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpServerCustomSerializerTest.java index 14a2396f..84f76e38 100644 --- a/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpServerCustomSerializerTest.java +++ b/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/TcpServerCustomSerializerTest.java @@ -30,10 +30,12 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; import org.springframework.integration.Message; import org.springframework.integration.MessageChannel; import org.springframework.integration.core.SubscribableChannel; import org.springframework.integration.handler.AbstractReplyProducingMessageHandler; +import org.springframework.integration.samples.tcpclientserver.support.CustomTestContextLoader; import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -47,7 +49,8 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; * @author: ceposta */ @RunWith(SpringJUnit4ClassRunner.class) -@ContextConfiguration(locations = {"/META-INF/spring/integration/tcpServerCustomSerialize-context.xml"}) +@ContextConfiguration(loader=CustomTestContextLoader.class, + locations = {"/META-INF/spring/integration/tcpServerCustomSerialize-context.xml"}) @DirtiesContext public class TcpServerCustomSerializerTest { @@ -55,6 +58,9 @@ public class TcpServerCustomSerializerTest { @Qualifier("incomingServerChannel") MessageChannel incomingServerChannel; + @Value("${availableServerSocket}") + int availableServerSocket; + @Test public void testHappyPath() { @@ -86,7 +92,7 @@ public class TcpServerCustomSerializerTest { Writer out = null; BufferedReader in = null; try { - socket = new Socket("localhost", 11111); + socket = new Socket("localhost", availableServerSocket); out = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); out.write(sourceMessage); out.flush(); diff --git a/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/support/CustomTestContextLoader.java b/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/support/CustomTestContextLoader.java new file mode 100644 index 00000000..372d257f --- /dev/null +++ b/basic/tcp-client-server/src/test/java/org/springframework/integration/samples/tcpclientserver/support/CustomTestContextLoader.java @@ -0,0 +1,55 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.integration.samples.tcpclientserver.support; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; +import org.springframework.context.support.GenericApplicationContext; +import org.springframework.core.env.MapPropertySource; +import org.springframework.test.context.MergedContextConfiguration; +import org.springframework.test.context.support.GenericXmlContextLoader; + +/** + * + * @author Gunnar Hillert + * + */ +public class CustomTestContextLoader extends GenericXmlContextLoader { + + private static final Logger LOGGER = Logger.getLogger(CustomTestContextLoader.class); + + @Override + protected void loadBeanDefinitions(GenericApplicationContext context, + MergedContextConfiguration mergedConfig) { + + int availableServerSocket = SocketUtils.findAvailableServerSocket(5678); + + final Map sockets = new HashMap(); + sockets.put("availableServerSocket", availableServerSocket); + + if (LOGGER.isInfoEnabled()) { + LOGGER.info("Available Server Socket 1: " + availableServerSocket); + } + + final MapPropertySource propertySource = new MapPropertySource("sockets", sockets); + + context.getEnvironment().getPropertySources().addLast(propertySource); + super.loadBeanDefinitions(context, mergedConfig); + } + +}