INT-781 Outbound TCP Adapters Namespace & Tests (Work in progress)

This commit is contained in:
Gary Russell
2010-02-26 22:40:19 +00:00
parent 6e2295b625
commit 81584599ae
12 changed files with 221 additions and 47 deletions

View File

@@ -82,4 +82,12 @@ public abstract class AbstractInternetProtocolSendingMessageHandler implements M
this.soSendBufferSize = size;
}
/**
* @return the port
*/
public int getPort() {
return port;
}
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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 " +

View File

@@ -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();

View File

@@ -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>