remove channel-resolver attribute

remove ChannelResolver awareness from router parsers and FactoryBean

refactor 'channelIdentifierMap' -> 'channelMappings' and other clarity enhancements

trim array tokens

added AbstractMappingMessageRouter
This commit is contained in:
Mark Fisher
2011-10-17 17:24:09 -04:00
parent f11b17f9fb
commit 73c9876aca
30 changed files with 457 additions and 471 deletions

View File

@@ -96,10 +96,6 @@
<entry>order</entry>
<entry><imagedata fileref="images/tickmark.png"/></entry><entry><imagedata fileref="images/tickmark.png"/></entry><entry><imagedata fileref="images/tickmark.png"/></entry><entry><imagedata fileref="images/tickmark.png"/></entry><entry><imagedata fileref="images/tickmark.png"/></entry><entry><imagedata fileref="images/tickmark.png"/></entry>
</row>
<row>
<entry>channel-resolver</entry>
<entry><imagedata fileref="images/tickmark.png"/></entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
</row>
<row>
<entry>method</entry>
<entry><imagedata fileref="images/tickmark.png"/></entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
@@ -188,10 +184,6 @@
<entry>order</entry>
<entry></entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
</row>
<row>
<entry>channel-resolver</entry>
<entry><imagedata fileref="images/tickmark.png"/></entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
</row>
<row>
<entry>method</entry>
<entry><imagedata fileref="images/tickmark.png"/></entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
@@ -793,8 +785,8 @@ public List<String> route(@Header("orderStatus") OrderStatus status)]]></program
</listitem>
<listitem>
<para><emphasis>Step 3</emphasis> - Resolve <code>channel name</code> to the actual instance of the
<classname>MessageChannel</classname> where using <classname>ChannelResolver</classname>, the router will obtain a
reference to a bean (which is hopefully a <classname>MessageChannel</classname>) identified by the result of the
<classname>MessageChannel</classname> as a reference to a bean within the Application Context
(which is hopefully a <classname>MessageChannel</classname>) identified by the result of the
previous step.</para>
</listitem>
</itemizedlist>
@@ -825,8 +817,8 @@ public List<String> route(@Header("orderStatus") OrderStatus status)]]></program
</listitem>
<listitem>
<para><emphasis>Step 3</emphasis> - Resolve <code>channel name</code> to the actual instance of the
<classname>MessageChannel</classname> where using <classname>ChannelResolver</classname>, the router will obtain a
reference to a bean (which is hopefully a <classname>MessageChannel</classname>) identified by the result of the
<classname>MessageChannel</classname> as a reference to a bean within the Application Context
(which is hopefully a <classname>MessageChannel</classname>) identified by the result of the
previous step.</para>
</listitem>
</itemizedlist>
@@ -860,9 +852,8 @@ public List<String> route(@Header("orderStatus") OrderStatus status)]]></program
</para>
<para>
So all that is left is for Step 3 to resolve the <code>channel name</code> ('kermit') to an actual instance of the
<classname>MessageChannel</classname> identified by this name. That will be done via the default
<interface>ChannelResolver</interface> implementation which is a <classname>BeanFactoryChannelResolver</classname>. It
basically does a bean lookup for the name provided. So now all messages which contain the header/value pair as <code>testHeader=kermit</code>
<classname>MessageChannel</classname> identified by this name. That basically involves a bean lookup
for the name provided. So now all messages which contain the header/value pair as <code>testHeader=kermit</code>
are going to be routed to a <classname>MessageChannel</classname> whose bean name (id) is 'kermit'.
</para>
<para>

View File

