/*
* Copyright 2002-2016 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.ip.tcp;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.ServerSocketFactory;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.serializer.DefaultDeserializer;
import org.springframework.core.serializer.DefaultSerializer;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory;
import org.springframework.integration.ip.tcp.connection.AbstractConnectionFactory;
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactory;
import org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactoryChain;
import org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpNioClientConnectionFactory;
import org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer;
import org.springframework.integration.ip.tcp.serializer.ByteArrayLengthHeaderSerializer;
import org.springframework.integration.ip.tcp.serializer.ByteArrayStxEtxSerializer;
import org.springframework.integration.ip.util.TestingUtilities;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessagingException;
import org.springframework.messaging.PollableChannel;
import org.springframework.messaging.support.GenericMessage;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
/**
* @author Gary Russell
* @author Artem Bilan
* @since 2.0
*/
public class TcpSendingMessageHandlerTests extends AbstractTcpChannelAdapterTests {
private static final Log logger = LogFactory.getLog(TcpSendingMessageHandlerTests.class);
private void readFully(InputStream is, byte[] buff) throws IOException {
for (int i = 0; i < buff.length; i++) {
buff[i] = (byte) is.read();
}
}
@Test
public void testNetCrLf() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
int i = 0;
while (true) {
byte[] b = new byte[6];
readFully(socket.getInputStream(), b);
b = ("Reply" + (++i) + "\r\n").getBytes();
socket.getOutputStream().write(b);
}
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNetClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(10000);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply1", new String((byte[]) mOut.getPayload()));
mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply2", new String((byte[]) mOut.getPayload()));
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNetCrLfClientMode() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
int i = 0;
while (true) {
byte[] b = new byte[6];
readFully(socket.getInputStream(), b);
b = ("Reply" + (++i) + "\r\n").getBytes();
socket.getOutputStream().write(b);
}
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNetClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(Integer.MAX_VALUE);
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.setClientMode(true);
handler.setRetryInterval(10000);
handler.setBeanFactory(mock(BeanFactory.class));
handler.afterPropertiesSet();
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
taskScheduler.setPoolSize(1);
taskScheduler.initialize();
handler.setTaskScheduler(taskScheduler);
handler.start();
adapter.start();
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply1", new String((byte[]) mOut.getPayload()));
mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply2", new String((byte[]) mOut.getPayload()));
done.set(true);
handler.stop();
handler.start();
handler.stop();
adapter.stop();
serverSocket.get().close();
}
@Test
public void testNioCrLf() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
int i = 0;
while (true) {
byte[] b = new byte[6];
readFully(socket.getInputStream(), b);
b = ("Reply" + (++i) + "\r\n").getBytes();
socket.getOutputStream().write(b);
}
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNioClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(10000);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
Set<String> results = new HashSet<String>();
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
results.add(new String((byte[]) mOut.getPayload()));
mOut = channel.receive(10000);
assertNotNull(mOut);
results.add(new String((byte[]) mOut.getPayload()));
assertTrue(results.remove("Reply1"));
assertTrue(results.remove("Reply2"));
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNetStxEtx() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
int i = 0;
while (true) {
byte[] b = new byte[6];
readFully(socket.getInputStream(), b);
b = ("\u0002Reply" + (++i) + "\u0003").getBytes();
socket.getOutputStream().write(b);
}
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNetClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayStxEtxSerializer serializer = new ByteArrayStxEtxSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(10000);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply1", new String((byte[]) mOut.getPayload()));
mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply2", new String((byte[]) mOut.getPayload()));
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNioStxEtx() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
int i = 0;
while (true) {
byte[] b = new byte[6];
readFully(socket.getInputStream(), b);
b = ("\u0002Reply" + (++i) + "\u0003").getBytes();
socket.getOutputStream().write(b);
}
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNioClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayStxEtxSerializer serializer = new ByteArrayStxEtxSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(10000);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
Set<String> results = new HashSet<String>();
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
results.add(new String((byte[]) mOut.getPayload()));
mOut = channel.receive(10000);
assertNotNull(mOut);
results.add(new String((byte[]) mOut.getPayload()));
assertTrue(results.remove("Reply1"));
assertTrue(results.remove("Reply2"));
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNetLength() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
int i = 0;
while (true) {
byte[] b = new byte[8];
readFully(socket.getInputStream(), b);
if (!"\u0000\u0000\u0000\u0004Test".equals(new String(b))) {
throw new RuntimeException("Bad Data");
}
b = ("\u0000\u0000\u0000\u0006Reply" + (++i)).getBytes();
socket.getOutputStream().write(b);
}
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNetClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayLengthHeaderSerializer serializer = new ByteArrayLengthHeaderSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(10000);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply1", new String((byte[]) mOut.getPayload()));
mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply2", new String((byte[]) mOut.getPayload()));
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNioLength() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
int i = 0;
while (true) {
byte[] b = new byte[8];
readFully(socket.getInputStream(), b);
if (!"\u0000\u0000\u0000\u0004Test".equals(new String(b))) {
throw new RuntimeException("Bad Data");
}
b = ("\u0000\u0000\u0000\u0006Reply" + (++i)).getBytes();
socket.getOutputStream().write(b);
}
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNioClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayLengthHeaderSerializer serializer = new ByteArrayLengthHeaderSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(10000);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
Set<String> results = new HashSet<String>();
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
results.add(new String((byte[]) mOut.getPayload()));
mOut = channel.receive(10000);
assertNotNull(mOut);
results.add(new String((byte[]) mOut.getPayload()));
assertTrue(results.remove("Reply1"));
assertTrue(results.remove("Reply2"));
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNetSerial() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
int i = 0;
while (true) {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
ois.readObject();
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject("Reply" + (++i));
}
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNetClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ccf.setSerializer(new DefaultSerializer());
ccf.setDeserializer(new DefaultDeserializer());
ccf.setSoTimeout(10000);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply1", mOut.getPayload());
mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply2", mOut.getPayload());
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNioSerial() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
int i = 0;
while (true) {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
ois.readObject();
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject("Reply" + (++i));
}
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNioClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ccf.setSerializer(new DefaultSerializer());
ccf.setDeserializer(new DefaultDeserializer());
ccf.setSoTimeout(10000);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
Set<String> results = new HashSet<String>();
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
results.add((String) mOut.getPayload());
mOut = channel.receive(10000);
assertNotNull(mOut);
results.add((String) mOut.getPayload());
assertTrue(results.remove("Reply1"));
assertTrue(results.remove("Reply2"));
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNetSingleUseNoInbound() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final Semaphore semaphore = new Semaphore(0);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
for (int i = 0; i < 2; i++) {
Socket socket = server.accept();
semaphore.release();
byte[] b = new byte[6];
readFully(socket.getInputStream(), b);
semaphore.release();
socket.close();
}
server.close();
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNetClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(10000);
ccf.start();
ccf.setSingleUse(true);
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
assertTrue(semaphore.tryAcquire(4, 10000, TimeUnit.MILLISECONDS));
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNioSingleUseNoInbound() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final Semaphore semaphore = new Semaphore(0);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
for (int i = 0; i < 2; i++) {
Socket socket = server.accept();
semaphore.release();
byte[] b = new byte[8];
readFully(socket.getInputStream(), b);
semaphore.release();
socket.close();
}
server.close();
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNioClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(5000);
ccf.start();
ccf.setSingleUse(true);
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
handler.handleMessage(MessageBuilder.withPayload("Test.1").build());
handler.handleMessage(MessageBuilder.withPayload("Test.2").build());
assertTrue(semaphore.tryAcquire(4, 10000, TimeUnit.MILLISECONDS));
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNetSingleUseWithInbound() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final Semaphore semaphore = new Semaphore(0);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
for (int i = 1; i < 3; i++) {
Socket socket = server.accept();
semaphore.release();
byte[] b = new byte[6];
readFully(socket.getInputStream(), b);
b = ("Reply" + i + "\r\n").getBytes();
socket.getOutputStream().write(b);
socket.close();
}
server.close();
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNetClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(10000);
ccf.start();
ccf.setSingleUse(true);
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
assertTrue(semaphore.tryAcquire(2, 10000, TimeUnit.MILLISECONDS));
Set<String> replies = new HashSet<String>();
for (int i = 0; i < 2; i++) {
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
replies.add(new String((byte[]) mOut.getPayload()));
}
assertTrue(replies.remove("Reply1"));
assertTrue(replies.remove("Reply2"));
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNioSingleUseWithInbound() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final Semaphore semaphore = new Semaphore(0);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
for (int i = 1; i < 3; i++) {
Socket socket = server.accept();
semaphore.release();
byte[] b = new byte[6];
readFully(socket.getInputStream(), b);
b = ("Reply" + i + "\r\n").getBytes();
socket.getOutputStream().write(b);
socket.close();
}
server.close();
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNioClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(10000);
ccf.start();
ccf.setSingleUse(true);
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
assertTrue(semaphore.tryAcquire(2, 10000, TimeUnit.MILLISECONDS));
Set<String> replies = new HashSet<String>();
for (int i = 0; i < 2; i++) {
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
replies.add(new String((byte[]) mOut.getPayload()));
}
assertTrue(replies.remove("Reply1"));
assertTrue(replies.remove("Reply2"));
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNioSingleUseWithInboundMany() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final Semaphore semaphore = new Semaphore(0);
final AtomicBoolean done = new AtomicBoolean();
final List<Socket> serverSockets = new ArrayList<Socket>();
final ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0, 100);
serverSocket.set(server);
latch.countDown();
for (int i = 0; i < 100; i++) {
final Socket socket = server.accept();
serverSockets.add(socket);
final int j = i;
exec.execute(() -> {
semaphore.release();
byte[] b = new byte[9];
try {
readFully(socket.getInputStream(), b);
b = ("Reply" + j + "\r\n").getBytes();
socket.getOutputStream().write(b);
}
catch (IOException e1) {
e1.printStackTrace();
}
finally {
try {
socket.close();
}
catch (IOException e2) { }
}
});
}
server.close();
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNioClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ByteArrayCrLfSerializer serializer = new ByteArrayCrLfSerializer();
ccf.setSerializer(serializer);
ccf.setDeserializer(serializer);
ccf.setSoTimeout(10000);
ccf.setSingleUse(true);
ccf.setTaskExecutor(Executors.newCachedThreadPool());
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
int i = 0;
try {
for (i = 100; i < 200; i++) {
handler.handleMessage(MessageBuilder.withPayload("Test" + i).build());
}
}
catch (Exception e) {
e.printStackTrace();
fail("Exception at " + i);
}
assertTrue(semaphore.tryAcquire(100, 20000, TimeUnit.MILLISECONDS));
Set<String> replies = new HashSet<String>();
for (i = 100; i < 200; i++) {
Message<?> mOut = channel.receive(20000);
assertNotNull(mOut);
replies.add(new String((byte[]) mOut.getPayload()));
}
for (i = 0; i < 100; i++) {
assertTrue("Reply" + i + " missing", replies.remove("Reply" + i));
}
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNetNegotiate() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
int i = 0;
while (true) {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Object in = null;
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
if (i == 0) {
in = ois.readObject();
logger.debug("read object: " + in);
oos.writeObject("world!");
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
in = ois.readObject();
logger.debug("read object: " + in);
oos.writeObject("world!");
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
}
in = ois.readObject();
oos.writeObject("Reply" + (++i));
}
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNetClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ccf.setSerializer(new DefaultSerializer());
ccf.setDeserializer(new DefaultDeserializer());
ccf.setSoTimeout(10000);
TcpConnectionInterceptorFactoryChain fc = new TcpConnectionInterceptorFactoryChain();
fc.setInterceptors(new TcpConnectionInterceptorFactory[] {
newInterceptorFactory(),
newInterceptorFactory()
});
ccf.setInterceptorFactoryChain(fc);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
handler.handleMessage(MessageBuilder.withPayload("Test").build());
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply1", mOut.getPayload());
mOut = channel.receive(10000);
assertNotNull(mOut);
assertEquals("Reply2", mOut.getPayload());
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNioNegotiate() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
int i = 100;
while (true) {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Object in;
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
if (i == 100) {
in = ois.readObject();
logger.debug("read object: " + in);
oos.writeObject("world!");
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
Thread.sleep(500);
}
in = ois.readObject();
oos.writeObject("Reply" + (i++));
}
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNioClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ccf.setSerializer(new DefaultSerializer());
ccf.setDeserializer(new DefaultDeserializer());
ccf.setSoTimeout(10000);
TcpConnectionInterceptorFactoryChain fc = new TcpConnectionInterceptorFactoryChain();
fc.setInterceptors(new TcpConnectionInterceptorFactory[] {newInterceptorFactory()});
ccf.setInterceptorFactoryChain(fc);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
adapter.setConnectionFactory(ccf);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
for (int i = 0; i < 1000; i++) {
handler.handleMessage(MessageBuilder.withPayload("Test").build());
}
Set<String> results = new TreeSet<String>();
for (int i = 0; i < 1000; i++) {
Message<?> mOut = channel.receive(10000);
assertNotNull(mOut);
results.add((String) mOut.getPayload());
}
logger.debug("results: " + results);
for (int i = 100; i < 1100; i++) {
assertTrue("Missing Reply" + i, results.remove("Reply" + i));
}
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNetNegotiateSingleNoListen() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
Object in = ois.readObject();
logger.debug("read object: " + in);
oos.writeObject("world!");
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
in = ois.readObject();
logger.debug("read object: " + in);
oos.writeObject("world!");
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
in = ois.readObject();
oos.writeObject("Reply");
socket.close();
server.close();
}
catch (Exception e) {
if (!done.get()) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNetClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ccf.setSerializer(new DefaultSerializer());
ccf.setDeserializer(new DefaultDeserializer());
ccf.setSoTimeout(10000);
TcpConnectionInterceptorFactoryChain fc = new TcpConnectionInterceptorFactoryChain();
fc.setInterceptors(new TcpConnectionInterceptorFactory[] {
newInterceptorFactory(),
newInterceptorFactory()
});
ccf.setInterceptorFactoryChain(fc);
ccf.setSingleUse(true);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testNioNegotiateSingleNoListen() throws Exception {
final AtomicReference<ServerSocket> serverSocket = new AtomicReference<ServerSocket>();
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean done = new AtomicBoolean();
Executors.newSingleThreadExecutor().execute(() -> {
int i = 0;
try {
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0);
serverSocket.set(server);
latch.countDown();
Socket socket = server.accept();
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
Object in = ois.readObject();
logger.debug("read object: " + in);
oos.writeObject("world!");
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
in = ois.readObject();
logger.debug("read object: " + in);
oos.writeObject("world!");
ois = new ObjectInputStream(socket.getInputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject("Reply" + (++i));
socket.close();
server.close();
}
catch (Exception e) {
if (i == 0) {
e.printStackTrace();
}
}
});
assertTrue(latch.await(10, TimeUnit.SECONDS));
AbstractConnectionFactory ccf = new TcpNioClientConnectionFactory("localhost",
serverSocket.get().getLocalPort());
noopPublisher(ccf);
ccf.setSerializer(new DefaultSerializer());
ccf.setDeserializer(new DefaultDeserializer());
ccf.setSoTimeout(10000);
TcpConnectionInterceptorFactoryChain fc = new TcpConnectionInterceptorFactoryChain();
fc.setInterceptors(new TcpConnectionInterceptorFactory[] {
newInterceptorFactory(),
newInterceptorFactory()
});
ccf.setInterceptorFactoryChain(fc);
ccf.setSingleUse(true);
ccf.start();
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
handler.setConnectionFactory(ccf);
handler.handleMessage(MessageBuilder.withPayload("Test").build());
done.set(true);
ccf.stop();
serverSocket.get().close();
}
@Test
public void testOutboundChannelAdapterWithinChain() throws Exception {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(
"TcpOutboundChannelAdapterWithinChainTests-context.xml", this.getClass());
AbstractServerConnectionFactory scf = ctx.getBean(AbstractServerConnectionFactory.class);
TestingUtilities.waitListening(scf, null);
MessageChannel channelAdapterWithinChain = ctx.getBean("tcpOutboundChannelAdapterWithinChain", MessageChannel.class);
PollableChannel inbound = ctx.getBean("inbound", PollableChannel.class);
String testPayload = "Hello, world!";
channelAdapterWithinChain.send(new GenericMessage<String>(testPayload));
Message<?> m = inbound.receive(1000);
assertNotNull(m);
assertEquals(testPayload, new String((byte[]) m.getPayload()));
ctx.close();
}
@Test
public void testConnectionException() throws Exception {
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
AbstractConnectionFactory mockCcf = mock(AbstractClientConnectionFactory.class);
Mockito.doAnswer(invocation -> {
throw new SocketException("Failed to connect");
}).when(mockCcf).getConnection();
handler.setConnectionFactory(mockCcf);
try {
handler.handleMessage(new GenericMessage<String>("foo"));
fail("Expected exception");
}
catch (Exception e) {
assertTrue(e instanceof MessagingException);
assertTrue(e.getCause() != null);
assertTrue(e.getCause() instanceof SocketException);
assertEquals("Failed to connect", e.getCause().getMessage());
}
}
}