diff --git a/docs/src/reference/docbook/ip.xml b/docs/src/reference/docbook/ip.xml
index b661c1259f..b7f357fef9 100644
--- a/docs/src/reference/docbook/ip.xml
+++ b/docs/src/reference/docbook/ip.xml
@@ -652,7 +652,7 @@
Two sequential
messages arriving on the same socket might
be processed by different threads. This means that the order in which the messages are
- sent to the channel is indeterminate; the strict ordering of the messages on the
+ sent to the channel is indeterminate; the strict ordering of the messages arriving on the
socket is not maintained.
@@ -660,6 +660,14 @@
is required, consider setting using-nio to false
and using async handoff.
+
+ Alternatively, you may choose to insert a resequencer downstream of the inbound endpoint to
+ return the messages to their proper sequence. Set apply-sequence
+ to true on the connection factory, and messages arriving on a TCP connection will
+ have sequenceNumber and correlationId headers
+ set. The resequencer uses these headers to return the messages to their proper
+ sequence.
+
IP Configuration Attributes
@@ -727,7 +735,7 @@
true, false
Whether or not connection uses NIO. Refer to the java.nio
package for more information.
- See .
+ See .
Default false.
@@ -739,6 +747,18 @@
Refer to java.nio.ByteBuffer documentation for
more information. Must be false if using-nio is false.
+
+ apply-sequence
+ Y
+ Y
+ true, false
+ When using NIO, it may be necessary to resequence messages. When this
+ attribute is set to true, correlationId and
+ sequenceNumber headers will be added to
+ received messages.
+ See .
+ Default false.
+
so-timeout
Y
diff --git a/spring-integration-ip/.springBeans b/spring-integration-ip/.springBeans
index 4d34282f88..253efca1a7 100644
--- a/spring-integration-ip/.springBeans
+++ b/spring-integration-ip/.springBeans
@@ -1,13 +1,14 @@
1
-
+
src/test/java/org/springframework/integration/ip/tcp/connection/SOLingerTests-context.xml
+ src/test/java/org/springframework/integration/ip/tcp/AutoStartTests-context.xml
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/AbstractInternetProtocolReceivingChannelAdapter.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/AbstractInternetProtocolReceivingChannelAdapter.java
index 108bdc9b04..23391ef289 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/AbstractInternetProtocolReceivingChannelAdapter.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/AbstractInternetProtocolReceivingChannelAdapter.java
@@ -35,23 +35,23 @@ import org.springframework.util.Assert;
public abstract class AbstractInternetProtocolReceivingChannelAdapter
extends MessageProducerSupport implements Runnable, CommonSocketOptions {
- protected final int port;
+ private final int port;
- protected volatile int soTimeout = 0;
+ private volatile int soTimeout = 0;
- protected volatile int soReceiveBufferSize = -1;
+ private volatile int soReceiveBufferSize = -1;
- protected volatile int receiveBufferSize = 2048;
+ private volatile int receiveBufferSize = 2048;
- protected volatile boolean active;
+ private volatile boolean active;
- protected volatile boolean listening;
+ private volatile boolean listening;
- protected volatile String localAddress;
+ private volatile String localAddress;
- protected volatile Executor taskExecutor;
+ private volatile Executor taskExecutor;
- protected volatile int poolSize = 5;
+ private volatile int poolSize = 5;
public AbstractInternetProtocolReceivingChannelAdapter(int port) {
@@ -66,30 +66,39 @@ public abstract class AbstractInternetProtocolReceivingChannelAdapter
return port;
}
- /* (non-Javadoc)
- * @see org.springframework.integration.ip.SocketOptions#setSoTimeout(int)
- */
public void setSoTimeout(int soTimeout) {
this.soTimeout = soTimeout;
}
- /* (non-Javadoc)
- * @see org.springframework.integration.ip.SocketOptions#setSoReceiveBufferSize(int)
+ /**
+ * @return the soTimeout
*/
+ public int getSoTimeout() {
+ return soTimeout;
+ }
+
public void setSoReceiveBufferSize(int soReceiveBufferSize) {
this.soReceiveBufferSize = soReceiveBufferSize;
}
- /* (non-Javadoc)
- * @see org.springframework.integration.ip.CommonSocketOptions#setSoSendBufferSize(int)
+ /**
+ * @return the soReceiveBufferSize
*/
- public void setSoSendBufferSize(int soSendBufferSize) {
+ public int getSoReceiveBufferSize() {
+ return soReceiveBufferSize;
}
public void setReceiveBufferSize(int receiveBufferSize) {
this.receiveBufferSize = receiveBufferSize;
}
+ /**
+ * @return the receiveBufferSize
+ */
+ public int getReceiveBufferSize() {
+ return receiveBufferSize;
+ }
+
@Override
protected void doStart() {
TaskScheduler taskScheduler = this.getTaskScheduler();
@@ -117,9 +126,6 @@ public abstract class AbstractInternetProtocolReceivingChannelAdapter
}
}
- /* (non-Javadoc)
- * @see org.springframework.integration.endpoint.AbstractEndpoint#doStop()
- */
@Override
protected void doStop() {
this.active = false;
@@ -129,6 +135,13 @@ public abstract class AbstractInternetProtocolReceivingChannelAdapter
return listening;
}
+ /**
+ * @param listening the listening to set
+ */
+ public void setListening(boolean listening) {
+ this.listening = listening;
+ }
+
public String getLocalAddress() {
return localAddress;
}
@@ -145,4 +158,18 @@ public abstract class AbstractInternetProtocolReceivingChannelAdapter
this.taskExecutor = taskExecutor;
}
+ /**
+ * @return the taskExecutor
+ */
+ public Executor getTaskExecutor() {
+ return taskExecutor;
+ }
+
+ /**
+ * @return the active
+ */
+ public boolean isActive() {
+ return active;
+ }
+
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/AbstractInternetProtocolSendingMessageHandler.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/AbstractInternetProtocolSendingMessageHandler.java
index 16189c5e8e..abe6438315 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/AbstractInternetProtocolSendingMessageHandler.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/AbstractInternetProtocolSendingMessageHandler.java
@@ -36,15 +36,15 @@ public abstract class AbstractInternetProtocolSendingMessageHandler extends Abst
protected final Log logger = LogFactory.getLog(getClass());
- protected final SocketAddress destinationAddress;
+ private final SocketAddress destinationAddress;
- protected final String host;
+ private final String host;
- protected final int port;
+ private final int port;
- protected volatile int soSendBufferSize = -1;
+ private volatile int soSendBufferSize = -1;
- protected volatile int soTimeout = -1;
+ private volatile int soTimeout = -1;
public AbstractInternetProtocolSendingMessageHandler(String host, int port) {
Assert.notNull(host, "host must not be null");
@@ -80,6 +80,14 @@ public abstract class AbstractInternetProtocolSendingMessageHandler extends Abst
this.soSendBufferSize = size;
}
+ /**
+ * @return the host
+ */
+ public String getHost() {
+ return host;
+ }
+
+
/**
* @return the port
*/
@@ -87,4 +95,28 @@ public abstract class AbstractInternetProtocolSendingMessageHandler extends Abst
return port;
}
+
+ /**
+ * @return the destinationAddress
+ */
+ public SocketAddress getDestinationAddress() {
+ return destinationAddress;
+ }
+
+
+ /**
+ * @return the soTimeout
+ */
+ public int getSoTimeout() {
+ return soTimeout;
+ }
+
+
+ /**
+ * @return the soSendBufferSize
+ */
+ public int getSoSendBufferSize() {
+ return soSendBufferSize;
+ }
+
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/CommonSocketOptions.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/CommonSocketOptions.java
index 1201ce3b36..bdbd844bdf 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/CommonSocketOptions.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/CommonSocketOptions.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2001-2011 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.
@@ -29,19 +29,19 @@ public interface CommonSocketOptions {
* @see Socket#setSoTimeout(int)
* @see DatagramSocket#setSoTimeout(int)
*/
- public void setSoTimeout(int soTimeout);
+ void setSoTimeout(int soTimeout);
/**
* @see Socket#setReceiveBufferSize(int)
* @see DatagramSocket#setReceiveBufferSize(int)
*/
- public void setSoReceiveBufferSize(int soReceiveBufferSize);
+ void setSoReceiveBufferSize(int soReceiveBufferSize);
/**
* @see Socket#setSendBufferSize(int)
* @see DatagramSocket#setSendBufferSize(int)
*/
- public void setSoSendBufferSize(int soSendBufferSize);
+ void setSoSendBufferSize(int soSendBufferSize);
/**
* On a multi-homed system, specifies the ip address of the network interface used to communicate.
@@ -53,6 +53,6 @@ public interface CommonSocketOptions {
*
* @param localAddress
*/
- public void setLocalAddress(String localAddress);
+ void setLocalAddress(String localAddress);
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/IpHeaders.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/IpHeaders.java
index fc191d09ce..f628ca0de8 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/IpHeaders.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/IpHeaders.java
@@ -42,6 +42,11 @@ public abstract class IpHeaders {
public static final String CONNECTION_ID = IP + "connection_id";
+ /**
+ * Use apply-sequence and sequenceNumber instead
+ * @deprecated
+ */
+ @Deprecated
public static final String CONNECTION_SEQ = IP + "connection_seq";
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/config/IpAdapterParserUtils.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/config/IpAdapterParserUtils.java
index 2ba9fc45a4..a5cee11ea0 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/config/IpAdapterParserUtils.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/config/IpAdapterParserUtils.java
@@ -107,6 +107,11 @@ public abstract class IpAdapterParserUtils {
public static final String LOOKUP_HOST = "lookup-host";
+ public static final String AUTO_STARTUP = "auto-startup";
+
+ public static final String PHASE = "phase";
+
+ public static final String APPLY_SEQUENCE = "apply-sequence";
/**
* Adds a constructor-arg to the provided bean definition builder
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/config/TcpConnectionFactoryFactoryBean.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/config/TcpConnectionFactoryFactoryBean.java
index ab2238400b..0e85635220 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/config/TcpConnectionFactoryFactoryBean.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/config/TcpConnectionFactoryFactoryBean.java
@@ -17,6 +17,7 @@ package org.springframework.integration.ip.config;
import java.util.concurrent.Executor;
+import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.serializer.Deserializer;
@@ -24,13 +25,11 @@ import org.springframework.core.serializer.Serializer;
import org.springframework.integration.ip.tcp.connection.AbstractConnectionFactory;
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactoryChain;
-import org.springframework.integration.ip.tcp.connection.TcpListener;
import org.springframework.integration.ip.tcp.connection.TcpMessageMapper;
import org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpNetServerConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpNioClientConnectionFactory;
import org.springframework.integration.ip.tcp.connection.TcpNioServerConnectionFactory;
-import org.springframework.integration.ip.tcp.connection.TcpSender;
import org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer;
/**
@@ -42,58 +41,56 @@ import org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer
*
*/
public class TcpConnectionFactoryFactoryBean extends AbstractFactoryBean
- implements SmartLifecycle {
+ implements SmartLifecycle, BeanNameAware {
- private AbstractConnectionFactory connectionFactory;
-
- private String type;
+ private volatile AbstractConnectionFactory connectionFactory;
- protected String host;
-
- protected int port;
-
- protected TcpListener listener;
+ private volatile String type;
- protected TcpSender sender;
+ private volatile String host;
- protected int soTimeout;
+ private volatile int port;
- private int soSendBufferSize;
+ private volatile int soTimeout;
- private int soReceiveBufferSize;
-
- private boolean soTcpNoDelay;
+ private volatile int soSendBufferSize;
- private int soLinger = -1; // don't set by default
+ private volatile int soReceiveBufferSize;
- private boolean soKeepAlive;
+ private volatile boolean soTcpNoDelay;
- private int soTrafficClass = -1; // don't set by default
-
- private Executor taskExecutor;
-
- protected Deserializer> deserializer = new ByteArrayCrLfSerializer();
-
- protected Serializer> serializer = new ByteArrayCrLfSerializer();
-
- protected TcpMessageMapper mapper = new TcpMessageMapper();
+ private volatile int soLinger = -1; // don't set by default
- protected boolean singleUse;
+ private volatile boolean soKeepAlive;
- protected int poolSize = 5;
+ private volatile int soTrafficClass = -1; // don't set by default
- protected volatile boolean active;
+ private volatile Executor taskExecutor;
- protected TcpConnectionInterceptorFactoryChain interceptorFactoryChain;
-
- private boolean lookupHost = true;
-
- private String localAddress;
+ private volatile Deserializer> deserializer = new ByteArrayCrLfSerializer();
+
+ private volatile Serializer> serializer = new ByteArrayCrLfSerializer();
+
+ private volatile TcpMessageMapper mapper = new TcpMessageMapper();
+
+ private volatile boolean singleUse;
+
+ private volatile int poolSize = 5;
+
+ private volatile TcpConnectionInterceptorFactoryChain interceptorFactoryChain;
+
+ private volatile boolean lookupHost = true;
+
+ private volatile String localAddress;
+
+ private volatile boolean usingNio;
+
+ private volatile boolean usingDirectBuffers;
+
+ private volatile String beanName;
+
+ private volatile boolean applySequence;
- private boolean usingNio;
-
- private boolean usingDirectBuffers;
-
@Override
public Class> getObjectType() {
return this.connectionFactory != null ? this.connectionFactory.getClass()
@@ -136,6 +133,7 @@ public class TcpConnectionFactoryFactoryBean extends AbstractFactoryBean connections = new ConcurrentHashMap();
@@ -94,4 +94,11 @@ public class TcpInboundGateway extends MessagingGatewaySupport implements TcpLis
public String getComponentType(){
return "ip:tcp-inbound-gateway";
}
+
+ /**
+ * @return the connectionFactory
+ */
+ protected AbstractServerConnectionFactory getConnectionFactory() {
+ return connectionFactory;
+ }
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpOutboundGateway.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpOutboundGateway.java
index 0f8f978856..194a0ebb63 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpOutboundGateway.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpOutboundGateway.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2001-2011 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.
@@ -22,6 +22,7 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
+import org.springframework.context.SmartLifecycle;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessageTimeoutException;
@@ -35,28 +36,34 @@ import org.springframework.integration.ip.tcp.connection.TcpListener;
import org.springframework.integration.ip.tcp.connection.TcpSender;
import org.springframework.util.Assert;
-/**
+/**
* TCP outbound gateway that uses a client connection factory. If the factory is configured
* for single-use connections, each request is sent on a new connection; if the factory does not use
* single use connections, each request is blocked until the previous response is received
- * (or times out). Asynchronous requests/responses over the same connection are not
+ * (or times out). Asynchronous requests/responses over the same connection are not
* supported - use a pair of outbound/inbound adapters for that use case.
- *
+ *
+ * {@link SmartLifecycle} methods delegate to the underlying {@link AbstractConnectionFactory}
+ *
+ *
* @author Gary Russell
* @since 2.0
*/
-public class TcpOutboundGateway extends AbstractReplyProducingMessageHandler implements TcpSender, TcpListener {
+public class TcpOutboundGateway extends AbstractReplyProducingMessageHandler implements TcpSender, TcpListener, SmartLifecycle {
+
+ private volatile AbstractConnectionFactory connectionFactory;
- protected AbstractConnectionFactory connectionFactory;
-
private Map pendingReplies = new ConcurrentHashMap();
-
+
private Semaphore semaphore = new Semaphore(1, true);
- private long replyTimeout = 10000;
-
- private long requestTimeout = 10000;
+ private volatile long replyTimeout = 10000;
+ private volatile long requestTimeout = 10000;
+
+ private volatile boolean autoStartup = true;
+
+ private volatile int phase;
/**
* @param requestTimeout the requestTimeout to set
@@ -98,7 +105,7 @@ public class TcpOutboundGateway extends AbstractReplyProducingMessageHandler imp
connection.send(requestMessage);
Message> replyMessage = reply.getReply();
if (replyMessage == null) {
- throw new MessageTimeoutException(requestMessage, "Timed out waiting for response");
+ throw new MessageTimeoutException(requestMessage, "Timed out waiting for response");
}
if (logger.isDebugEnabled()) {
logger.debug("Respose " + replyMessage);
@@ -137,12 +144,8 @@ public class TcpOutboundGateway extends AbstractReplyProducingMessageHandler imp
return false;
}
- public boolean isListening() {
- return false;
- }
-
public void setConnectionFactory(AbstractConnectionFactory connectionFactory) {
- Assert.isTrue(connectionFactory instanceof AbstractClientConnectionFactory,
+ Assert.isTrue(connectionFactory instanceof AbstractClientConnectionFactory,
this.getClass().getName() + " requires a client connection factory");
this.connectionFactory = connectionFactory;
connectionFactory.registerListener(this);
@@ -157,10 +160,59 @@ public class TcpOutboundGateway extends AbstractReplyProducingMessageHandler imp
// do nothing - no asynchronous multiplexing supported
}
+ /**
+ * Specify the Spring Integration reply channel. If this property is not
+ * set the gateway will check for a 'replyChannel' header on the request.
+ */
+ public void setReplyChannel(MessageChannel replyChannel) {
+ this.setOutputChannel(replyChannel);
+ }
+ public String getComponentType(){
+ return "ip:tcp-outbound-gateway";
+ }
+
+ public void start() {
+ this.connectionFactory.start();
+ }
+
+ public void stop() {
+ this.connectionFactory.stop();
+ }
+
+ public boolean isRunning() {
+ return this.connectionFactory.isRunning();
+ }
+
+ public int getPhase() {
+ return this.phase;
+ }
+
+ public boolean isAutoStartup() {
+ return this.autoStartup;
+ }
+
+ public void stop(Runnable callback) {
+ this.connectionFactory.stop(callback);
+ }
+
+ public void setAutoStartup(boolean autoStartup) {
+ this.autoStartup = autoStartup;
+ }
+
+ public void setPhase(int phase) {
+ this.phase = phase;
+ }
+
+ /**
+ * @return the connectionFactory
+ */
+ protected AbstractConnectionFactory getConnectionFactory() {
+ return connectionFactory;
+ }
/**
* Class used to coordinate the asynchronous reply to its request.
- *
+ *
* @author Gary Russell
* @since 2.0
*/
@@ -197,14 +249,4 @@ public class TcpOutboundGateway extends AbstractReplyProducingMessageHandler imp
}
}
- /**
- * Specify the Spring Integration reply channel. If this property is not
- * set the gateway will check for a 'replyChannel' header on the request.
- */
- public void setReplyChannel(MessageChannel replyChannel) {
- this.setOutputChannel(replyChannel);
- }
- public String getComponentType(){
- return "ip:tcp-outbound-gateway";
- }
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapter.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapter.java
index ed342ff01d..9cb093a452 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapter.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpReceivingChannelAdapter.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2002-2011 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.
@@ -15,8 +15,6 @@
*/
package org.springframework.integration.ip.tcp;
-import java.net.ServerSocket;
-
import org.springframework.integration.Message;
import org.springframework.integration.endpoint.MessageProducerSupport;
import org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory;
@@ -38,11 +36,9 @@ import org.springframework.integration.ip.tcp.connection.TcpListener;
public class TcpReceivingChannelAdapter
extends MessageProducerSupport implements TcpListener {
- protected ServerSocket serverSocket;
+ private ConnectionFactory clientConnectionFactory;
- protected ConnectionFactory clientConnectionFactory;
-
- protected ConnectionFactory serverConnectionFactory;
+ private ConnectionFactory serverConnectionFactory;
public boolean onMessage(Message> message) {
sendMessage(message);
@@ -51,12 +47,22 @@ public class TcpReceivingChannelAdapter
@Override
protected void doStart() {
- // Nothing to do; we're passive
+ if (this.serverConnectionFactory != null) {
+ this.serverConnectionFactory.start();
+ }
+ if (this.clientConnectionFactory != null) {
+ this.clientConnectionFactory.start();
+ }
}
@Override
protected void doStop() {
- // Nothing to do; we're passive
+ if (this.clientConnectionFactory != null) {
+ this.clientConnectionFactory.stop();
+ }
+ if (this.serverConnectionFactory != null) {
+ this.serverConnectionFactory.stop();
+ }
}
/**
@@ -88,4 +94,18 @@ public class TcpReceivingChannelAdapter
public String getComponentType(){
return "ip:tcp-inbound-channel-adapter";
}
+
+ /**
+ * @return the clientConnectionFactory
+ */
+ protected ConnectionFactory getClientConnectionFactory() {
+ return clientConnectionFactory;
+ }
+
+ /**
+ * @return the serverConnectionFactory
+ */
+ protected ConnectionFactory getServerConnectionFactory() {
+ return serverConnectionFactory;
+ }
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandler.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandler.java
index 59884c6c71..83dd53b3b7 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandler.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/TcpSendingMessageHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2002-2011 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.
@@ -21,6 +21,7 @@ import java.util.concurrent.ConcurrentHashMap;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.context.SmartLifecycle;
import org.springframework.integration.Message;
import org.springframework.integration.MessageDeliveryException;
import org.springframework.integration.MessageHandlingException;
@@ -35,7 +36,7 @@ import org.springframework.integration.ip.tcp.connection.TcpSender;
import org.springframework.integration.mapping.MessageMappingException;
/**
- * Tcp outbound channel adapter using a TcpConnection to
+ * Tcp outbound channel adapter using a TcpConnection to
* send data - if the connection factory is a server
* factory, the TcpListener owns the connections. If it is
* a client factory, this object owns the connection.
@@ -43,39 +44,36 @@ import org.springframework.integration.mapping.MessageMappingException;
* @since 2.0
*
*/
-public class TcpSendingMessageHandler extends AbstractMessageHandler implements TcpSender {
-
- protected Log logger = LogFactory.getLog(this.getClass());
-
- protected TcpConnection connection;
-
- protected ConnectionFactory clientConnectionFactory;
-
- protected ConnectionFactory serverConnectionFactory;
-
- protected Map connections = new ConcurrentHashMap();
-
- protected synchronized TcpConnection getConnection() {
+public class TcpSendingMessageHandler extends AbstractMessageHandler implements TcpSender, SmartLifecycle {
+
+ protected final Log logger = LogFactory.getLog(this.getClass());
+
+ private volatile ConnectionFactory clientConnectionFactory;
+
+ private volatile ConnectionFactory serverConnectionFactory;
+
+ private Map connections = new ConcurrentHashMap();
+
+ private volatile boolean autoStartup;
+
+ private volatile int phase;
+
+ protected TcpConnection getConnection() {
+ TcpConnection connection = null;
+ if (this.clientConnectionFactory == null) {
+ return null;
+ }
try {
- this.connection = clientConnectionFactory.getConnection();
+ connection = this.clientConnectionFactory.getConnection();
} catch (Exception e) {
logger.error("Error creating SocketWriter", e);
}
- return this.connection;
- }
-
- /**
- * Close the underlying socket and prepare to establish a new socket on
- * the next write.
- */
- protected void close() {
- this.connection.close();
- this.connection = null;
+ return connection;
}
/**
* Writes the message payload to the underlying socket, using the specified
- * message format.
+ * message format.
* @see org.springframework.integration.core.MessageHandler#handleMessage(org.springframework.integration.Message)
*/
public void handleMessageInternal(final Message> message) throws MessageRejectedException,
@@ -96,7 +94,7 @@ public class TcpSendingMessageHandler extends AbstractMessageHandler implements
}
return;
}
-
+
// we own the connection
try {
doWrite(message);
@@ -116,8 +114,9 @@ public class TcpSendingMessageHandler extends AbstractMessageHandler implements
* @param message The message to write.
*/
protected void doWrite(Message> message) {
+ TcpConnection connection = null;
try {
- TcpConnection connection = getConnection();
+ connection = getConnection();
if (connection == null) {
throw new MessageMappingException(message, "Failed to create connection");
}
@@ -126,11 +125,10 @@ public class TcpSendingMessageHandler extends AbstractMessageHandler implements
}
connection.send(message);
} catch (Exception e) {
- String connectionId = null;
- if (this.connection != null) {
- connectionId = this.connection.getConnectionId();
+ String connectionId = null;
+ if (connection != null) {
+ connectionId = connection.getConnectionId();
}
- this.connection = null;
if (e instanceof MessageMappingException) {
throw (MessageMappingException) e;
}
@@ -142,7 +140,7 @@ public class TcpSendingMessageHandler extends AbstractMessageHandler implements
* Sets the client or server connection factory; for this (an outbound adapter), if
* the factory is a server connection factory, the sockets are owned by a receiving
* channel adapter and this adapter is used to send replies.
- *
+ *
* @param connectionFactory the connectionFactory to set
*/
public void setConnectionFactory(AbstractConnectionFactory connectionFactory) {
@@ -157,11 +155,83 @@ public class TcpSendingMessageHandler extends AbstractMessageHandler implements
public void addNewConnection(TcpConnection connection) {
connections.put(connection.getConnectionId(), connection);
}
-
+
public void removeDeadConnection(TcpConnection connection) {
connections.remove(connection.getConnectionId());
}
+
public String getComponentType(){
return "ip:tcp-outbound-channel-adapter";
}
+
+ public void start() {
+ if (this.clientConnectionFactory != null) {
+ this.clientConnectionFactory.start();
+ }
+ if (this.serverConnectionFactory != null) {
+ this.serverConnectionFactory.start();
+ }
+ }
+
+ public void stop() {
+ if (this.clientConnectionFactory != null) {
+ this.clientConnectionFactory.stop();
+ }
+ if (this.serverConnectionFactory != null) {
+ this.serverConnectionFactory.stop();
+ }
+ }
+
+ public boolean isRunning() {
+ boolean cfRunning = this.clientConnectionFactory != null ? this.clientConnectionFactory.isRunning() : false;
+ boolean sfRunning = this.serverConnectionFactory != null ? this.serverConnectionFactory.isRunning() : false;
+ return cfRunning | sfRunning;
+ }
+
+ public int getPhase() {
+ return this.phase;
+ }
+
+ public boolean isAutoStartup() {
+ return this.autoStartup;
+ }
+
+ public void stop(Runnable callback) {
+ if (this.clientConnectionFactory != null) {
+ this.clientConnectionFactory.stop(callback);
+ }
+ if (this.serverConnectionFactory != null) {
+ this.serverConnectionFactory.stop(callback);
+ }
+ }
+
+ public void setAutoStartup(boolean autoStartup) {
+ this.autoStartup = autoStartup;
+ }
+
+ public void setPhase(int phase) {
+ this.phase = phase;
+ }
+
+ /**
+ * @return the clientConnectionFactory
+ */
+ protected ConnectionFactory getClientConnectionFactory() {
+ return clientConnectionFactory;
+ }
+
+ /**
+ * @return the serverConnectionFactory
+ */
+ protected ConnectionFactory getServerConnectionFactory() {
+ return serverConnectionFactory;
+ }
+
+ /**
+ * @return the connections
+ */
+ protected Map getConnections() {
+ return connections;
+ }
+
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java
index 6253e3706b..259d47bb36 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractClientConnectionFactory.java
@@ -19,8 +19,6 @@ package org.springframework.integration.ip.tcp.connection;
import java.net.Socket;
import java.net.SocketException;
-import org.springframework.util.Assert;
-
/**
* Abstract class for client connection factories; client connection factories
* establish outgoing connections.
@@ -30,7 +28,7 @@ import org.springframework.util.Assert;
*/
public abstract class AbstractClientConnectionFactory extends AbstractConnectionFactory {
- protected TcpConnection theConnection;
+ private TcpConnection theConnection;
/**
* Constructs a factory that will established connections to the host and port.
@@ -38,9 +36,7 @@ public abstract class AbstractClientConnectionFactory extends AbstractConnection
* @param port The port.
*/
public AbstractClientConnectionFactory(String host, int port) {
- Assert.notNull(host, "host must not be null");
- this.host = host;
- this.port = port;
+ super(host, port);
}
/**
@@ -53,11 +49,12 @@ public abstract class AbstractClientConnectionFactory extends AbstractConnection
* @param socket The new socket.
*/
protected void initializeConnection(TcpConnection connection, Socket socket) {
- if (this.listener != null) {
- connection.registerListener(this.listener);
+ TcpListener listener = this.getListener();
+ if (listener != null) {
+ connection.registerListener(listener);
}
- if (this.listener != null || this.singleUse) {
- if (this.soTimeout <= 0) {
+ if (listener != null || this.isSingleUse()) {
+ if (this.getSoTimeout() <= 0) {
try {
socket.setSoTimeout(DEFAULT_REPLY_TIMEOUT);
} catch (SocketException e) {
@@ -65,10 +62,24 @@ public abstract class AbstractClientConnectionFactory extends AbstractConnection
}
}
}
- connection.setMapper(this.mapper);
- connection.setDeserializer(this.deserializer);
- connection.setSerializer(this.serializer);
- connection.setSingleUse(this.singleUse);
+ connection.setMapper(this.getMapper());
+ connection.setDeserializer(this.getDeserializer());
+ connection.setSerializer(this.getSerializer());
+ connection.setSingleUse(this.isSingleUse());
+ }
+
+ /**
+ * @param theConnection the theConnection to set
+ */
+ protected void setTheConnection(TcpConnection theConnection) {
+ this.theConnection = theConnection;
+ }
+
+ /**
+ * @return the theConnection
+ */
+ protected TcpConnection getTheConnection() {
+ return theConnection;
}
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractConnectionFactory.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractConnectionFactory.java
index 5b5566f2b6..181e6477ac 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractConnectionFactory.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractConnectionFactory.java
@@ -36,73 +36,85 @@ import java.util.concurrent.TimeUnit;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.serializer.Deserializer;
import org.springframework.core.serializer.Serializer;
import org.springframework.integration.MessagingException;
+import org.springframework.integration.context.IntegrationObjectSupport;
import org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer;
import org.springframework.util.Assert;
/**
* Base class for all connection factories.
- *
+ *
* @author Gary Russell
* @since 2.0
*
*/
-public abstract class AbstractConnectionFactory
- implements ConnectionFactory, Runnable, SmartLifecycle {
+public abstract class AbstractConnectionFactory extends IntegrationObjectSupport
+ implements ConnectionFactory, Runnable, SmartLifecycle, BeanNameAware {
- protected Log logger = LogFactory.getLog(this.getClass());
-
- protected final static int DEFAULT_REPLY_TIMEOUT = 10000;
-
- protected String host;
-
- protected int port;
-
- protected TcpListener listener;
+ protected final Log logger = LogFactory.getLog(this.getClass());
- protected TcpSender sender;
+ protected static final int DEFAULT_REPLY_TIMEOUT = 10000;
- protected int soTimeout;
+ private volatile String host;
- private int soSendBufferSize;
+ private volatile int port;
- private int soReceiveBufferSize;
-
- private boolean soTcpNoDelay;
+ private volatile TcpListener listener;
- private int soLinger = -1; // don't set by default
+ private volatile TcpSender sender;
- private boolean soKeepAlive;
+ private volatile int soTimeout;
- private int soTrafficClass = -1; // don't set by default
-
- private Executor taskExecutor;
-
- private boolean privateExecutor;
+ private volatile int soSendBufferSize;
- protected Deserializer> deserializer = new ByteArrayCrLfSerializer();
-
- protected Serializer> serializer = new ByteArrayCrLfSerializer();
-
- protected TcpMessageMapper mapper = new TcpMessageMapper();
+ private volatile int soReceiveBufferSize;
- protected boolean singleUse;
+ private volatile boolean soTcpNoDelay;
- protected int poolSize = 5;
+ private volatile int soLinger = -1; // don't set by default
- protected volatile boolean active;
+ private volatile boolean soKeepAlive;
- protected TcpConnectionInterceptorFactoryChain interceptorFactoryChain;
-
- private boolean lookupHost = true;
-
- private List connections = new LinkedList();
+ private volatile int soTrafficClass = -1; // don't set by default
+
+ private volatile Executor taskExecutor;
+
+ private volatile boolean privateExecutor;
+
+ private volatile Deserializer> deserializer = new ByteArrayCrLfSerializer();
+
+ private volatile Serializer> serializer = new ByteArrayCrLfSerializer();
+
+ private volatile TcpMessageMapper mapper = new TcpMessageMapper();
+
+ private volatile boolean singleUse;
+
+ private volatile int poolSize = 5;
+
+ private volatile boolean active;
+
+ private volatile TcpConnectionInterceptorFactoryChain interceptorFactoryChain;
+
+ private volatile boolean lookupHost = true;
+
+ private volatile List connections = new LinkedList();
protected final Object lifecycleMonitor = new Object();
-
+
+ public AbstractConnectionFactory(int port) {
+ this.port = port;
+ }
+
+ public AbstractConnectionFactory(String host, int port) {
+ Assert.notNull(host, "host must not be null");
+ this.host = host;
+ this.port = port;
+ }
+
/**
* Sets socket attributes on the socket.
* @param socket The socket.
@@ -240,6 +252,48 @@ public abstract class AbstractConnectionFactory
return port;
}
+ /**
+ * @return the listener
+ */
+ public TcpListener getListener() {
+ return listener;
+ }
+
+ /**
+ * @return the sender
+ */
+ public TcpSender getSender() {
+ return sender;
+ }
+
+ /**
+ * @return the serializer
+ */
+ public Serializer> getSerializer() {
+ return serializer;
+ }
+
+ /**
+ * @return the deserializer
+ */
+ public Deserializer> getDeserializer() {
+ return deserializer;
+ }
+
+ /**
+ * @return the mapper
+ */
+ public TcpMessageMapper getMapper() {
+ return mapper;
+ }
+
+ /**
+ * @return the poolSize
+ */
+ public int getPoolSize() {
+ return poolSize;
+ }
+
/**
* Registers a TcpListener to receive messages after
* the payload has been converted from the input data.
@@ -252,7 +306,7 @@ public abstract class AbstractConnectionFactory
}
/**
- * Registers a TcpSender; for server sockets, used to
+ * Registers a TcpSender; for server sockets, used to
* provide connection information so a sender can be used
* to reply to incoming messages.
* @param sender The sender
@@ -271,7 +325,7 @@ public abstract class AbstractConnectionFactory
}
/**
- *
+ *
* @param deserializer the deserializer to set
*/
public void setDeserializer(Deserializer> deserializer) {
@@ -279,7 +333,7 @@ public abstract class AbstractConnectionFactory
}
/**
- *
+ *
* @param serializer the serializer to set
*/
public void setSerializer(Serializer> serializer) {
@@ -287,7 +341,7 @@ public abstract class AbstractConnectionFactory
}
/**
- *
+ *
* @param mapper the mapper to set; defaults to a {@link TcpMessageMapper}
*/
public void setMapper(TcpMessageMapper mapper) {
@@ -309,7 +363,7 @@ public abstract class AbstractConnectionFactory
this.singleUse = singleUse;
}
-
+
public void setPoolSize(int poolSize) {
this.poolSize = poolSize;
}
@@ -349,10 +403,13 @@ public abstract class AbstractConnectionFactory
this.getTaskExecutor().execute(this);
}
}
+ if (logger.isInfoEnabled()) {
+ logger.info("started " + this);
+ }
}
/**
- * Creates a taskExecutor (if one was not provided).
+ * Creates a taskExecutor (if one was not provided).
*/
protected Executor getTaskExecutor() {
synchronized (this.lifecycleMonitor) {
@@ -388,7 +445,7 @@ public abstract class AbstractConnectionFactory
try {
if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
logger.debug("Forcing executor shutdown");
- executorService.shutdownNow();
+ executorService.shutdownNow();
if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
logger.debug("Executor failed to shutdown");
}
@@ -402,6 +459,9 @@ public abstract class AbstractConnectionFactory
}
}
}
+ if (logger.isInfoEnabled()) {
+ logger.info("stopped " + this);
+ }
}
protected TcpConnection wrapConnection(TcpConnection connection) throws Exception {
@@ -409,7 +469,7 @@ public abstract class AbstractConnectionFactory
if (this.interceptorFactoryChain == null) {
return connection;
}
- TcpConnectionInterceptorFactory[] interceptorFactories =
+ TcpConnectionInterceptorFactory[] interceptorFactories =
this.interceptorFactoryChain.getInterceptorFactories();
if (interceptorFactories == null) {
return connection;
@@ -433,9 +493,9 @@ public abstract class AbstractConnectionFactory
}
/**
- *
+ *
* Times out any expired connections then, if selectionCount > 0, processes the selected keys.
- *
+ *
* @param selectionCount
* @param selector
* @param connections
@@ -483,7 +543,7 @@ public abstract class AbstractConnectionFactory
else if (key.isReadable()) {
try {
key.interestOps(key.interestOps() - key.readyOps());
- final TcpNioConnection connection;
+ final TcpNioConnection connection;
connection = (TcpNioConnection) key.attachment();
connection.setLastRead(System.currentTimeMillis());
this.taskExecutor.execute(new Runnable() {
@@ -535,13 +595,17 @@ public abstract class AbstractConnectionFactory
protected void doAccept(final Selector selector, ServerSocketChannel server, long now) throws IOException {
throw new UnsupportedOperationException("Nio server factory must override this method");
}
-
+
public int getPhase() {
return 0;
}
+ /**
+ * We are controlled by the startup options of
+ * the bound endpoint.
+ */
public boolean isAutoStartup() {
- return true;
+ return false;
}
public void stop(Runnable callback) {
@@ -558,7 +622,7 @@ public abstract class AbstractConnectionFactory
this.connections.add(connection);
}
}
-
+
protected void harvestClosedConnections() {
synchronized (this.connections) {
Iterator iterator = this.connections.iterator();
@@ -570,4 +634,29 @@ public abstract class AbstractConnectionFactory
}
}
}
+
+ public boolean isRunning() {
+ return this.active;
+ }
+
+ /**
+ * @return the active
+ */
+ protected boolean isActive() {
+ return active;
+ }
+
+ /**
+ * @param active the active to set
+ */
+ protected void setActive(boolean active) {
+ this.active = active;
+ }
+
+ protected void checkActive() throws IOException {
+ if (!this.isActive()) {
+ throw new IOException(this + " connection factory has not been started");
+ }
+ }
+
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractServerConnectionFactory.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractServerConnectionFactory.java
index cbb9724e07..8bb5e3726d 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractServerConnectionFactory.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractServerConnectionFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2001-2011 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.
@@ -29,9 +29,9 @@ import java.net.SocketException;
*/
public abstract class AbstractServerConnectionFactory extends AbstractConnectionFactory {
- protected boolean listening;
+ private boolean listening;
- protected String localAddress;
+ private String localAddress;
/**
@@ -39,7 +39,7 @@ public abstract class AbstractServerConnectionFactory extends AbstractConnection
* @param port
*/
public AbstractServerConnectionFactory(int port) {
- this.port = port;
+ super(port);
}
@@ -51,6 +51,14 @@ public abstract class AbstractServerConnectionFactory extends AbstractConnection
throw new UnsupportedOperationException("Getting a connection from a server factory is not supported");
}
+ /**
+ * @param listening the listening to set
+ */
+ protected void setListening(boolean listening) {
+ this.listening = listening;
+ }
+
+
/**
*
* @return true if the server is listening on the port.
@@ -66,20 +74,21 @@ public abstract class AbstractServerConnectionFactory extends AbstractConnection
* @param socket The new socket.
*/
protected void initializeConnection(TcpConnection connection, Socket socket) {
- if (this.listener != null) {
- connection.registerListener(this.listener);
+ TcpListener listener = this.getListener();
+ if (listener != null) {
+ connection.registerListener(listener);
}
- connection.registerSender(this.sender);
- connection.setMapper(this.mapper);
- connection.setDeserializer(this.deserializer);
- connection.setSerializer(this.serializer);
- connection.setSingleUse(this.singleUse);
+ connection.registerSender(this.getSender());
+ connection.setMapper(this.getMapper());
+ connection.setDeserializer(this.getDeserializer());
+ connection.setSerializer(this.getSerializer());
+ connection.setSingleUse(this.isSingleUse());
/*
* If we have a collaborating outbound channel adapter and we are configured
* for single use; need to enforce a timeout on the socket so we will close
* it some period after the response was sent (timeout on the next read).
*/
- if (this.singleUse && this.soTimeout <= 0 && this.listener != null) {
+ if (this.isSingleUse() && this.getSoTimeout() <= 0 && listener != null) {
try {
socket.setSoTimeout(DEFAULT_REPLY_TIMEOUT);
} catch (SocketException e) {
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractTcpConnection.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractTcpConnection.java
index 5860a2dc22..c2fc6cdee1 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractTcpConnection.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractTcpConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2001-2011 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.
@@ -19,6 +19,7 @@ package org.springframework.integration.ip.tcp.connection;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketException;
+import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import org.apache.commons.logging.Log;
@@ -33,68 +34,62 @@ import org.springframework.util.Assert;
* Base class for TcpConnections. TcpConnections are established by
* client connection factories (outgoing) or server connection factories
* (incoming).
- *
+ *
* @author Gary Russell
* @since 2.0
*
*/
public abstract class AbstractTcpConnection implements TcpConnection {
- protected Log logger = LogFactory.getLog(this.getClass());
-
+ protected final Log logger = LogFactory.getLog(this.getClass());
+
@SuppressWarnings("rawtypes")
- protected Deserializer deserializer;
-
+ private volatile Deserializer deserializer;
+
@SuppressWarnings("rawtypes")
- protected Serializer serializer;
-
- protected TcpMessageMapper mapper;
-
- protected TcpListener listener;
-
- private TcpListener actualListener;
+ private volatile Serializer serializer;
- protected TcpSender sender;
+ private volatile TcpMessageMapper mapper;
- protected boolean singleUse;
+ private volatile TcpListener listener;
- protected final boolean server;
+ private volatile TcpListener actualListener;
- protected String connectionId;
-
- private AtomicLong sequence = new AtomicLong();
-
- private int soLinger = -1;
+ private volatile TcpSender sender;
- private String hostName = "unknown";
+ private volatile boolean singleUse;
- private String hostAddress = "unknown";
-
- private int port;
-
- private final boolean lookupHost;
+ private final boolean server;
+
+ private volatile String connectionId;
+
+ private final AtomicLong sequence = new AtomicLong();
+
+ private volatile int soLinger = -1;
+
+ private volatile String hostName = "unknown";
+
+ private volatile String hostAddress = "unknown";
+
+ private volatile int port;
- private int hashCode;
-
public AbstractTcpConnection(Socket socket, boolean server, boolean lookupHost) {
this.server = server;
- this.lookupHost = lookupHost;
- this.hashCode = socket.hashCode();
InetAddress inetAddress = socket.getInetAddress();
if (inetAddress != null) {
this.hostAddress = inetAddress.getHostAddress();
- if (this.lookupHost) {
+ if (lookupHost) {
this.hostName = inetAddress.getHostName();
} else {
this.hostName = this.hostAddress;
}
}
- this.connectionId = this.hostName + ":" + this.port + ":" + this.hashCode;
+ this.connectionId = this.hostName + ":" + this.port + ":" + UUID.randomUUID().toString();
try {
this.soLinger = socket.getSoLinger();
} catch (SocketException e) { }
}
-
+
public void afterSend(Message> message) throws Exception {
if (logger.isDebugEnabled())
logger.debug("Message sent " + message);
@@ -119,7 +114,7 @@ public abstract class AbstractTcpConnection implements TcpConnection {
}
/**
- * If we have been intercepted, propagate the close from the outermost interceptor;
+ * If we have been intercepted, propagate the close from the outermost interceptor;
* otherwise, just call close().
*/
protected void closeConnection() {
@@ -147,14 +142,14 @@ public abstract class AbstractTcpConnection implements TcpConnection {
public void setMapper(TcpMessageMapper mapper) {
Assert.notNull(mapper, this.getClass().getName() + " Mapper may not be null");
this.mapper = mapper;
- if (this.serializer != null &&
+ if (this.serializer != null &&
!(this.serializer instanceof AbstractByteArraySerializer)) {
mapper.setStringToBytes(false);
}
}
/**
- *
+ *
* @return the deserializer
*/
public Deserializer> getDeserializer() {
@@ -169,7 +164,7 @@ public abstract class AbstractTcpConnection implements TcpConnection {
}
/**
- *
+ *
* @return the serializer
*/
public Serializer> getSerializer() {
@@ -177,7 +172,7 @@ public abstract class AbstractTcpConnection implements TcpConnection {
}
/**
- * @param serializer the serializer to set
+ * @param serializer the serializer to set
*/
public void setSerializer(Serializer> serializer) {
this.serializer = serializer;
@@ -202,7 +197,7 @@ public abstract class AbstractTcpConnection implements TcpConnection {
this.actualListener = outerInterceptor.getListener();
}
}
-
+
/**
* @param sender the sender to set
*/
@@ -219,9 +214,16 @@ public abstract class AbstractTcpConnection implements TcpConnection {
public TcpListener getListener() {
return this.listener;
}
-
+
/**
- * @param singleUse true if this socket is to used once and
+ * @return the sender
+ */
+ public TcpSender getSender() {
+ return sender;
+ }
+
+ /**
+ * @param singleUse true if this socket is to used once and
* discarded.
*/
public void setSingleUse(boolean singleUse) {
@@ -229,7 +231,7 @@ public abstract class AbstractTcpConnection implements TcpConnection {
}
/**
- *
+ *
* @return True if connection is used once.
*/
public boolean isSingleUse() {
@@ -240,8 +242,8 @@ public abstract class AbstractTcpConnection implements TcpConnection {
return server;
}
- public long getConnectionSeq() {
- return sequence.incrementAndGet();
+ public long incrementAndGetConnectionSequence() {
+ return this.sequence.incrementAndGet();
}
public String getHostAddress() {
@@ -255,5 +257,5 @@ public abstract class AbstractTcpConnection implements TcpConnection {
public String getConnectionId() {
return this.connectionId;
}
-
+
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractTcpConnectionInterceptor.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractTcpConnectionInterceptor.java
index b4ef4b2a3a..7a47ea3547 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractTcpConnectionInterceptor.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/AbstractTcpConnectionInterceptor.java
@@ -157,8 +157,8 @@ public abstract class AbstractTcpConnectionInterceptor implements TcpConnectionI
}
}
- public long getConnectionSeq() {
- return this.theConnection.getConnectionSeq();
+ public long incrementAndGetConnectionSequence() {
+ return this.theConnection.incrementAndGetConnectionSequence();
}
TcpSender getSender() {
@@ -176,5 +176,5 @@ public abstract class AbstractTcpConnectionInterceptor implements TcpConnectionI
this.realSender = sender != null;
return this.realSender;
}
-
+
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/ConnectionFactory.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/ConnectionFactory.java
index ea5fa3a148..8b30feeb41 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/ConnectionFactory.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/ConnectionFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2001-2011 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.
@@ -16,6 +16,8 @@
package org.springframework.integration.ip.tcp.connection;
+import org.springframework.context.SmartLifecycle;
+
/**
@@ -25,8 +27,8 @@ package org.springframework.integration.ip.tcp.connection;
* @since 2.0
*
*/
-public interface ConnectionFactory {
+public interface ConnectionFactory extends SmartLifecycle {
- public TcpConnection getConnection() throws Exception;
+ TcpConnection getConnection() throws Exception;
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnection.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnection.java
index 3fbfe27708..ebc9f79a67 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnection.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnection.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2001-2011 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.
@@ -26,9 +26,9 @@ import org.springframework.integration.Message;
/**
* An abstraction over {@link Socket} and {@link SocketChannel} that
* sends {@link Message} objects by serializing the payload
- * and streaming it to the destination. Requires a {@link TcpListener}
+ * and streaming it to the destination. Requires a {@link TcpListener}
* to receive incoming messages.
- *
+ *
* @author Gary Russell
* @since 2.0
*
@@ -38,115 +38,115 @@ public interface TcpConnection extends Runnable {
/**
* Closes the connection.
*/
- public void close();
+ void close();
/**
* @return true if the connection is open.
*/
- public boolean isOpen();
+ boolean isOpen();
/**
* Converts and sends the message.
* @param message The message
- * @throws Exception
+ * @throws Exception
*/
- public void send(Message> message) throws Exception;
+ void send(Message> message) throws Exception;
/**
* Uses the deserializer to obtain the message payload
* from the connection's input stream.
* @return The payload
- * @throws Exception
+ * @throws Exception
*/
- public Object getPayload() throws Exception;
+ Object getPayload() throws Exception;
/**
* @return the host name
*/
- public String getHostName();
+ String getHostName();
/**
* @return the host address
*/
- public String getHostAddress();
+ String getHostAddress();
/**
* @return the port
*/
- public int getPort();
+ int getPort();
/**
- * Sets the listener that will receive incoming Messages.
+ * Sets the listener that will receive incoming Messages.
* @param listener The listener
*/
- public void registerListener(TcpListener listener);
+ void registerListener(TcpListener listener);
/**
* Registers a sender. Used on server side sockets so a
* sender can determine which connection to send a reply
* to.
- * @param sender the sender
+ * @param sender the sender
*/
- public void registerSender(TcpSender sender);
+ void registerSender(TcpSender sender);
/**
* @return a string uniquely representing a connection.
*/
- public String getConnectionId();
+ String getConnectionId();
/**
* When true, the socket is used once and discarded.
* @param singleUse the singleUse
*/
- public void setSingleUse(boolean singleUse);
+ void setSingleUse(boolean singleUse);
/**
- *
+ *
* @return True if connection is used once.
*/
- public boolean isSingleUse();
+ boolean isSingleUse();
/**
- *
+ *
* @return True if connection is used once.
*/
- public boolean isServer();
+ boolean isServer();
/**
* @param mapper the mapper
*/
- public void setMapper(TcpMessageMapper mapper);
+ void setMapper(TcpMessageMapper mapper);
/**
- *
+ *
* @return the deserializer
*/
- public Deserializer> getDeserializer();
+ Deserializer> getDeserializer();
/**
* @param deserializer the deserializer to set
*/
- public void setDeserializer(Deserializer> deserializer);
+ void setDeserializer(Deserializer> deserializer);
/**
- *
+ *
* @return the serializer
*/
- public Serializer> getSerializer();
+ Serializer> getSerializer();
/**
* @param serializer the serializer to set
*/
- public void setSerializer(Serializer> serializer);
+ void setSerializer(Serializer> serializer);
/**
* @return this connection's listener
*/
- public TcpListener getListener();
+ TcpListener getListener();
/**
* @return the next sequence number for a message received on this socket
*/
- public long getConnectionSeq();
+ long incrementAndGetConnectionSequence();
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnectionInterceptor.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnectionInterceptor.java
index 3a7e9caeab..4db2d00083 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnectionInterceptor.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnectionInterceptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2001-2011 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.
@@ -22,6 +22,6 @@ package org.springframework.integration.ip.tcp.connection;
*/
public interface TcpConnectionInterceptor extends TcpConnection, TcpListener, TcpSender {
- public void setTheConnection(TcpConnection connection);
+ void setTheConnection(TcpConnection connection);
}
\ No newline at end of file
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnectionInterceptorFactory.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnectionInterceptorFactory.java
index 6a69543134..84edf4167b 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnectionInterceptorFactory.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpConnectionInterceptorFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2001-2011 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.
@@ -31,6 +31,6 @@ public interface TcpConnectionInterceptorFactory {
*
* @return the TcpInterceptor
*/
- public abstract TcpConnectionInterceptor getInterceptor();
+ abstract TcpConnectionInterceptor getInterceptor();
}
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpListener.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpListener.java
index c93b493a6f..aa617331ab 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpListener.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2010 the original author or authors.
+ * Copyright 2001-2011 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.
@@ -33,6 +33,6 @@ public interface TcpListener {
* @param message The message.
* @return true if the message was intercepted
*/
- public abstract boolean onMessage(Message> message);
+ abstract boolean onMessage(Message> message);
}
\ No newline at end of file
diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpMessageMapper.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpMessageMapper.java
index 56489a706a..a905506d1d 100644
--- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpMessageMapper.java
+++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/connection/TcpMessageMapper.java
@@ -41,20 +41,35 @@ public class TcpMessageMapper implements
OutboundMessageMapper