RouterEndpoint now delegates directly to a single ChannelResolver strategy. This removes the extra level of indirection that was provided by the Router interface. Also, instead of providing multiple ChannelResolver strategy interfaces, the name-resolving and single-channel implementations are now available as abstract base classes.

This commit is contained in:
Mark Fisher
2008-09-04 01:55:32 +00:00
parent b3a155de94
commit 40fc9c207d
30 changed files with 617 additions and 794 deletions

View File

@@ -22,8 +22,6 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.ConfigurationException;
import org.springframework.integration.router.MultiChannelRouter;
import org.springframework.integration.router.SingleChannelRouter;
import org.springframework.integration.xml.router.XPathMultiChannelNameResolver;
import org.springframework.integration.xml.router.XPathSingleChannelNameResolver;
import org.springframework.util.StringUtils;
@@ -54,27 +52,19 @@ public class XPathRouterParser extends AbstractSingleBeanDefinitionParser {
|| (!StringUtils.hasText(xPathExpression) && !StringUtils.hasText(xPathExpressionRef))) {
throw new ConfigurationException("Exactly one of 'xpath-expression' or 'xpath-expression-ref' is required.");
}
BeanDefinitionBuilder resolverDefinitionBuilder = null;
if (multiChannel) {
builder.getBeanDefinition().setBeanClass(MultiChannelRouter.class);
resolverDefinitionBuilder = BeanDefinitionBuilder
.genericBeanDefinition(XPathMultiChannelNameResolver.class);
builder.getBeanDefinition().setBeanClass(XPathMultiChannelNameResolver.class);
}
else {
builder.getBeanDefinition().setBeanClass(SingleChannelRouter.class);
resolverDefinitionBuilder = BeanDefinitionBuilder
.genericBeanDefinition(XPathSingleChannelNameResolver.class);
builder.getBeanDefinition().setBeanClass(XPathSingleChannelNameResolver.class);
}
if (StringUtils.hasText(xPathExpression)) {
XPathExpression expression = XPathExpressionFactory.createXPathExpression(xPathExpression);
resolverDefinitionBuilder.addConstructorArgValue(expression);
builder.addConstructorArgValue(expression);
}
else {
resolverDefinitionBuilder.addConstructorArgReference(xPathExpressionRef);
builder.addConstructorArgReference(xPathExpressionRef);
}
builder.addPropertyValue("channelNameResolver", resolverDefinitionBuilder.getBeanDefinition());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 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.
@@ -18,39 +18,41 @@ package org.springframework.integration.xml.router;
import java.util.List;
import org.springframework.integration.message.Message;
import org.springframework.integration.router.MultiChannelNameResolver;
import org.springframework.util.Assert;
import org.springframework.xml.xpath.NodeMapper;
import org.springframework.xml.xpath.XPathExpression;
import org.w3c.dom.DOMException;
import org.w3c.dom.Node;
import org.springframework.integration.message.Message;
import org.springframework.integration.router.AbstractMultiChannelNameResolver;
import org.springframework.integration.xml.util.XPathUtils;
import org.springframework.util.Assert;
import org.springframework.xml.xpath.NodeMapper;
import org.springframework.xml.xpath.XPathExpression;
/**
*
* @author Jonas Partner
*
*/
public class XPathMultiChannelNameResolver extends AbstractXPathChannelNameResolver implements MultiChannelNameResolver {
public class XPathMultiChannelNameResolver extends AbstractMultiChannelNameResolver {
private final XPathExpression xPathExpression;
private NodeMapper nodeMapper = new TextContentNodeMapper();
private volatile NodeMapper nodeMapper = new TextContentNodeMapper();
public XPathMultiChannelNameResolver(XPathExpression xPathExpression) {
Assert.notNull("XPAthExpression must be provided");
Assert.notNull("XPathExpression must not be null");
this.xPathExpression = xPathExpression;
}
public void setNodeMapper(NodeMapper nodeMapper) {
Assert.notNull(nodeMapper, "NodeMapper can not be null");
Assert.notNull(nodeMapper, "NodeMapper must not be null");
this.nodeMapper = nodeMapper;
}
@SuppressWarnings("unchecked")
public String[] resolve(Message<?> message) {
Node node = extractNode(message);
List channelNamesList = xPathExpression.evaluate(node, nodeMapper);
public String[] resolveChannelNames(Message<?> message) {
Node node = XPathUtils.extractPayloadAsNode(message);
List channelNamesList = this.xPathExpression.evaluate(node, this.nodeMapper);
return (String[]) channelNamesList.toArray(new String[channelNamesList.size()]);
}

View File

@@ -19,24 +19,26 @@ package org.springframework.integration.xml.router;
import org.w3c.dom.Node;
import org.springframework.integration.message.Message;
import org.springframework.integration.router.ChannelNameResolver;
import org.springframework.integration.router.AbstractSingleChannelNameResolver;
import org.springframework.integration.xml.util.XPathUtils;
import org.springframework.util.Assert;
import org.springframework.xml.xpath.XPathExpression;
/**
* @author Jonas Partner
*/
public class XPathSingleChannelNameResolver extends AbstractXPathChannelNameResolver implements ChannelNameResolver {
public class XPathSingleChannelNameResolver extends AbstractSingleChannelNameResolver {
private final XPathExpression xPathExpression;
public XPathSingleChannelNameResolver(XPathExpression xPathExpression) {
Assert.notNull("XPathExpression must be provided");
this.xPathExpression = xPathExpression;
}
public String resolve(Message<?> message) {
Node node = extractNode(message);
public String resolveChannelName(Message<?> message) {
Node node = XPathUtils.extractPayloadAsNode(message);
return xPathExpression.evaluateAsString(node);
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2007 the original author or authors.
* Copyright 2002-2008 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.
@@ -14,23 +14,27 @@
* limitations under the License.
*/
package org.springframework.integration.xml.router;
package org.springframework.integration.xml.util;
import org.w3c.dom.Node;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessagingException;
import org.w3c.dom.Node;
/**
*
* @author Jonas Partner
*
* @author Mark Fisher
*/
public class AbstractXPathChannelNameResolver {
public abstract class XPathUtils {
protected Node extractNode(Message<?> message) {
/**
* Return the given Message's payload as a Node if possible, else an Exception will be thrown.
*/
public static Node extractPayloadAsNode(Message<?> message) {
if (!Node.class.isAssignableFrom(message.getPayload().getClass())) {
throw new MessagingException(message, "Payload does not implement org.w3c.dom.Node so can not be evaluated");
throw new MessagingException(message, "payload is not assignable to [" + Node.class.getName() + "] so can not be evaluated");
}
return (Node) message.getPayload();
}
}

View File

@@ -34,24 +34,24 @@ import org.springframework.xml.xpath.XPathExpressionFactory;
*/
public class XPathMultiChannelNameResolverTests {
@SuppressWarnings("unchecked")
@Test
@SuppressWarnings("unchecked")
public void testSimpleSingleeAttribute() throws Exception {
Document doc = XmlTestUtil.getDocumentForString("<doc type=\"one\" />");
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathMultiChannelNameResolver resolver = new XPathMultiChannelNameResolver(expression);
String[] channelNames = resolver.resolve(new GenericMessage(doc));
String[] channelNames = resolver.resolveChannelNames(new GenericMessage(doc));
assertEquals("Wrong number of channels returend", 1, channelNames.length);
assertEquals("Wrong channel name", "one", channelNames[0]);
}
@SuppressWarnings("unchecked")
@Test
@SuppressWarnings("unchecked")
public void testMultipleNodeValues() throws Exception {
Document doc = XmlTestUtil.getDocumentForString("<doc type=\"one\"><book>bOne</book><book>bTwo</book></doc>");
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/book");
XPathMultiChannelNameResolver resolver = new XPathMultiChannelNameResolver(expression);
String[] channelNames = resolver.resolve(new GenericMessage(doc));
String[] channelNames = resolver.resolveChannelNames(new GenericMessage(doc));
assertEquals("Wrong number of channels returend", 2, channelNames.length);
assertEquals("Wrong channel name", "bOne", channelNames[0]);
assertEquals("Wrong channel name", "bTwo", channelNames[1]);
@@ -61,7 +61,7 @@ public class XPathMultiChannelNameResolverTests {
public void testNonNodePayload() throws Exception {
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathMultiChannelNameResolver resolver = new XPathMultiChannelNameResolver(expression);
resolver.resolve(new StringMessage("test"));
resolver.resolveChannelNames(new StringMessage("test"));
}
}

View File

@@ -24,7 +24,6 @@ import org.w3c.dom.Document;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.message.MessagingException;
import org.springframework.integration.message.StringMessage;
import org.springframework.integration.xml.router.XPathSingleChannelNameResolver;
import org.springframework.integration.xml.util.XmlTestUtil;
import org.springframework.xml.xpath.XPathExpression;
import org.springframework.xml.xpath.XPathExpressionFactory;
@@ -34,13 +33,13 @@ import org.springframework.xml.xpath.XPathExpressionFactory;
*/
public class XPathSingleChannelNameResolverTests {
@SuppressWarnings("unchecked")
@Test
@SuppressWarnings("unchecked")
public void testSimpleDocType() throws Exception {
Document doc = XmlTestUtil.getDocumentForString("<doc type=\"one\" />");
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathSingleChannelNameResolver resolver = new XPathSingleChannelNameResolver(expression);
String channelName = resolver.resolve(new GenericMessage(doc));
String channelName = resolver.resolveChannelName(new GenericMessage(doc));
assertEquals("Wrong channel name", "one", channelName);
}
@@ -48,7 +47,7 @@ public class XPathSingleChannelNameResolverTests {
public void testNonNodePayload() throws Exception {
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathSingleChannelNameResolver resolver = new XPathSingleChannelNameResolver(expression);
resolver.resolve(new StringMessage("test"));
resolver.resolveChannelName(new StringMessage("test"));
}
}