INT-781 Outbound TCP Adapters Namespace & Tests (Work in progress)
This commit is contained in:
@@ -82,4 +82,12 @@ public abstract class AbstractInternetProtocolSendingMessageHandler implements M
|
||||
this.soSendBufferSize = size;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the port
|
||||
*/
|
||||
public int getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -77,8 +77,15 @@ public abstract class IpAdapterParserUtils {
|
||||
static final String CUSTOM_SOCKET_READER_CLASS_NAME =
|
||||
"custom-socket-reader-class-name";
|
||||
|
||||
// static final String
|
||||
static final String CUSTOM_SOCKET_WRITER_CLASS_NAME =
|
||||
"custom-socket-writer-class-name";
|
||||
|
||||
static final String SO_LINGER = "so-linger";
|
||||
|
||||
static final String SO_TCP_NODELAY = "so-tcp-nodelay";
|
||||
|
||||
static final String SO_TRAFFIC_CLASS = "so-traffic-class";
|
||||
|
||||
|
||||
/**
|
||||
* Adds a constructor-arg to the bean definition with the value
|
||||
|
||||
@@ -16,17 +16,19 @@
|
||||
|
||||
package org.springframework.integration.ip.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler;
|
||||
import org.springframework.integration.ip.tcp.TcpNioSendingMessageHandler;
|
||||
import org.springframework.integration.ip.udp.MulticastSendingMessageHandler;
|
||||
import org.springframework.integration.ip.udp.UnicastSendingMessageHandler;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
@@ -38,25 +40,21 @@ public class IpOutboundChannelAdapterParser extends AbstractOutboundChannelAdapt
|
||||
String protocol = IpAdapterParserUtils.getProtocol(element);
|
||||
BeanDefinitionBuilder builder = null;
|
||||
if (protocol.equals("tcp")) {
|
||||
throw new BeanCreationException("tcp not yet supported");
|
||||
builder = parseTcp(element);
|
||||
}
|
||||
else if (protocol.equals("udp")) {
|
||||
String multicast = IpAdapterParserUtils.getMulticast(element);
|
||||
if (multicast.equals("true")) {
|
||||
builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(MulticastSendingMessageHandler.class);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder,
|
||||
element, IpAdapterParserUtils.MIN_ACKS_SUCCESS,
|
||||
"minAcksForSuccess");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder,
|
||||
element, IpAdapterParserUtils.TIME_TO_LIVE,
|
||||
"timeToLive");
|
||||
}
|
||||
else {
|
||||
builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(UnicastSendingMessageHandler.class);
|
||||
}
|
||||
builder = parseUdp(element);
|
||||
}
|
||||
IpAdapterParserUtils.addCommonSocketOptions(builder, element);
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param element
|
||||
* @param builder
|
||||
*/
|
||||
private void addHostAndPortToConstructor(Element element,
|
||||
BeanDefinitionBuilder builder) {
|
||||
String host = element.getAttribute(IpAdapterParserUtils.HOST);
|
||||
if (!StringUtils.hasText(host)) {
|
||||
throw new BeanCreationException(IpAdapterParserUtils.HOST
|
||||
@@ -65,6 +63,30 @@ public class IpOutboundChannelAdapterParser extends AbstractOutboundChannelAdapt
|
||||
builder.addConstructorArgValue(host);
|
||||
String port = IpAdapterParserUtils.getPort(element);
|
||||
builder.addConstructorArgValue(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param element
|
||||
* @return
|
||||
*/
|
||||
private BeanDefinitionBuilder parseUdp(Element element) {
|
||||
BeanDefinitionBuilder builder;
|
||||
String multicast = IpAdapterParserUtils.getMulticast(element);
|
||||
if (multicast.equals("true")) {
|
||||
builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(MulticastSendingMessageHandler.class);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder,
|
||||
element, IpAdapterParserUtils.MIN_ACKS_SUCCESS,
|
||||
"minAcksForSuccess");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder,
|
||||
element, IpAdapterParserUtils.TIME_TO_LIVE,
|
||||
"timeToLive");
|
||||
}
|
||||
else {
|
||||
builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(UnicastSendingMessageHandler.class);
|
||||
}
|
||||
addHostAndPortToConstructor(element, builder);
|
||||
IpAdapterParserUtils.addConstuctorValueIfAttributeDefined(builder,
|
||||
element, IpAdapterParserUtils.CHECK_LENGTH, true);
|
||||
IpAdapterParserUtils.addConstuctorValueIfAttributeDefined(builder,
|
||||
@@ -91,10 +113,43 @@ public class IpOutboundChannelAdapterParser extends AbstractOutboundChannelAdapt
|
||||
+ " must be supplied");
|
||||
}
|
||||
}
|
||||
IpAdapterParserUtils.addCommonSocketOptions(builder, element);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.RECEIVE_BUFFER_SIZE);
|
||||
return builder.getBeanDefinition();
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param element
|
||||
* @return
|
||||
*/
|
||||
private BeanDefinitionBuilder parseTcp(Element element) {
|
||||
BeanDefinitionBuilder builder;
|
||||
String useNio = IpAdapterParserUtils.getUseNio(element);
|
||||
if (useNio.equals("false")) {
|
||||
builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(TcpNetSendingMessageHandler.class);
|
||||
}
|
||||
else {
|
||||
builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(TcpNioSendingMessageHandler.class);
|
||||
}
|
||||
addHostAndPortToConstructor(element, builder);
|
||||
builder.addPropertyValue(
|
||||
Conventions.attributeNameToPropertyName(IpAdapterParserUtils.MESSAGE_FORMAT),
|
||||
IpAdapterParserUtils.getMessageFormat(element));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.CUSTOM_SOCKET_WRITER_CLASS_NAME);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.USING_DIRECT_BUFFERS);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.SO_KEEP_ALIVE);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.SO_LINGER);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.SO_TCP_NODELAY);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.SO_TRAFFIC_CLASS);
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public abstract class AbstractTcpReceivingChannelAdapter extends
|
||||
*/
|
||||
public void run() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(this.getClass().getSimpleName() + " running...");
|
||||
logger.debug(this.getClass().getSimpleName() + " running on port: " + port);
|
||||
}
|
||||
if (this.active && this.threadPoolTaskScheduler == null) {
|
||||
this.threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
|
||||
|
||||
@@ -50,7 +50,7 @@ public abstract class AbstractTcpSendingMessageHandler extends
|
||||
|
||||
protected boolean soKeepAlive = false;
|
||||
|
||||
protected int messageFormat;
|
||||
protected int messageFormat = MessageFormats.FORMAT_LENGTH_HEADER;
|
||||
|
||||
protected boolean blockingWrite = false;
|
||||
|
||||
@@ -111,7 +111,7 @@ public abstract class AbstractTcpSendingMessageHandler extends
|
||||
.newSingleThreadExecutor(new ThreadFactory() {
|
||||
public Thread newThread(Runnable runner) {
|
||||
Thread thread = new Thread(runner);
|
||||
thread.setName("UDP-Ack-Handler");
|
||||
thread.setName("Tcp-NonBlocking-Handler-port-" + port);
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
}
|
||||
@@ -131,9 +131,16 @@ public abstract class AbstractTcpSendingMessageHandler extends
|
||||
protected void doWrite(Message<?> message) {
|
||||
try {
|
||||
byte[] bytes = mapper.fromMessage(message);
|
||||
this.getWriter().write(bytes);
|
||||
SocketWriter writer = this.getWriter();
|
||||
if (writer == null) {
|
||||
throw new MessageMappingException("Failed to create SocketWriter");
|
||||
}
|
||||
writer.write(bytes);
|
||||
} catch (Exception e) {
|
||||
writer = null;
|
||||
if (e instanceof MessageMappingException) {
|
||||
throw (MessageMappingException) e;
|
||||
}
|
||||
throw new MessageMappingException("Failed to map message", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +230,10 @@ public class NioSocketReader extends AbstractSocketReader {
|
||||
protected void readChannel(ByteBuffer buffer) throws IOException {
|
||||
try {
|
||||
int len = channel.read(buffer);
|
||||
if (len < 0) {
|
||||
logger.debug("Socket closed");
|
||||
throw new IOException("Socket closed");
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Read " + len + " bytes, buffer is now at " +
|
||||
buffer.position() + " of " +
|
||||
|
||||
@@ -67,7 +67,7 @@ public class TcpNioReceivingChannelAdapter extends
|
||||
try {
|
||||
serverChannel = ServerSocketChannel.open();
|
||||
serverChannel.configureBlocking(false);
|
||||
serverChannel.socket().bind(new InetSocketAddress(port));
|
||||
serverChannel.socket().bind(new InetSocketAddress(port), 10);
|
||||
final Selector selector = Selector.open();
|
||||
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
|
||||
doSelect(serverChannel, selector);
|
||||
@@ -107,7 +107,7 @@ public class TcpNioReceivingChannelAdapter extends
|
||||
while (active) {
|
||||
int selectionCount = selector.select();
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("SelectionCount: " + selectionCount);
|
||||
logger.debug("Port " + port + " SelectionCount: " + selectionCount);
|
||||
if (selectionCount > 0) {
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = keys.iterator();
|
||||
|
||||
@@ -66,6 +66,11 @@ the custom message format. See java docs for TcpNetReceivingChannelAdapter and T
|
||||
<xsd:attribute name="ack-port" type="xsd:string" />
|
||||
<xsd:attribute name="ack-timeout" type="xsd:string" />
|
||||
<xsd:attribute name="time-to-live" type="xsd:string" />
|
||||
<xsd:attribute name="custom-socket-writer-class-name" type="xsd:string" />
|
||||
<xsd:attribute name="so-linger" type="xsd:string" />
|
||||
<xsd:attribute name="so-tcp-nodelay" type="xsd:boolean" />
|
||||
<xsd:attribute name="so-traffic-class" type="xsd:string" />
|
||||
<xsd:attribute name="blocking-write" type="xsd:boolean" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
Reference in New Issue
Block a user