@@ -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. You may obtain a copy of the License at
@@ -18,10 +18,9 @@ import java.util.Map;
import org.springframework.expression.Expression;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.core.MessageHandler;
import org.springframework.integration.router.AbstractMessageRouter;
import org.springframework.integration.router.AbstractMappingMessageRouter;
import org.springframework.integration.router.ExpressionEvaluatingRouter;
import org.springframework.integration.router.MethodInvokingRouter;
import org.springframework.integration.support.channel.ChannelResolver;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -35,9 +34,7 @@ import org.springframework.util.StringUtils;
*/
public class RouterFactoryBean extends AbstractStandardMessageHandlerFactoryBean {
private volatile ChannelResolver channelResolver;
private volatile Map<String, String> channelIdentifierMap;
private volatile Map<String, String> channelMappings;
private volatile MessageChannel defaultOutputChannel;
@@ -50,10 +47,6 @@ public class RouterFactoryBean extends AbstractStandardMessageHandlerFactoryBean
private volatile Boolean ignoreSendFailures;
public void setChannelResolver(ChannelResolver channelResolver) {
this.channelResolver = channelResolver;
}
public void setDefaultOutputChannel(MessageChannel defaultOutputChannel) {
this.defaultOutputChannel = defaultOutputChannel;
}
@@ -74,14 +67,14 @@ public class RouterFactoryBean extends AbstractStandardMessageHandlerFactoryBean
this.ignoreSendFailures = ignoreSendFailures;
}
public void setChannelIdentifierMap(Map<String, String> channelIdentifierMap) {
this.channelIdentifierMap = channelIdentifierMap;
public void setChannelMappings(Map<String, String> channelMappings) {
this.channelMappings = channelMappings;
}
@Override
MessageHandler createMethodInvokingHandler(Object targetObject, String targetMethodName) {
Assert.notNull(targetObject, "target object must not be null");
AbstractMessageRouter router = this.extractTypeIfPossible(targetObject, AbstractMessageRouter.class);
AbstractMappingMessageRouter router = this.extractTypeIfPossible(targetObject, AbstractMappingMessageRouter.class);
if (router == null) {
router = this.createMethodInvokingRouter(targetObject, targetMethodName);
this.configureRouter(router);
@@ -102,19 +95,16 @@ public class RouterFactoryBean extends AbstractStandardMessageHandlerFactoryBean
return this.configureRouter(new ExpressionEvaluatingRouter(expression));
}
private AbstractMessageRouter createMethodInvokingRouter(Object targetObject, String targetMethodName) {
private AbstractMappingMessageRouter createMethodInvokingRouter(Object targetObject, String targetMethodName) {
MethodInvokingRouter router = (StringUtils.hasText(targetMethodName))
? new MethodInvokingRouter(targetObject, targetMethodName)
: new MethodInvokingRouter(targetObject);
return router;
}
private AbstractMessageRouter configureRouter(AbstractMessageRouter router) {
if (this.channelResolver != null) {
router.setChannelResolver(this.channelResolver);
}
if (this.channelIdentifierMap != null) {
router.setChannelIdentifierMap(this.channelIdentifierMap);
private AbstractMappingMessageRouter configureRouter(AbstractMappingMessageRouter router) {
if (this.channelMappings != null) {
router.setChannelMappings(this.channelMappings);
}
if (this.defaultOutputChannel != null) {
router.setDefaultOutputChannel(this.defaultOutputChannel);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 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.
@@ -41,7 +41,7 @@ public class RouterAnnotationPostProcessor extends AbstractMethodAnnotationPostP
@Override
protected MessageHandler createHandler(Object bean, Method method, Router annotation) {
MethodInvokingRouter router = new MethodInvokingRouter(bean, method);
router.setChannelResolver(this.channelResolver);
router.setBeanFactory(this.beanFactory);
String defaultOutputChannelName = annotation.defaultOutputChannel();
if (StringUtils.hasText(defaultOutputChannelName)) {
MessageChannel defaultOutputChannel = this.channelResolver.resolveChannelName(defaultOutputChannelName);

View File

@@ -21,11 +21,11 @@ import java.util.List;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.StringUtils;
import org.springframework.integration.config.RouterFactoryBean;
import org.springframework.util.CollectionUtils;
import org.springframework.util.xml.DomUtils;
/**
@@ -37,8 +37,7 @@ public abstract class AbstractRouterParser extends AbstractConsumerEndpointParse
@Override
protected final BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".config.RouterFactoryBean");
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(RouterFactoryBean.class);
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "default-output-channel");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "timeout");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "resolution-required");
@@ -52,28 +51,28 @@ public abstract class AbstractRouterParser extends AbstractConsumerEndpointParse
protected final BeanDefinition parseRouter(Element element, ParserContext parserContext) {
BeanDefinition beanDefinition = this.doParseRouter(element, parserContext);
if (beanDefinition != null) {
String channelResolver = element.getAttribute("channel-resolver");
if (StringUtils.hasText(channelResolver)){
beanDefinition.getPropertyValues().add("channelResolver", new RuntimeBeanReference(channelResolver));
}
// check if mapping is provided otherwise returned values will be treated as channel names
List<Element> childElements = DomUtils.getChildElementsByTagName(element, "mapping");
if (childElements != null && childElements.size() > 0) {
ManagedMap<String, String> channelMap = new ManagedMap<String, String>();
for (Element childElement : childElements) {
String key = childElement.getAttribute(this.getMappingKeyAttributeValue());
channelMap.put(key, childElement.getAttribute("channel"));
List<Element> mappingElements = DomUtils.getChildElementsByTagName(element, "mapping");
if (!CollectionUtils.isEmpty(mappingElements)) {
ManagedMap<String, String> channelMappings = new ManagedMap<String, String>();
for (Element mappingElement : mappingElements) {
String key = mappingElement.getAttribute(this.getMappingKeyAttributeName());
channelMappings.put(key, mappingElement.getAttribute("channel"));
}
beanDefinition.getPropertyValues().add("channelIdentifierMap", channelMap);
beanDefinition.getPropertyValues().add("channelMappings", channelMappings);
}
}
return beanDefinition;
}
protected abstract BeanDefinition doParseRouter(Element element, ParserContext parserContext);
protected String getMappingKeyAttributeValue(){
/**
* Returns the name of the attribute that provides a key for the
* channel mappings. This can be overridden by subclasses.
*/
protected String getMappingKeyAttributeName() {
return "value";
}
protected abstract BeanDefinition doParseRouter(Element element, ParserContext parserContext);
}

View File

@@ -18,14 +18,13 @@ package org.springframework.integration.config.xml;
import java.util.List;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element;
/**
* Parser for the &lt;router/&gt; element.
@@ -35,9 +34,6 @@ import org.w3c.dom.Element;
*/
public class DefaultRouterParser extends AbstractDelegatingConsumerEndpointParser {
private static final String CHANNEL_RESOLVER_PROPERTY = "channelResolver";
@Override
String getFactoryBeanClassName() {
return IntegrationNamespaceUtils.BASE_PACKAGE + ".config.RouterFactoryBean";
@@ -50,30 +46,13 @@ public class DefaultRouterParser extends AbstractDelegatingConsumerEndpointParse
@Override
protected void postProcess(BeanDefinitionBuilder builder, Element element, ParserContext parserContext) {
String resolverBeanName = element.getAttribute("channel-resolver");
List<Element> mappingElements = DomUtils.getChildElementsByTagName(element, "mapping");
if (!CollectionUtils.isEmpty(mappingElements)) {
if (StringUtils.hasText(resolverBeanName)) {
parserContext.getReaderContext().error(
"The 'channel-resolver' attribute and 'mapping' sub-elements are mutually exclusive.",
parserContext.extractSource(element));
}
BeanDefinitionBuilder channelResolverBuilder = BeanDefinitionBuilder.genericBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".support.channel.BeanFactoryChannelResolver");
ManagedMap<String, String> channelMap = new ManagedMap<String, String>();
ManagedMap<String, String> channelMappings = new ManagedMap<String, String>();
for (Element mappingElement : mappingElements) {
channelMap.put(mappingElement.getAttribute("value"), mappingElement.getAttribute("channel"));
channelMappings.put(mappingElement.getAttribute("value"), mappingElement.getAttribute("channel"));
}
builder.addPropertyValue("channelIdentifierMap", channelMap);
builder.addPropertyValue(CHANNEL_RESOLVER_PROPERTY, channelResolverBuilder.getBeanDefinition());
}
else if (StringUtils.hasText(resolverBeanName)) {
builder.addPropertyReference(CHANNEL_RESOLVER_PROPERTY, resolverBeanName);
}
else {
RootBeanDefinition resolverBeanDefintion = new RootBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".support.channel.BeanFactoryChannelResolver");
builder.addPropertyValue(CHANNEL_RESOLVER_PROPERTY, resolverBeanDefintion);
builder.addPropertyValue("channelMappings", channelMappings);
}
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "default-output-channel");
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "timeout");

View File

@@ -16,11 +16,13 @@
package org.springframework.integration.config.xml;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.router.ErrorMessageExceptionTypeRouter;
/**
* Parser for the &lt;exception-type-router/&gt; element.
*
@@ -28,17 +30,15 @@ import org.w3c.dom.Element;
* @since 2.0.4
*/
public class ErrorMessageExceptionTypeRouterParser extends AbstractRouterParser {
@Override
protected BeanDefinition doParseRouter(Element element,
ParserContext parserContext) {
BeanDefinitionBuilder payloadTypeRouterBuilder = BeanDefinitionBuilder.genericBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".router.ErrorMessageExceptionTypeRouter");
return payloadTypeRouterBuilder.getBeanDefinition();
}
@Override
protected String getMappingKeyAttributeValue(){
protected String getMappingKeyAttributeName() {
return "exception-type";
}
@Override
protected BeanDefinition doParseRouter(Element element, ParserContext parserContext) {
return new RootBeanDefinition(ErrorMessageExceptionTypeRouter.class);
}
}

View File

@@ -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 org.w3c.dom.Element;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.router.HeaderValueRouter;
/**
* Parser for the &lt;header-value-router/&gt; element.
@@ -33,8 +34,7 @@ public class HeaderValueRouterParser extends AbstractRouterParser {
@Override
protected BeanDefinition doParseRouter(Element element, ParserContext parserContext) {
BeanDefinitionBuilder headerValueRouterBuilder = BeanDefinitionBuilder.genericBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".router.HeaderValueRouter");
BeanDefinitionBuilder headerValueRouterBuilder = BeanDefinitionBuilder.genericBeanDefinition(HeaderValueRouter.class);
headerValueRouterBuilder.addConstructorArgValue(element.getAttribute("header-name"));
return headerValueRouterBuilder.getBeanDefinition();
}

View File

@@ -17,8 +17,9 @@
package org.springframework.integration.config.xml;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.router.PayloadTypeRouter;
import org.w3c.dom.Element;
/**
@@ -29,17 +30,15 @@ import org.w3c.dom.Element;
* @since 1.0.3
*/
public class PayloadTypeRouterParser extends AbstractRouterParser {
@Override
protected BeanDefinition doParseRouter(Element element,
ParserContext parserContext) {
BeanDefinitionBuilder payloadTypeRouterBuilder = BeanDefinitionBuilder.genericBeanDefinition(
IntegrationNamespaceUtils.BASE_PACKAGE + ".router.PayloadTypeRouter");
return payloadTypeRouterBuilder.getBeanDefinition();
}
@Override
protected String getMappingKeyAttributeValue(){
protected String getMappingKeyAttributeName() {
return "type";
}
@Override
protected BeanDefinition doParseRouter(Element element, ParserContext parserContext) {
return new RootBeanDefinition(PayloadTypeRouter.class);
}
}

View File

@@ -0,0 +1,229 @@
/*
* 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.router;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.MessagingException;
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
import org.springframework.integration.support.channel.ChannelResolutionException;
import org.springframework.integration.support.channel.ChannelResolver;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Base class for all Message Routers.
*
* @author Mark Fisher
* @author Oleg Zhurakousky
* @author Gunnar Hillert
* @since 2.1
*/
@ManagedResource
public abstract class AbstractMappingMessageRouter extends AbstractMessageRouter {
private final Map<String, String> channelMappings = new ConcurrentHashMap<String, String>();
private volatile ChannelResolver channelResolver;
private volatile String prefix;
private volatile String suffix;
private volatile boolean resolutionRequired = true;
/**
* Provide mappings from channel keys to channel names.
* Channel names will be resolved by the {@link ChannelResolver}.
*/
public void setChannelMappings(Map<String, String> channelMappings) {
this.channelMappings.clear();
this.channelMappings.putAll(channelMappings);
}
/**
* Specify the {@link ChannelResolver} strategy to use.
* The default is a BeanFactoryChannelResolver.
*/
public void setChannelResolver(ChannelResolver channelResolver) {
Assert.notNull(channelResolver, "'channelResolver' must not be null");
this.channelResolver = channelResolver;
}
/**
* Specify a prefix to be added to each channel name prior to resolution.
*/
public void setPrefix(String prefix) {
this.prefix = prefix;
}
/**
* Specify a suffix to be added to each channel name prior to resolution.
*/
public void setSuffix(String suffix) {
this.suffix = suffix;
}
/**
* Specify whether this router should ignore any failure to resolve a channel name to
* an actual MessageChannel instance when delegating to the ChannelResolver strategy.
*/
public void setResolutionRequired(boolean resolutionRequired) {
this.resolutionRequired = resolutionRequired;
}
/**
* Returns an unmodifiable version of the channel mappings.
* This is intended for use by subclasses only.
*/
protected Map<String, String> getChannelMappings() {
return Collections.unmodifiableMap(this.channelMappings);
}
/**
* Add a channel mapping from the provided key to channel name.
*/
@ManagedOperation
public void setChannelMapping(String key, String channelName) {
this.channelMappings.put(key, channelName);
}
/**
* Remove a channel mapping for the given key if present.
*/
@ManagedOperation
public void removeChannelMapping(String key) {
this.channelMappings.remove(key);
}
@Override
public void onInit() {
BeanFactory beanFactory = this.getBeanFactory();
if (this.channelResolver == null && beanFactory != null) {
this.channelResolver = new BeanFactoryChannelResolver(beanFactory);
}
}
/**
* Subclasses must implement this method to return the channel keys.
* A "key" might be present in this router's "channelMappings", or it
* could be the channel's name or even the Message Channel instance itself.
*/
protected abstract List<Object> getChannelKeys(Message<?> message);
@Override
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
Collection<MessageChannel> channels = new ArrayList<MessageChannel>();
Collection<Object> channelKeys = this.getChannelKeys(message);
addToCollection(channels, channelKeys, message);
return channels;
}
private MessageChannel resolveChannelForName(String channelName, Message<?> message) {
if (this.channelResolver == null) {
this.onInit();
}
Assert.state(this.channelResolver != null, "unable to resolve channel names, no ChannelResolver available");
MessageChannel channel = null;
try {
channel = this.channelResolver.resolveChannelName(channelName);
}
catch (ChannelResolutionException e) {
if (this.resolutionRequired) {
throw new MessagingException(message, "failed to resolve channel name '" + channelName + "'", e);
}
}
if (channel == null && this.resolutionRequired) {
throw new MessagingException(message, "failed to resolve channel name '" + channelName + "'");
}
return channel;
}
private void addChannelFromString(Collection<MessageChannel> channels, String channelKey, Message<?> message) {
if (channelKey.indexOf(',') != -1) {
for (String name : StringUtils.tokenizeToStringArray(channelKey, ",")) {
addChannelFromString(channels, name, message);
}
return;
}
// if the channelMappings contains a mapping, we'll use the mapped value
// otherwise, the String-based channelKey itself will be used as the channel name
String channelName = channelKey;
if (this.channelMappings.containsKey(channelKey)) {
channelName = this.channelMappings.get(channelKey);
}
if (this.prefix != null) {
channelName = this.prefix + channelName;
}
if (this.suffix != null) {
channelName = channelName + this.suffix;
}
MessageChannel channel = resolveChannelForName(channelName, message);
if (channel != null) {
channels.add(channel);
}
}
private void addToCollection(Collection<MessageChannel> channels, Collection<?> channelKeys, Message<?> message) {
if (channelKeys == null) {
return;
}
for (Object channelKey : channelKeys) {
if (channelKey == null) {
continue;
}
else if (channelKey instanceof MessageChannel) {
channels.add((MessageChannel) channelKey);
}
else if (channelKey instanceof MessageChannel[]) {
channels.addAll(Arrays.asList((MessageChannel[]) channelKey));
}
else if (channelKey instanceof String) {
addChannelFromString(channels, (String) channelKey, message);
}
else if (channelKey instanceof String[]) {
for (String indicatorName : (String[]) channelKey) {
addChannelFromString(channels, indicatorName, message);
}
}
else if (channelKey instanceof Collection) {
addToCollection(channels, (Collection<?>) channelKey, message);
}
else if (this.getRequiredConversionService().canConvert(channelKey.getClass(), String.class)) {
addChannelFromString(channels, this.getConversionService().convert(channelKey, String.class), message);
}
else {
throw new MessagingException("unsupported return type for router [" + channelKey.getClass() + "]");
}
}
}
}

View File

@@ -32,7 +32,7 @@ import org.springframework.util.Assert;
* @author Mark Fisher
* @since 2.0
*/
class AbstractMessageProcessingRouter extends AbstractMessageRouter {
class AbstractMessageProcessingRouter extends AbstractMappingMessageRouter {
private final MessageProcessor<Object> messageProcessor;
@@ -55,7 +55,7 @@ class AbstractMessageProcessingRouter extends AbstractMessageRouter {
}
@Override
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
Object result = this.messageProcessor.processMessage(message);
return Collections.singletonList(result);
}

View File

@@ -16,14 +16,8 @@
package org.springframework.integration.router;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.support.ConversionServiceFactory;
import org.springframework.integration.Message;
@@ -34,14 +28,7 @@ import org.springframework.integration.channel.NullChannel;
import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.handler.AbstractMessageHandler;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
import org.springframework.integration.support.channel.ChannelResolutionException;
import org.springframework.integration.support.channel.ChannelResolver;
import org.springframework.jmx.export.annotation.ManagedOperation;
import org.springframework.jmx.export.annotation.ManagedResource;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
/**
* Base class for all Message Routers.
@@ -61,63 +48,6 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
private final MessagingTemplate messagingTemplate = new MessagingTemplate();
private volatile String prefix;
private volatile String suffix;
private volatile ChannelResolver channelResolver;
private volatile boolean resolutionRequired = true;
protected volatile Map<String, String> channelIdentifierMap = new ConcurrentHashMap<String, String>();
/**
* Specify the {@link ChannelResolver} strategy to use.
* The default is a BeanFactoryChannelResolver.
*/
public void setChannelResolver(ChannelResolver channelResolver) {
Assert.notNull(channelResolver, "'channelResolver' must not be null");
this.channelResolver = channelResolver;
}
/**
* Specify a prefix to be added to each channel name prior to resolution.
*/
public void setPrefix(String prefix) {
this.prefix = prefix;
}
/**
* Specify a suffix to be added to each channel name prior to resolution.
*/
public void setSuffix(String suffix) {
this.suffix = suffix;
}
/**
* Allows you to set the map which will map channel identifiers to channel names.
* Channel names will be resolve via {@link ChannelResolver}
* @param channelIdentifierMap
*/
public void setChannelIdentifierMap(Map<String, String> channelIdentifierMap) {
this.channelIdentifierMap.clear();
this.channelIdentifierMap.putAll(channelIdentifierMap);
}
@ManagedOperation
public void setChannelMapping(String channelIdentifier, String channelName) {
this.channelIdentifierMap.put(channelIdentifier, channelName);
}
/**
* Removes channel mapping for a give channel identifier
* @param channelIdentifier
*/
@ManagedOperation
public void removeChannelMapping(String channelIdentifier) {
this.channelIdentifierMap.remove(channelIdentifier);
}
/**
* Set the default channel where Messages should be sent if channel resolution
@@ -139,14 +69,6 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
this.messagingTemplate.setSendTimeout(timeout);
}
/**
* Specify whether this router should ignore any failure to resolve a channel name to
* an actual MessageChannel instance when delegating to the ChannelResolver strategy.
*/
public void setResolutionRequired(boolean resolutionRequired) {
this.resolutionRequired = resolutionRequired;
}
/**
* Specify whether send failures for one or more of the recipients should be ignored. By default this is
* <code>false</code> meaning that an Exception will be thrown whenever a send fails. To override this and suppress
@@ -178,14 +100,6 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
return this.messagingTemplate;
}
@Override
public void onInit() {
BeanFactory beanFactory = this.getBeanFactory();
if (this.channelResolver == null && beanFactory != null) {
this.channelResolver = new BeanFactoryChannelResolver(beanFactory);
}
}
protected ConversionService getRequiredConversionService() {
if (this.getConversionService() == null) {
this.setConversionService(ConversionServiceFactory.createDefaultConversionService());
@@ -194,10 +108,10 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
}
/**
* Subclasses must implement this method to return the channel identifiers.
* Subclasses must implement this method to return a Collection of zero or more
* MessageChannels to which the given Message should be routed.
*/
protected abstract List<Object> getChannelIdentifiers(Message<?> message);
protected abstract Collection<MessageChannel> determineTargetChannels(Message<?> message);
@Override
protected void handleMessageInternal(Message<?> message) {
@@ -228,103 +142,12 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
if (!sent) {
if (this.defaultOutputChannel != null) {
this.messagingTemplate.send(this.defaultOutputChannel, message);
} else {
}
else {
throw new MessageDeliveryException(message,
"no channel resolved by router and no default output channel defined");
}
}
}
private Collection<MessageChannel> determineTargetChannels(Message<?> message) {
Collection<MessageChannel> channels = new ArrayList<MessageChannel>();
Collection<Object> channelsReturned = this.getChannelIdentifiers(message);
addToCollection(channels, channelsReturned, message);
return channels;
}
private MessageChannel resolveChannelForName(String channelName, Message<?> message) {
if (this.channelResolver == null) {
this.onInit();
}
Assert.state(this.channelResolver != null,
"unable to resolve channel names, no ChannelResolver available");
MessageChannel channel = null;
try {
channel = this.channelResolver.resolveChannelName(channelName);
}
catch (ChannelResolutionException e) {
if (this.resolutionRequired) {
throw new MessagingException(message,
"failed to resolve channel name '" + channelName + "'", e);
}
}
if (channel == null && this.resolutionRequired) {
throw new MessagingException(message,
"failed to resolve channel name '" + channelName + "'");
}
return channel;
}
private void addChannelFromString(Collection<MessageChannel> channels, String channelIdentifier, Message<?> message) {
if (channelIdentifier.indexOf(',') != -1) {
for (String name : StringUtils.commaDelimitedListToStringArray(channelIdentifier)) {
addChannelFromString(channels, name, message);
}
return;
}
// if the channelIdentifierMap contains a mapping, we'll use the mapped value
// otherwise, the String-based channelIdentifier itself will be used as the channel name
String channelName = channelIdentifier;
if (!CollectionUtils.isEmpty(channelIdentifierMap) && channelIdentifierMap.containsKey(channelIdentifier)) {
channelName = channelIdentifierMap.get(channelIdentifier);
}
if (this.prefix != null) {
channelName = this.prefix + channelName;
}
if (this.suffix != null) {
channelName = channelName + suffix;
}
MessageChannel channel = resolveChannelForName(channelName, message);
if (channel != null) {
channels.add(channel);
}
}
private void addToCollection(Collection<MessageChannel> channels, Collection<?> channelIndicators, Message<?> message) {
if (channelIndicators == null) {
return;
}
for (Object channelIndicator : channelIndicators) {
if (channelIndicator == null) {
continue;
}
else if (channelIndicator instanceof MessageChannel) {
channels.add((MessageChannel) channelIndicator);
}
else if (channelIndicator instanceof MessageChannel[]) {
channels.addAll(Arrays.asList((MessageChannel[]) channelIndicator));
}
else if (channelIndicator instanceof String) {
addChannelFromString(channels, (String) channelIndicator, message);
}
else if (channelIndicator instanceof String[]) {
for (String indicatorName : (String[]) channelIndicator) {
addChannelFromString(channels, indicatorName, message);
}
}
else if (channelIndicator instanceof Collection) {
addToCollection(channels, (Collection<?>) channelIndicator, message);
}
else if (this.getRequiredConversionService().canConvert(channelIndicator.getClass(), String.class)) {
addChannelFromString(channels,
this.getConversionService().convert(channelIndicator, String.class), message);
}
else {
throw new MessagingException(
"unsupported return type for router [" + channelIndicator.getClass() + "]");
}
}
}
}

View File

@@ -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.
@@ -30,23 +30,23 @@ import org.springframework.integration.MessageChannel;
* @author Mark Fisher
* @author Oleg Zhurakousky
*/
public class ErrorMessageExceptionTypeRouter extends AbstractMessageRouter {
public class ErrorMessageExceptionTypeRouter extends AbstractMappingMessageRouter {
@Override
protected List<Object> getChannelIdentifiers(Message<?> message) {
String channelIdentifier = null;
protected List<Object> getChannelKeys(Message<?> message) {
String mostSpecificCause = null;
Object payload = message.getPayload();
if (payload != null && (payload instanceof Throwable) && this.channelIdentifierMap != null) {
Throwable mostSpecificCause = (Throwable) payload;
while (mostSpecificCause != null) {
String mappedChannelIdentifier = this.channelIdentifierMap.get(mostSpecificCause.getClass().getName());
if (mappedChannelIdentifier != null) {
channelIdentifier = mappedChannelIdentifier;
if (payload instanceof Throwable) {
Throwable cause = (Throwable) payload;
while (cause != null) {
String causeName = cause.getClass().getName();
if (this.getChannelMappings().keySet().contains(causeName)) {
mostSpecificCause = causeName;
}
mostSpecificCause = mostSpecificCause.getCause();
cause = cause.getCause();
}
}
return Collections.singletonList((Object) channelIdentifier);
return Collections.singletonList((Object) mostSpecificCause);
}
}

View File

@@ -30,7 +30,7 @@ import org.springframework.util.StringUtils;
* @author Mark Fisher
* @since 1.0.3
*/
public class HeaderValueRouter extends AbstractMessageRouter {
public class HeaderValueRouter extends AbstractMappingMessageRouter {
private final String headerName;
@@ -43,7 +43,7 @@ public class HeaderValueRouter extends AbstractMessageRouter {
}
@Override
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
Object value = message.getHeaders().get(this.headerName);
if (value instanceof String && ((String) value).indexOf(',') != -1) {
value = StringUtils.tokenizeToStringArray((String) value, ",", true, true);

View File

@@ -31,7 +31,7 @@ import org.springframework.util.CollectionUtils;
* @author Mark Fisher
* @author Oleg Zhurakousky
*/
public class PayloadTypeRouter extends AbstractMessageRouter {
public class PayloadTypeRouter extends AbstractMappingMessageRouter {
private static final String ARRAY_SUFFIX = "[]";
@@ -45,13 +45,8 @@ public class PayloadTypeRouter extends AbstractMessageRouter {
* preferring direct interface over indirect subclass
*/
@Override
protected List<Object> getChannelIdentifiers(Message<?> message) {
String channelName = this.getChannelName(message);
return (channelName != null) ? Collections.<Object>singletonList(channelName) : null;
}
private String getChannelName(Message<?> message) {
if (CollectionUtils.isEmpty(this.channelIdentifierMap)) {
protected List<Object> getChannelKeys(Message<?> message) {
if (CollectionUtils.isEmpty(this.getChannelMappings())) {
return null;
}
Class<?> type = message.getPayload().getClass();
@@ -59,13 +54,15 @@ public class PayloadTypeRouter extends AbstractMessageRouter {
if (isArray) {
type = type.getComponentType();
}
return this.findClosestMatch(type, isArray);
String closestMatch = this.findClosestMatch(type, isArray);
return (closestMatch != null) ? Collections.<Object>singletonList(closestMatch) : null;
}
private String findClosestMatch(Class<?> type, boolean isArray) {
int minTypeDiffWeight = Integer.MAX_VALUE;
List<String> matches = new ArrayList<String>();
for (String candidate : this.channelIdentifierMap.keySet()) {
for (String candidate : this.getChannelMappings().keySet()) {
if (isArray) {
if (!candidate.endsWith(ARRAY_SUFFIX)) {
continue;
@@ -96,7 +93,7 @@ public class PayloadTypeRouter extends AbstractMessageRouter {
return null;
}
// we have a winner
return this.channelIdentifierMap.get(matches.get(0));
return matches.get(0);
}
private int determineTypeDifferenceWeight(String candidate, Class<?> type, int level) {

View File

@@ -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.
@@ -17,6 +17,7 @@
package org.springframework.integration.router;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.InitializingBean;
@@ -39,7 +40,7 @@ import org.springframework.util.Assert;
* the values can be provided via the {@link #setRecipients(List)} method.
* <p/>
* For more advanced, programmatic control of dynamic recipient lists, consider
* using the @Router annotation or extending {@link AbstractMessageRouter} instead.
* using the @Router annotation or extending {@link AbstractMappingMessageRouter} instead.
* <p/>
* Contrary to a standard &lt;router .../&gt; this handler will try to send to
* all channels that are configured as recipients. It is to channels what a
@@ -90,8 +91,8 @@ public class RecipientListRouter extends AbstractMessageRouter implements Initia
}
@Override
protected List<Object> getChannelIdentifiers(Message<?> message) {
List<Object> channels = new ArrayList<Object>();
protected Collection<MessageChannel> determineTargetChannels(Message<?> message) {
List<MessageChannel> channels = new ArrayList<MessageChannel>();
List<Recipient> recipientList = this.recipients;
for (Recipient recipient : recipientList) {
if (recipient.accept(message)) {

View File

@@ -2115,22 +2115,6 @@ endpoint itself is a Polling Consumer for a channel with a queue.
</xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="channel-resolver" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Provides a reference to a ChannelResolver that resolves
the return value to the name of a MessageChannel
within the application context. If none is provided,
the return value is expected to match a channel name
exactly.
]]></xsd:documentation>
<xsd:appinfo>
<tool:annotation kind="ref">
<tool:expected-type type="org.springframework.integration.core.ChannelResolver" />
</tool:annotation>
</xsd:appinfo>
</xsd:annotation>
</xsd:attribute>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>

View File

@@ -19,7 +19,7 @@
<bean id="payloadTypeRouter" class="org.springframework.integration.router.PayloadTypeRouter">
<property name="resolutionRequired" value="true"/>
<property name="channelIdentifierMap">
<property name="channelMappings">
<map>
<entry key="java.lang.String" value="strings"/>
</map>

View File

@@ -29,7 +29,7 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.router.AbstractMessageRouter;
import org.springframework.integration.router.AbstractMappingMessageRouter;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -50,7 +50,7 @@ public class RouterFactoryBeanDelegationTests {
private PollableChannel discard;
@Autowired @Qualifier("org.springframework.integration.config.RouterFactoryBean#0")
private AbstractMessageRouter router;
private AbstractMappingMessageRouter router;
@Test

View File

@@ -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.
@@ -72,7 +72,7 @@ public class ErrorMessageExceptionTypeRouterTests {
exceptionTypeChannelMap.put(IllegalArgumentException.class.getName(), "illegalArgumentChannel");
exceptionTypeChannelMap.put(RuntimeException.class.getName(), "runtimeExceptionChannel");
exceptionTypeChannelMap.put(MessageHandlingException.class.getName(), "messageHandlingExceptionChannel");
router.setChannelIdentifierMap(exceptionTypeChannelMap);
router.setChannelMappings(exceptionTypeChannelMap);
router.setBeanFactory(beanFactory);
@@ -95,7 +95,7 @@ public class ErrorMessageExceptionTypeRouterTests {
Map<String, String> exceptionTypeChannelMap = new HashMap<String, String>();
exceptionTypeChannelMap.put(RuntimeException.class.getName(), "runtimeExceptionChannel");
exceptionTypeChannelMap.put(MessageHandlingException.class.getName(), "runtimeExceptionChannel");
router.setChannelIdentifierMap(exceptionTypeChannelMap);
router.setChannelMappings(exceptionTypeChannelMap);
router.setBeanFactory(beanFactory);
router.setDefaultOutputChannel(defaultChannel);
@@ -116,7 +116,7 @@ public class ErrorMessageExceptionTypeRouterTests {
ErrorMessageExceptionTypeRouter router = new ErrorMessageExceptionTypeRouter();
Map<String, String> exceptionTypeChannelMap = new HashMap<String, String>();
exceptionTypeChannelMap.put(MessageHandlingException.class.getName(), "messageHandlingExceptionChannel");
router.setChannelIdentifierMap(exceptionTypeChannelMap);
router.setChannelMappings(exceptionTypeChannelMap);
router.setBeanFactory(beanFactory);
router.setDefaultOutputChannel(defaultChannel);
router.handleMessage(message);
@@ -152,7 +152,7 @@ public class ErrorMessageExceptionTypeRouterTests {
ErrorMessageExceptionTypeRouter router = new ErrorMessageExceptionTypeRouter();
Map<String, String> exceptionTypeChannelMap = new HashMap<String, String>();
exceptionTypeChannelMap.put(MessageDeliveryException.class.getName(), "messageDeliveryExceptionChannel");
router.setChannelIdentifierMap(exceptionTypeChannelMap);
router.setChannelMappings(exceptionTypeChannelMap);
router.setBeanFactory(beanFactory);
router.setResolutionRequired(true);
router.handleMessage(message);
@@ -170,7 +170,7 @@ public class ErrorMessageExceptionTypeRouterTests {
exceptionTypeChannelMap.put(IllegalArgumentException.class.getName(), "illegalArgumentChannel");
exceptionTypeChannelMap.put(RuntimeException.class.getName(), "runtimeExceptionChannel");
exceptionTypeChannelMap.put(MessageHandlingException.class.getName(), "messageHandlingExceptionChannel");
router.setChannelIdentifierMap(exceptionTypeChannelMap);
router.setChannelMappings(exceptionTypeChannelMap);
router.setBeanFactory(beanFactory);
router.setDefaultOutputChannel(defaultChannel);
router.handleMessage(message);
@@ -191,7 +191,7 @@ public class ErrorMessageExceptionTypeRouterTests {
Map<String, String> exceptionTypeChannelMap = new HashMap<String, String>();
exceptionTypeChannelMap.put(IllegalArgumentException.class.getName(), "illegalArgumentChannel");
exceptionTypeChannelMap.put(MessageHandlingException.class.getName(), "messageHandlingExceptionChannel");
router.setChannelIdentifierMap(exceptionTypeChannelMap);
router.setChannelMappings(exceptionTypeChannelMap);
router.setBeanFactory(beanFactory);
router.setDefaultOutputChannel(defaultChannel);
router.handleMessage(message);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 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.
@@ -90,12 +90,12 @@ public class HeaderValueRouterTests {
@SuppressWarnings({ "unchecked", "rawtypes" })
public void resolveChannelNameFromMap() {
StaticApplicationContext context = new StaticApplicationContext();
ManagedMap channelMap = new ManagedMap();
channelMap.put("testKey", "testChannel");
ManagedMap channelMappings = new ManagedMap();
channelMappings.put("testKey", "testChannel");
RootBeanDefinition routerBeanDefinition = new RootBeanDefinition(HeaderValueRouter.class);
routerBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue("testHeaderName");
routerBeanDefinition.getPropertyValues().addPropertyValue("resolutionRequired", "true");
routerBeanDefinition.getPropertyValues().addPropertyValue("channelIdentifierMap", channelMap);
routerBeanDefinition.getPropertyValues().addPropertyValue("channelMappings", channelMappings);
routerBeanDefinition.getPropertyValues().addPropertyValue("beanFactory", context);
context.registerBeanDefinition("router", routerBeanDefinition);
context.registerBeanDefinition("testChannel", new RootBeanDefinition(QueueChannel.class));
@@ -112,12 +112,12 @@ public class HeaderValueRouterTests {
@SuppressWarnings({ "unchecked", "rawtypes" })
public void resolveChannelNameFromMapAndCustomeResolver() {
final StaticApplicationContext context = new StaticApplicationContext();
ManagedMap channelMap = new ManagedMap();
channelMap.put("testKey", "testChannel");
ManagedMap channelMappings = new ManagedMap();
channelMappings.put("testKey", "testChannel");
RootBeanDefinition routerBeanDefinition = new RootBeanDefinition(HeaderValueRouter.class);
routerBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue("testHeaderName");
routerBeanDefinition.getPropertyValues().addPropertyValue("resolutionRequired", "true");
routerBeanDefinition.getPropertyValues().addPropertyValue("channelIdentifierMap", channelMap);
routerBeanDefinition.getPropertyValues().addPropertyValue("channelMappings", channelMappings);
routerBeanDefinition.getPropertyValues().addPropertyValue("beanFactory", context);
routerBeanDefinition.getPropertyValues().addPropertyValue("channelResolver", new ChannelResolver() {
public MessageChannel resolveChannelName(String channelName) {

View File

@@ -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.
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.mock;
import java.util.List;
import org.junit.Test;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.integration.Message;
import org.springframework.integration.MessagingException;
@@ -38,9 +39,9 @@ public class MultiChannelRouterTests {
@Test
public void routeWithChannelMapping() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
public List<Object> getChannelIdentifiers(Message<?> message) {
public List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new String[] {"channel1", "channel2"});
}
};
@@ -62,9 +63,9 @@ public class MultiChannelRouterTests {
@Test(expected = MessagingException.class)
public void channelNameLookupFailure() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
public List<Object> getChannelIdentifiers(Message<?> message) {
public List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new String[] {"noSuchChannel"} );
}
};
@@ -76,9 +77,9 @@ public class MultiChannelRouterTests {
@Test(expected = MessagingException.class)
public void channelMappingNotAvailable() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
public List<Object> getChannelIdentifiers(Message<?> message) {
public List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new String[] {"noSuchChannel"});
}
};

View File

@@ -51,22 +51,32 @@ public class PayloadTypeRouterTests {
payloadTypeChannelMap.put(String.class.getName(), "stringChannel");
payloadTypeChannelMap.put(Integer.class.getName(), "integerChannel");
PayloadTypeRouter router = new PayloadTypeRouter();
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setBeanFactory(beanFactory);
Message<String> message1 = new GenericMessage<String>("test");
Message<Integer> message2 = new GenericMessage<Integer>(123);
assertEquals(1, router.getChannelIdentifiers(message1).size());
assertEquals("stringChannel", router.getChannelIdentifiers(message1).iterator().next());
assertEquals(1, router.getChannelIdentifiers(message2).size());
assertEquals("integerChannel", router.getChannelIdentifiers(message2).iterator().next());
assertEquals(1, router.getChannelKeys(message1).size());
assertNull(stringChannel.receive(0));
router.handleMessage(message1);
assertEquals(message1, stringChannel.receive(0));
assertEquals(1, router.getChannelKeys(message2).size());
assertNull(integerChannel.receive(0));
router.handleMessage(message2);
assertEquals(message2, integerChannel.receive(0));
// validate dynamics
QueueChannel newChannel = new QueueChannel();
beanFactory.registerSingleton("newChannel", newChannel);
router.setChannelMapping(String.class.getName(), "newChannel");
assertEquals(1, router.getChannelIdentifiers(message1).size());
assertEquals("newChannel", router.getChannelIdentifiers(message1).iterator().next());
assertEquals(1, router.getChannelKeys(message1).size());
assertNull(newChannel.receive(0));
router.handleMessage(message1);
assertEquals(message1, newChannel.receive(0));
// validate exception is thrown if mappings were removed and
// channelResolutionRequires = true (which is the default)
@@ -98,7 +108,7 @@ public class PayloadTypeRouterTests {
Map<String, String> payloadTypeChannelMap = new ConcurrentHashMap<String, String>();
payloadTypeChannelMap.put(Number.class.getName(), "numberChannel");
PayloadTypeRouter router = new PayloadTypeRouter();
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setBeanFactory(beanFactory);
router.setDefaultOutputChannel(defaultChannel);
Message<Integer> message = new GenericMessage<Integer>(99);
@@ -112,7 +122,7 @@ public class PayloadTypeRouterTests {
QueueChannel newChannel = new QueueChannel();
beanFactory.registerSingleton("newChannel", newChannel);
router.setChannelMapping(Integer.class.getName(), "newChannel");
assertEquals(1, router.getChannelIdentifiers(message).size());
assertEquals(1, router.getChannelKeys(message).size());
router.handleMessage(message);
result = newChannel.receive(10);
assertNotNull(result);
@@ -138,7 +148,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<Integer> message = new GenericMessage<Integer>(99);
@@ -166,7 +176,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<Integer> message = new GenericMessage<Integer>(99);
@@ -193,7 +203,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<C1> message = new GenericMessage<C1>(new C1());
@@ -224,7 +234,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<C1> message = new GenericMessage<C1>(new C1());
@@ -255,7 +265,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<C1> message = new GenericMessage<C1>(new C1());
@@ -286,7 +296,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<C1> message = new GenericMessage<C1>(new C1());
@@ -315,7 +325,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<Integer> message = new GenericMessage<Integer>(99);
@@ -330,7 +340,7 @@ public class PayloadTypeRouterTests {
QueueChannel newChannel = new QueueChannel();
beanFactory.registerSingleton("newChannel", newChannel);
router.setChannelMapping(Integer.class.getName(), "newChannel");
assertEquals(1, router.getChannelIdentifiers(message).size());
assertEquals(1, router.getChannelKeys(message).size());
router.handleMessage(message);
result = newChannel.receive(10);
assertNotNull(result);
@@ -356,7 +366,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<String> message = new GenericMessage<String>("test");
@@ -383,7 +393,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<Integer> message = new GenericMessage<Integer>(99);
@@ -412,7 +422,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
Message<String> message1 = new GenericMessage<String>("test");
Message<Integer> message2 = new GenericMessage<Integer>(123);
@@ -440,7 +450,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<String> message1 = new GenericMessage<String>("test");
@@ -481,7 +491,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<C1> message = new GenericMessage<C1>(new C1());
@@ -515,7 +525,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<C1> message = new GenericMessage<C1>(new C1());
@@ -548,7 +558,7 @@ public class PayloadTypeRouterTests {
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setChannelMappings(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<C1> message = new GenericMessage<C1>(new C1());

View File

@@ -44,9 +44,9 @@ public class RouterTests {
@Test(expected = MessageDeliveryException.class)
public void nullChannelRaisesMessageDeliveryExceptionByDefault() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@Override
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return null;
}
};
@@ -56,9 +56,9 @@ public class RouterTests {
@Test(expected = MessageDeliveryException.class)
public void nullChannelIdentifierUsingChannelResolverRaisesMessageDeliveryExceptionByDefault() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@Override
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return null;
}
};
@@ -70,9 +70,9 @@ public class RouterTests {
@Test(expected = MessageDeliveryException.class)
public void nullChannelIdentifierInListRaisesMessageDeliveryExceptionByDefault() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@Override
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return Collections.singletonList(null);
}
};
@@ -84,8 +84,8 @@ public class RouterTests {
@Test(expected = MessageDeliveryException.class)
public void emptyChannelNameArrayRaisesMessageDeliveryExceptionByDefault() {
AbstractMessageRouter router = new AbstractMessageRouter() {
protected List<Object> getChannelIdentifiers(Message<?> message) {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
protected List<Object> getChannelKeys(Message<?> message) {
return new ArrayList<Object>();
}
};
@@ -97,9 +97,9 @@ public class RouterTests {
@Test(expected = MessagingException.class)
public void channelMappingIsRequiredWhenResolvingChannelNames() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message){
protected List<Object> getChannelKeys(Message<?> message){
return CollectionUtils.arrayToList(new String[] { "notImportant" });
}
};
@@ -109,9 +109,9 @@ public class RouterTests {
@Test
public void beanFactoryWithRouter() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new String[] { "testChannel" });
}
};
@@ -126,9 +126,9 @@ public class RouterTests {
@Test
public void beanFactoryWithRouterAndMultipleCommaSeparatedChannelNames() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new String[] { "testChannel1,testChannel2" });
}
};
@@ -154,9 +154,9 @@ public class RouterTests {
@Test(expected = MessagingException.class)
public void channelResolutionIsRequiredByDefault() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new String[] { "testChannelDoesNotExist", "testChannel" });
}
};
@@ -172,9 +172,9 @@ public class RouterTests {
@Test
public void unresolvableChannelIdentifierInListAreIgnoredWhenResolutionRequiredIsFalse() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new String[] { "testChannelDoesNotExist", "testChannel" });
}
};
@@ -193,9 +193,9 @@ public class RouterTests {
@Test
public void beanFactoryWithRouterAndChannelPrefix() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new String[] { "MyChannel" });
}
};
@@ -214,9 +214,9 @@ public class RouterTests {
@Test(expected = MessagingException.class)
public void beanFactoryWithRouterAndChannelPrefixFailing() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new String[] { "testing_MyChannel" });
}
};
@@ -233,9 +233,9 @@ public class RouterTests {
@Test
public void beanFactoryWithRouterAndChannelSuffix() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new String[] { "MyChannel" });
}
};
@@ -253,9 +253,9 @@ public class RouterTests {
@Test(expected = MessagingException.class)
public void beanFactoryWithRouterAndChannelSuffixFailing() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new String[] { "MyChannel_withSuffix" });
}
};
@@ -272,9 +272,9 @@ public class RouterTests {
@Test
public void beanFactoryWithRouterAndChannelIdentifiersInListWithinAList() {
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
List<String> channelNames1 = CollectionUtils.arrayToList(new String[] { "channel1" });
List<String> channelNames2 = CollectionUtils.arrayToList(new String[] { "channel2" });
@@ -312,9 +312,9 @@ public class RouterTests {
final QueueChannel testChannel1 = new QueueChannel();
final QueueChannel testChannel2 = new QueueChannel();
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
MessageChannel[] channelNames1 = new MessageChannel[] { testChannel1 };
MessageChannel[] channelNames2 = new MessageChannel[] { testChannel2 };
@@ -349,9 +349,9 @@ public class RouterTests {
final QueueChannel testChannel1 = new QueueChannel();
final QueueChannel testChannel2 = new QueueChannel();
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new Integer[] { 100, 200 });
}
};
@@ -375,6 +375,7 @@ public class RouterTests {
String channel = "channel1";
@SuppressWarnings("unused")
public String getChannel() {
return this.channel;
}
@@ -386,9 +387,9 @@ public class RouterTests {
final QueueChannel testChannel1 = new QueueChannel();
AbstractMessageRouter router = new AbstractMessageRouter() {
AbstractMappingMessageRouter router = new AbstractMappingMessageRouter() {
@SuppressWarnings("unchecked")
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return CollectionUtils.arrayToList(new CustomObjectWithChannelName[] { new CustomObjectWithChannelName() });
}
};

View File

@@ -19,7 +19,6 @@ package org.springframework.integration.router.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
@@ -29,6 +28,7 @@ import java.util.List;
import org.junit.Test;
import org.mockito.Mockito;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.Message;
@@ -41,7 +41,7 @@ import org.springframework.integration.core.MessagingTemplate;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.core.SubscribableChannel;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.router.AbstractMessageRouter;
import org.springframework.integration.router.AbstractMappingMessageRouter;
import org.springframework.integration.router.MethodInvokingRouter;
import org.springframework.integration.support.channel.ChannelResolver;
import org.springframework.integration.test.util.TestUtils;
@@ -142,18 +142,6 @@ public class RouterParserTests {
assertEquals(new Long(1234), timeout);
}
@Test
public void channelResolverConfigured() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
"routerParserTests.xml", this.getClass());
Object channelResolverBean = context.getBean("testChannelResolver");
Object endpoint = context.getBean("routerWithChannelResolver");
MethodInvokingRouter router = TestUtils.getPropertyValue(endpoint, "handler", MethodInvokingRouter.class);
ChannelResolver channelResolver = (ChannelResolver)
new DirectFieldAccessor(router).getPropertyValue("channelResolver");
assertSame(channelResolverBean, channelResolver);
}
@Test
public void sequence() {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
@@ -196,7 +184,7 @@ public class RouterParserTests {
}
}
public static class TestRouterImplementation extends AbstractMessageRouter {
public static class TestRouterImplementation extends AbstractMappingMessageRouter {
private final MessageChannel channel;
@@ -206,7 +194,7 @@ public class RouterParserTests {
@Override
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
return Collections.singletonList((Object)this.channel);
}
}

View File

@@ -28,7 +28,7 @@ import org.springframework.integration.Message;
import org.springframework.integration.MessageChannel;
import org.springframework.integration.config.ConsumerEndpointFactoryBean;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.router.AbstractMessageRouter;
import org.springframework.integration.router.AbstractMappingMessageRouter;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
@@ -87,7 +87,7 @@ public class RouterWithMappingTests {
assertNull(fooChannelForExpression.receive(0));
assertNull(barChannelForExpression.receive(0));
// validate dynamics
AbstractMessageRouter router = (AbstractMessageRouter) TestUtils.getPropertyValue(spelRouter, "handler");
AbstractMappingMessageRouter router = (AbstractMappingMessageRouter) TestUtils.getPropertyValue(spelRouter, "handler");
router.setChannelMapping("baz", "fooChannelForExpression");
expressionRouter.send(message3);
assertNull(defaultChannelForExpression.receive(10));

View File

@@ -80,10 +80,6 @@
<channel id="timeoutRouterChannel"/>
<router id="routerWithTimeout" ref="payloadAsChannelNameRouter" timeout="1234" input-channel="timeoutRouterChannel"/>
<channel id="channelResolverRouterChannel"/>
<router id="routerWithChannelResolver" input-channel="channelResolverRouterChannel"
ref="payloadAsChannelNameRouter" channel-resolver="testChannelResolver"/>
<beans:bean id="testChannelResolver"
class="org.springframework.integration.router.config.RouterParserTests$TestChannelResover"/>

View File

@@ -24,6 +24,7 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.xml.AbstractRouterParser;
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
import org.springframework.integration.xml.router.XPathRouter;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -36,15 +37,13 @@ import org.springframework.util.StringUtils;
*/
public class XPathRouterParser extends AbstractRouterParser {
private XPathExpressionParser xpathParser = new XPathExpressionParser();
private final XPathExpressionParser xpathParser = new XPathExpressionParser();
@Override
protected BeanDefinition doParseRouter(Element element, ParserContext parserContext) {
BeanDefinitionBuilder xpathRouterBuilder = BeanDefinitionBuilder.genericBeanDefinition(
"org.springframework.integration.xml.router.XPathRouter");
NodeList xPathExpressionNodes = element.getElementsByTagNameNS(
element.getNamespaceURI(), "xpath-expression");
BeanDefinitionBuilder xpathRouterBuilder = BeanDefinitionBuilder.genericBeanDefinition(XPathRouter.class);
NodeList xPathExpressionNodes = element.getElementsByTagNameNS(element.getNamespaceURI(), "xpath-expression");
Assert.isTrue(xPathExpressionNodes.getLength() <= 1, "At most one xpath-expression child may be specified.");
String xPathExpressionRef = element.getAttribute("xpath-expression-ref");
IntegrationNamespaceUtils.setValueIfAttributeDefined(xpathRouterBuilder, element, "evaluate-as-string");
@@ -53,8 +52,7 @@ public class XPathRouterParser extends AbstractRouterParser {
Assert.isTrue(xPathExpressionChildPresent ^ xPathReferencePresent,
"Exactly one of 'xpath-expression' or 'xpath-expression-ref' is required.");
if (xPathExpressionChildPresent) {
BeanDefinition beanDefinition = this.xpathParser.parse(
(Element) xPathExpressionNodes.item(0), parserContext);
BeanDefinition beanDefinition = this.xpathParser.parse((Element) xPathExpressionNodes.item(0), parserContext);
xpathRouterBuilder.addConstructorArgValue(beanDefinition);
}
else {

View File

@@ -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.
@@ -22,7 +22,7 @@ import java.util.List;
import java.util.Map;
import org.springframework.integration.Message;
import org.springframework.integration.router.AbstractMessageRouter;
import org.springframework.integration.router.AbstractMappingMessageRouter;
import org.springframework.integration.xml.DefaultXmlPayloadConverter;
import org.springframework.integration.xml.XmlPayloadConverter;
import org.springframework.util.Assert;
@@ -38,7 +38,7 @@ import org.w3c.dom.Node;
* @author Jonas Partner
* @author Oleg Zhurakousky
*/
public class XPathRouter extends AbstractMessageRouter {
public class XPathRouter extends AbstractMappingMessageRouter {
private volatile NodeMapper<Object> nodeMapper = new TextContentNodeMapper();
@@ -113,10 +113,10 @@ public class XPathRouter extends AbstractMessageRouter {
}
@Override
protected List<Object> getChannelIdentifiers(Message<?> message) {
protected List<Object> getChannelKeys(Message<?> message) {
Node node = this.converter.convertToNode(message.getPayload());
if (this.evaluateAsString){
return Collections.singletonList((Object)this.xPathExpression.evaluateAsString(node));
if (this.evaluateAsString) {
return Collections.singletonList((Object) this.xPathExpression.evaluateAsString(node));
}
else {
return this.xPathExpression.evaluate(node, this.nodeMapper);

View File

@@ -37,7 +37,7 @@ import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.core.PollableChannel;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.router.AbstractMessageRouter;
import org.springframework.integration.router.AbstractMappingMessageRouter;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.integration.xml.DefaultXmlPayloadConverter;
@@ -181,7 +181,7 @@ public class XPathRouterParserTests {
assertNull(channelB.receive(10));
EventDrivenConsumer routerEndpoint = ac.getBean("xpathRouterEmpty", EventDrivenConsumer.class);
AbstractMessageRouter xpathRouter = (AbstractMessageRouter) TestUtils.getPropertyValue(routerEndpoint, "handler");
AbstractMappingMessageRouter xpathRouter = (AbstractMappingMessageRouter) TestUtils.getPropertyValue(routerEndpoint, "handler");
xpathRouter.setChannelMapping("channelA", "channelB");
inputChannel.send(docMessage);
assertNotNull(channelB.receive(10));
@@ -201,7 +201,7 @@ public class XPathRouterParserTests {
assertNotNull(channelB.receive(10));
EventDrivenConsumer routerEndpoint = ac.getBean("xpathRouterWithMapping", EventDrivenConsumer.class);
AbstractMessageRouter xpathRouter = (AbstractMessageRouter) TestUtils.getPropertyValue(routerEndpoint, "handler");
AbstractMappingMessageRouter xpathRouter = (AbstractMappingMessageRouter) TestUtils.getPropertyValue(routerEndpoint, "handler");
xpathRouter.removeChannelMapping("channelA");
inputChannel.send(docMessage);
assertNotNull(channelA.receive(10));
@@ -223,7 +223,7 @@ public class XPathRouterParserTests {
assertNull(channelB.receive(10));
EventDrivenConsumer routerEndpoint = ac.getBean("xpathRouterWithMappingMultiChannel", EventDrivenConsumer.class);
AbstractMessageRouter xpathRouter = (AbstractMessageRouter) TestUtils.getPropertyValue(routerEndpoint, "handler");
AbstractMappingMessageRouter xpathRouter = (AbstractMappingMessageRouter) TestUtils.getPropertyValue(routerEndpoint, "handler");
xpathRouter.removeChannelMapping("channelA");
xpathRouter.removeChannelMapping("channelB");
inputChannel.send(docMessage);

View File

@@ -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.
@@ -41,7 +41,7 @@ public class XPathRouterTests {
Document doc = XmlTestUtil.getDocumentForString("<doc type=\"one\" />");
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathRouter router = new XPathRouter(expression);
Object[] channelNames = router.getChannelIdentifiers(new GenericMessage(doc)).toArray();
Object[] channelNames = router.getChannelKeys(new GenericMessage(doc)).toArray();
assertEquals("Wrong number of channels returned", 1, channelNames.length);
assertEquals("Wrong channel name", "one", channelNames[0]);
}
@@ -53,7 +53,7 @@ public class XPathRouterTests {
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathRouter router = new XPathRouter(expression);
router.setEvaluateAsString(true);
Object[] channelNames = router.getChannelIdentifiers(new GenericMessage(doc)).toArray();
Object[] channelNames = router.getChannelKeys(new GenericMessage(doc)).toArray();
assertEquals("Wrong number of channels returned", 1, channelNames.length);
assertEquals("Wrong channel name", "one", channelNames[0]);
}
@@ -65,7 +65,7 @@ public class XPathRouterTests {
XPathExpression expression = XPathExpressionFactory.createXPathExpression("name(./node())");
XPathRouter router = new XPathRouter(expression);
router.setEvaluateAsString(true);
Object[] channelNames = router.getChannelIdentifiers(new GenericMessage(doc)).toArray();
Object[] channelNames = router.getChannelKeys(new GenericMessage(doc)).toArray();
assertEquals("Wrong number of channels returned", 1, channelNames.length);
assertEquals("Wrong channel name", "doc", channelNames[0]);
}
@@ -76,7 +76,7 @@ public class XPathRouterTests {
Document doc = XmlTestUtil.getDocumentForString("<doc type=\"one\"><book>bOne</book><book>bTwo</book></doc>");
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/book");
XPathRouter router = new XPathRouter(expression);
Object[] channelNames = router.getChannelIdentifiers(new GenericMessage(doc)).toArray();
Object[] channelNames = router.getChannelKeys(new GenericMessage(doc)).toArray();
assertEquals("Wrong number of channels returned", 2, channelNames.length);
assertEquals("Wrong channel name", "bOne", channelNames[0]);
assertEquals("Wrong channel name", "bTwo", channelNames[1]);
@@ -96,7 +96,7 @@ public class XPathRouterTests {
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/book");
XPathRouter router = new XPathRouter(expression);
router.setEvaluateAsString(true);
Object[] channelNames = router.getChannelIdentifiers(new GenericMessage("<doc type=\"one\"><book>bOne</book><book>bTwo</book></doc>")).toArray();
Object[] channelNames = router.getChannelKeys(new GenericMessage("<doc type=\"one\"><book>bOne</book><book>bTwo</book></doc>")).toArray();
assertEquals("Wrong number of channels returned", 1, channelNames.length);
assertEquals("Wrong channel name", "bOne", channelNames[0]);
}
@@ -105,14 +105,14 @@ public class XPathRouterTests {
public void nonNodePayload() throws Exception {
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathRouter router = new XPathRouter(expression);
router.getChannelIdentifiers(new GenericMessage<String>("test"));
router.getChannelKeys(new GenericMessage<String>("test"));
}
@Test
public void nodePayload() throws Exception {
XPathRouter router = new XPathRouter("./three/text()");
Document testDocument = XmlTestUtil.getDocumentForString("<one><two><three>bob</three><three>dave</three></two></one>");
Object[] channelNames = router.getChannelIdentifiers(new GenericMessage<Node>(testDocument.getElementsByTagName("two").item(0))).toArray();
Object[] channelNames = router.getChannelKeys(new GenericMessage<Node>(testDocument.getElementsByTagName("two").item(0))).toArray();
assertEquals("bob",channelNames[0]);
assertEquals("dave",channelNames[1]);
}
@@ -122,7 +122,7 @@ public class XPathRouterTests {
Document doc = XmlTestUtil.getDocumentForString("<doc type='one' />");
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathRouter router = new XPathRouter(expression);
Object channelName = router.getChannelIdentifiers(new GenericMessage<Document>(doc)).toArray()[0];
Object channelName = router.getChannelKeys(new GenericMessage<Document>(doc)).toArray()[0];
assertEquals("Wrong channel name", "one", channelName);
}
@@ -130,7 +130,7 @@ public class XPathRouterTests {
public void testSimpleStringDoc() throws Exception {
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathRouter router = new XPathRouter(expression);
Object channelName = router.getChannelIdentifiers(new GenericMessage<String>("<doc type='one' />")).toArray()[0];
Object channelName = router.getChannelKeys(new GenericMessage<String>("<doc type='one' />")).toArray()[0];
assertEquals("Wrong channel name", "one", channelName);
}
@@ -138,14 +138,14 @@ public class XPathRouterTests {
public void testNonNodePayload() throws Exception {
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/doc/@type");
XPathRouter router = new XPathRouter(expression);
router.getChannelIdentifiers(new GenericMessage<String>("test"));
router.getChannelKeys(new GenericMessage<String>("test"));
}
@Test
public void testNodePayload() throws Exception {
XPathRouter router = new XPathRouter("./three/text()");
Document testDocument = XmlTestUtil.getDocumentForString("<one><two><three>bob</three></two></one>");
Object[] channelNames = router.getChannelIdentifiers(new GenericMessage<Node>(testDocument
Object[] channelNames = router.getChannelKeys(new GenericMessage<Node>(testDocument
.getElementsByTagName("two").item(0))).toArray();
assertEquals("bob", channelNames[0]);
}
@@ -155,7 +155,7 @@ public class XPathRouterTests {
Document doc = XmlTestUtil.getDocumentForString("<doc type='one' />");
XPathExpression expression = XPathExpressionFactory.createXPathExpression("/somethingelse/@type");
XPathRouter router = new XPathRouter(expression);
List<Object> channelNames = router.getChannelIdentifiers(new GenericMessage<Document>(doc));
List<Object> channelNames = router.getChannelKeys(new GenericMessage<Document>(doc));
assertEquals(0, channelNames.size());
}