Merge pull request #57 from ghillert/INT-2053
Refactor/Standardize Router XSD Schema Attributes
This commit is contained in:
@@ -1,8 +1,242 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<section xmlns="http://docbook.org/ns/docbook" version="5.0" xml:id="router"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>Router</title>
|
||||
|
||||
<title>Routers</title>
|
||||
<section id="router-overview">
|
||||
<title>Overview</title>
|
||||
<para>
|
||||
Routers are a crucial element in many messaging architectures. They consume
|
||||
Messages from a Message Channel and forward each consumed message to one or
|
||||
more different Message Channel depending on a set of conditions.
|
||||
</para>
|
||||
<para>
|
||||
Spring Integration provides the following routers out-of-the-box:
|
||||
</para>
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para><emphasis>(Generic) Router</emphasis></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis>Header Value Router</emphasis></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis>XPath Router (Part of the XML Module)</emphasis></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis>Payload Type Router</emphasis></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis>Recipient List Router</emphasis></para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para><emphasis>Error Message Exception Type Router</emphasis></para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
<para>
|
||||
Router implementations share many configuration parameters. Yet, certain differences
|
||||
exist between routers. Furthermore, the availability of configuration parameters
|
||||
depends on whether Routers are used inside or outside of a chain. In order to
|
||||
provide a quick overview, all available attributes are listed in the 2 tables
|
||||
below.
|
||||
</para>
|
||||
<table><title>Routers Outside a Chain</title>
|
||||
<tgroup cols="7">
|
||||
<colspec colnum="1" colname="col01" colwidth="3*"/>
|
||||
<colspec colnum="2" colname="col02" colwidth="1*" align="center"/>
|
||||
<colspec colnum="3" colname="col03" colwidth="1*" align="center"/>
|
||||
<colspec colnum="4" colname="col04" colwidth="1*" align="center"/>
|
||||
<colspec colnum="5" colname="col05" colwidth="1*" align="center"/>
|
||||
<colspec colnum="6" colname="col06" colwidth="1*" align="center"/>
|
||||
<colspec colnum="7" colname="col07" colwidth="1*" align="center"/>
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Attribute</entry>
|
||||
<entry>router</entry>
|
||||
<entry>header value router</entry>
|
||||
<entry>xpath router</entry>
|
||||
<entry>payload type router</entry>
|
||||
<entry>recipient list router</entry>
|
||||
<entry>exception type router</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>apply-sequence</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>x<entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>default-output-channel</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>resolution-required</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ignore-send-failures</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>timeout</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>id</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>auto-startup</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>input-channel</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>order</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>channel-resolver</entry>
|
||||
<entry>x</entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>method</entry>
|
||||
<entry>x</entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ref</entry>
|
||||
<entry>x</entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>expression</entry>
|
||||
<entry>x</entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>header-name</entry>
|
||||
<entry></entry><entry>x</entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>evaluate-as-string</entry>
|
||||
<entry></entry><entry></entry><entry>x</entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>xpath-expression-ref</entry>
|
||||
<entry></entry><entry></entry><entry>x</entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<table><title>Routers Inside a Chain</title>
|
||||
<tgroup cols="7">
|
||||
<colspec colnum="1" colname="col01" colwidth="3*"/>
|
||||
<colspec colnum="2" colname="col02" colwidth="1*" align="center"/>
|
||||
<colspec colnum="3" colname="col03" colwidth="1*" align="center"/>
|
||||
<colspec colnum="4" colname="col04" colwidth="1*" align="center"/>
|
||||
<colspec colnum="5" colname="col05" colwidth="1*" align="center"/>
|
||||
<colspec colnum="6" colname="col06" colwidth="1*" align="center"/>
|
||||
<colspec colnum="7" colname="col07" colwidth="1*" align="center"/>
|
||||
<thead>
|
||||
<row>
|
||||
<entry>Attribute</entry>
|
||||
<entry>router</entry>
|
||||
<entry>header value router</entry>
|
||||
<entry>xpath router</entry>
|
||||
<entry>payload type router</entry>
|
||||
<entry>recipient list router</entry>
|
||||
<entry>exception type router</entry>
|
||||
</row>
|
||||
</thead>
|
||||
<tbody>
|
||||
<row>
|
||||
<entry>apply-sequence</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>x<entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>default-output-channel</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>resolution-required</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ignore-send-failures</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>timeout</entry>
|
||||
<entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry><entry>x</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>id</entry>
|
||||
<entry></entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>auto-startup</entry>
|
||||
<entry></entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>input-channel</entry>
|
||||
<entry></entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>order</entry>
|
||||
<entry></entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>channel-resolver</entry>
|
||||
<entry>x</entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>method</entry>
|
||||
<entry>x</entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>ref</entry>
|
||||
<entry>x</entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>expression</entry>
|
||||
<entry>x</entry><entry></entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>header-name</entry>
|
||||
<entry></entry><entry>x</entry><entry></entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>evaluate-as-string</entry>
|
||||
<entry></entry><entry></entry><entry>x</entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>xpath-expression-ref</entry>
|
||||
<entry></entry><entry></entry><entry>x</entry><entry></entry><entry></entry><entry></entry>
|
||||
</row>
|
||||
</tbody>
|
||||
</tgroup>
|
||||
</table>
|
||||
<note>
|
||||
Router parameters have been more standardized across all router implementations
|
||||
in Spring Integration 2.1. Consequently, there are a few minor changes that
|
||||
leave the possibility of breaking older Spring Integration based applications.
|
||||
</note>
|
||||
<important>
|
||||
Since Spring Integration 2.1 the "ignore-channel-name-resolution-failures"
|
||||
attribute was removed in favor of consolidating its behavior with the
|
||||
"resolution-required" attribute. Also, the "resolution-required" attribute
|
||||
now defaults to "true".
|
||||
|
||||
Prior to these changes, the "resolution-required" attribute defaulted to false
|
||||
causing messages to be dropped silently when no channel was resolved and
|
||||
no "default-output-channel" was set.
|
||||
|
||||
The new behavior will require at least one resolved channel and by default
|
||||
will throw an Exception if no channel was determined (or an attempt to send
|
||||
was not successful).
|
||||
|
||||
If you do desire to drop messages silently simply set "default-output-channel='nullChannel'".
|
||||
</important>
|
||||
</section>
|
||||
<section id="router-implementations">
|
||||
<title>Router Implementations</title>
|
||||
<para>
|
||||
|
||||
@@ -45,8 +45,6 @@ public class RouterFactoryBean extends AbstractStandardMessageHandlerFactoryBean
|
||||
|
||||
private volatile Boolean resolutionRequired;
|
||||
|
||||
private volatile Boolean ignoreChannelNameResolutionFailures;
|
||||
|
||||
private volatile Boolean applySequence;
|
||||
|
||||
private volatile Boolean ignoreSendFailures;
|
||||
@@ -68,10 +66,6 @@ public class RouterFactoryBean extends AbstractStandardMessageHandlerFactoryBean
|
||||
this.resolutionRequired = resolutionRequired;
|
||||
}
|
||||
|
||||
public void setIgnoreChannelNameResolutionFailures(Boolean ignoreChannelNameResolutionFailures) {
|
||||
this.ignoreChannelNameResolutionFailures = ignoreChannelNameResolutionFailures;
|
||||
}
|
||||
|
||||
public void setApplySequence(Boolean applySequence) {
|
||||
this.applySequence = applySequence;
|
||||
}
|
||||
@@ -128,9 +122,6 @@ public class RouterFactoryBean extends AbstractStandardMessageHandlerFactoryBean
|
||||
if (this.timeout != null) {
|
||||
router.setTimeout(timeout.longValue());
|
||||
}
|
||||
if (this.ignoreChannelNameResolutionFailures != null) {
|
||||
router.setIgnoreChannelNameResolutionFailures(ignoreChannelNameResolutionFailures);
|
||||
}
|
||||
if (this.applySequence != null) {
|
||||
router.setApplySequence(this.applySequence);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -44,7 +44,6 @@ public abstract class AbstractRouterParser extends AbstractConsumerEndpointParse
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "resolution-required");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "apply-sequence");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-send-failures");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-channel-name-resolution-failures");
|
||||
BeanDefinition targetRouterBeanDefinition = this.parseRouter(element, parserContext);
|
||||
builder.addPropertyValue("targetObject", targetRouterBeanDefinition);
|
||||
return builder;
|
||||
|
||||
@@ -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.
|
||||
@@ -78,7 +78,6 @@ public class DefaultRouterParser extends AbstractDelegatingConsumerEndpointParse
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "default-output-channel");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "timeout");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "resolution-required");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-channel-name-resolution-failures");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "apply-sequence");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "ignore-send-failures");
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageDeliveryException;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.channel.NullChannel;
|
||||
import org.springframework.integration.core.MessagingTemplate;
|
||||
import org.springframework.integration.handler.AbstractMessageHandler;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
@@ -47,14 +48,13 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gunnar Hillert
|
||||
*/
|
||||
@ManagedResource
|
||||
public abstract class AbstractMessageRouter extends AbstractMessageHandler {
|
||||
|
||||
private volatile MessageChannel defaultOutputChannel;
|
||||
|
||||
private volatile boolean resolutionRequired;
|
||||
|
||||
private volatile boolean ignoreSendFailures;
|
||||
|
||||
private volatile boolean applySequence;
|
||||
@@ -67,7 +67,7 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
|
||||
|
||||
private volatile ChannelResolver channelResolver;
|
||||
|
||||
private volatile boolean ignoreChannelNameResolutionFailures;
|
||||
private volatile boolean resolutionRequired = true;
|
||||
|
||||
protected volatile Map<String, String> channelIdentifierMap = new ConcurrentHashMap<String, String>();
|
||||
|
||||
@@ -120,9 +120,12 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default channel where Messages should be sent if channel resolution fails to return any channels. If no
|
||||
* default channel is provided, the router will either drop the Message or throw an Exception depending on the value
|
||||
* of {@link #resolutionRequired}.
|
||||
* Set the default channel where Messages should be sent if channel resolution
|
||||
* fails to return any channels. If no default channel is provided and channel
|
||||
* resolution fails to return any channels, the router will throw an
|
||||
* {@link MessageDeliveryException}.
|
||||
*
|
||||
* If messages shall be ignored (dropped) instead, please provide a {@link NullChannel}.
|
||||
*/
|
||||
public void setDefaultOutputChannel(MessageChannel defaultOutputChannel) {
|
||||
this.defaultOutputChannel = defaultOutputChannel;
|
||||
@@ -136,21 +139,12 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
|
||||
this.messagingTemplate.setSendTimeout(timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this router should always be required to resolve at least one channel. The default is 'false'. To
|
||||
* trigger an exception whenever the resolver returns null or an empty channel list, and this endpoint has no
|
||||
* 'defaultOutputChannel' configured, set this value to 'true'.
|
||||
*/
|
||||
public void setResolutionRequired(boolean resolutionRequired) {
|
||||
this.resolutionRequired = resolutionRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 setIgnoreChannelNameResolutionFailures(boolean ignoreChannelNameResolutionFailures) {
|
||||
this.ignoreChannelNameResolutionFailures = ignoreChannelNameResolutionFailures;
|
||||
public void setResolutionRequired(boolean resolutionRequired) {
|
||||
this.resolutionRequired = resolutionRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,8 +228,7 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
|
||||
if (!sent) {
|
||||
if (this.defaultOutputChannel != null) {
|
||||
this.messagingTemplate.send(this.defaultOutputChannel, message);
|
||||
}
|
||||
else if (this.resolutionRequired) {
|
||||
} else {
|
||||
throw new MessageDeliveryException(message,
|
||||
"no channel resolved by router and no default output channel defined");
|
||||
}
|
||||
@@ -260,12 +253,12 @@ public abstract class AbstractMessageRouter extends AbstractMessageHandler {
|
||||
channel = this.channelResolver.resolveChannelName(channelName);
|
||||
}
|
||||
catch (ChannelResolutionException e) {
|
||||
if (!this.ignoreChannelNameResolutionFailures) {
|
||||
if (this.resolutionRequired) {
|
||||
throw new MessagingException(message,
|
||||
"failed to resolve channel name '" + channelName + "'", e);
|
||||
}
|
||||
}
|
||||
if (channel == null && !this.ignoreChannelNameResolutionFailures) {
|
||||
if (channel == null && this.resolutionRequired) {
|
||||
throw new MessagingException(message,
|
||||
"failed to resolve channel name '" + channelName + "'");
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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.
|
||||
@@ -19,6 +19,7 @@ package org.springframework.integration.router;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
@@ -28,6 +29,7 @@ import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageDeliveryException;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.annotation.Header;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
@@ -134,7 +136,15 @@ public class MethodInvokingRouterTests {
|
||||
Message<?> result2 = barChannel.receive(0);
|
||||
assertNotNull(result2);
|
||||
assertEquals("bar", result2.getPayload());
|
||||
router.handleMessage(badMessage);
|
||||
|
||||
try {
|
||||
router.handleMessage(badMessage);
|
||||
fail();
|
||||
} catch (MessageDeliveryException e) {
|
||||
/* Success */
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -171,7 +181,14 @@ public class MethodInvokingRouterTests {
|
||||
Message<?> result2 = barChannel.receive(0);
|
||||
assertNotNull(result2);
|
||||
assertEquals("bar", result2.getPayload());
|
||||
router.handleMessage(badMessage);
|
||||
|
||||
try {
|
||||
router.handleMessage(badMessage);
|
||||
fail();
|
||||
} catch (MessageDeliveryException e) {
|
||||
/* Success */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -208,7 +225,14 @@ public class MethodInvokingRouterTests {
|
||||
Message<?> result2 = barChannel.receive(0);
|
||||
assertNotNull(result2);
|
||||
assertEquals("bar", result2.getPayload());
|
||||
router.handleMessage(badMessage);
|
||||
|
||||
try {
|
||||
router.handleMessage(badMessage);
|
||||
fail();
|
||||
} catch (MessageDeliveryException e) {
|
||||
/* Success */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -251,7 +275,13 @@ public class MethodInvokingRouterTests {
|
||||
assertEquals("bar", result2a.getPayload());
|
||||
assertNotNull(result2b);
|
||||
assertEquals("bar", result2b.getPayload());
|
||||
router.handleMessage(badMessage);
|
||||
|
||||
try {
|
||||
router.handleMessage(badMessage);
|
||||
fail();
|
||||
} catch (MessageDeliveryException e) {
|
||||
/* Success */
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -294,7 +324,13 @@ public class MethodInvokingRouterTests {
|
||||
Message<?> result2b = barChannel.receive(0);
|
||||
assertNotNull(result2b);
|
||||
assertEquals("bar", result2b.getPayload());
|
||||
router.handleMessage(badMessage);
|
||||
|
||||
try {
|
||||
router.handleMessage(badMessage);
|
||||
fail();
|
||||
} catch (MessageDeliveryException e) {
|
||||
/* Success */
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -337,7 +373,13 @@ public class MethodInvokingRouterTests {
|
||||
Message<?> result2b = barChannel.receive(0);
|
||||
assertNotNull(result2b);
|
||||
assertEquals("bar", result2b.getPayload());
|
||||
router.handleMessage(badMessage);
|
||||
|
||||
try {
|
||||
router.handleMessage(badMessage);
|
||||
fail();
|
||||
} catch (MessageDeliveryException e) {
|
||||
/* Success */
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -380,7 +422,14 @@ public class MethodInvokingRouterTests {
|
||||
assertEquals("bar", result2a.getPayload());
|
||||
assertNotNull(result2b);
|
||||
assertEquals("bar", result2b.getPayload());
|
||||
router.handleMessage(badMessage);
|
||||
|
||||
try {
|
||||
router.handleMessage(badMessage);
|
||||
fail();
|
||||
} catch (MessageDeliveryException e) {
|
||||
/* Success */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -423,7 +472,14 @@ public class MethodInvokingRouterTests {
|
||||
assertEquals("bar", result2a.getPayload());
|
||||
assertNotNull(result2b);
|
||||
assertEquals("bar", result2b.getPayload());
|
||||
router.handleMessage(badMessage);
|
||||
|
||||
try {
|
||||
router.handleMessage(badMessage);
|
||||
fail();
|
||||
} catch (MessageDeliveryException e) {
|
||||
/* Success */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -466,7 +522,14 @@ public class MethodInvokingRouterTests {
|
||||
assertEquals("bar", result2a.getPayload());
|
||||
assertNotNull(result2b);
|
||||
assertEquals("bar", result2b.getPayload());
|
||||
router.handleMessage(badMessage);
|
||||
|
||||
try {
|
||||
router.handleMessage(badMessage);
|
||||
fail();
|
||||
} catch (MessageDeliveryException e) {
|
||||
/* Success */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -67,14 +67,15 @@ public class PayloadTypeRouterTests {
|
||||
router.setChannelMapping(String.class.getName(), "newChannel");
|
||||
assertEquals(1, router.getChannelIdentifiers(message1).size());
|
||||
assertEquals("newChannel", router.getChannelIdentifiers(message1).iterator().next());
|
||||
|
||||
// validate exception is thrown if mappings were removed and
|
||||
// channelResolutionRequires = true (which is the default)
|
||||
|
||||
// validate nothing happens if mappings were removed and resolutionRequires = false
|
||||
router.removeChannelMapping(String.class.getName());
|
||||
router.removeChannelMapping(Integer.class.getName());
|
||||
router.handleMessage(message1);
|
||||
|
||||
// validate exception is thrown if mappings were removed and resolutionRequires = true
|
||||
|
||||
router.setResolutionRequired(true);
|
||||
|
||||
try {
|
||||
router.handleMessage(message1);
|
||||
fail();
|
||||
|
||||
@@ -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.
|
||||
@@ -27,6 +27,7 @@ import org.junit.Test;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.MessageDeliveryException;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
@@ -37,11 +38,12 @@ import org.springframework.util.CollectionUtils;
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gunnar Hillert
|
||||
*/
|
||||
public class RouterTests {
|
||||
|
||||
@Test
|
||||
public void nullChannelIgnoredByDefault() {
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void nullChannelRaisesMessageDeliveryExceptionByDefault() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@Override
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
@@ -53,45 +55,7 @@ public class RouterTests {
|
||||
}
|
||||
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void nullChannelThrowsExceptionWhenResolutionRequired() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@Override
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
router.setResolutionRequired(true);
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyChannelListIgnoredByDefault() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@Override
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
}
|
||||
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void emptyChannelListThrowsExceptionWhenResolutionRequired() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@Override
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
router.setResolutionRequired(true);
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullChannelIdentifierIgnoredByDefault() {
|
||||
public void nullChannelIdentifierUsingChannelResolverRaisesMessageDeliveryExceptionByDefault() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@Override
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
@@ -104,8 +68,8 @@ public class RouterTests {
|
||||
router.handleMessage(message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullChannelIdentifierInListIgnoredByDefault() {
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void nullChannelIdentifierInListRaisesMessageDeliveryExceptionByDefault() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@Override
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
@@ -119,35 +83,7 @@ public class RouterTests {
|
||||
}
|
||||
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void nullChannelIdentifierTriggersExceptionWhenResolutionRequired() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
TestChannelResolver channelResolver = new TestChannelResolver();
|
||||
router.setChannelResolver(channelResolver);
|
||||
router.setResolutionRequired(true);
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
}
|
||||
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void nullChannelIdentifierInListTriggersExceptionWhenResolutionRequired() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return Collections.singletonList(null);
|
||||
}
|
||||
};
|
||||
TestChannelResolver channelResolver = new TestChannelResolver();
|
||||
router.setChannelResolver(channelResolver);
|
||||
router.setResolutionRequired(true);
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyChannelNameArrayIgnoredByDefault() {
|
||||
public void emptyChannelNameArrayRaisesMessageDeliveryExceptionByDefault() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return new ArrayList<Object>();
|
||||
@@ -159,21 +95,6 @@ public class RouterTests {
|
||||
router.handleMessage(message);
|
||||
}
|
||||
|
||||
@Test(expected = MessageDeliveryException.class)
|
||||
public void emptyChannelNameArrayThrowsExceptionWhenResolutionRequired() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] {});
|
||||
}
|
||||
};
|
||||
TestChannelResolver channelResolver = new TestChannelResolver();
|
||||
router.setChannelResolver(channelResolver);
|
||||
router.setResolutionRequired(true);
|
||||
Message<String> message = new GenericMessage<String>("test");
|
||||
router.handleMessage(message);
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void channelMappingIsRequiredWhenResolvingChannelNames() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@@ -203,4 +124,282 @@ public class RouterTests {
|
||||
assertEquals("test", reply.getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanFactoryWithRouterAndMultipleCommaSeparatedChannelNames() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] { "testChannel1,testChannel2" });
|
||||
}
|
||||
};
|
||||
|
||||
QueueChannel testChannel1 = new QueueChannel();
|
||||
QueueChannel testChannel2 = new QueueChannel();
|
||||
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
|
||||
context.getBeanFactory().registerSingleton("testChannel1", testChannel1);
|
||||
context.getBeanFactory().registerSingleton("testChannel2", testChannel2);
|
||||
|
||||
router.setBeanFactory(context);
|
||||
router.handleMessage(new GenericMessage<String>("test"));
|
||||
|
||||
Message<?> reply1 = testChannel1.receive(0);
|
||||
assertEquals("test", reply1.getPayload());
|
||||
|
||||
Message<?> reply2 = testChannel2.receive(0);
|
||||
assertEquals("test", reply2.getPayload());
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void channelResolutionIsRequiredByDefault() {
|
||||
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] { "testChannelDoesNotExist", "testChannel" });
|
||||
}
|
||||
};
|
||||
|
||||
QueueChannel testChannel = new QueueChannel();
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.getBeanFactory().registerSingleton("testChannel", testChannel);
|
||||
router.setBeanFactory(context);
|
||||
router.handleMessage(new GenericMessage<String>("test"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void unresolvableChannelIdentifierInListAreIgnoredWhenResolutionRequiredIsFalse() {
|
||||
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] { "testChannelDoesNotExist", "testChannel" });
|
||||
}
|
||||
};
|
||||
|
||||
router.setResolutionRequired(false);
|
||||
|
||||
QueueChannel testChannel = new QueueChannel();
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.getBeanFactory().registerSingleton("testChannel", testChannel);
|
||||
router.setBeanFactory(context);
|
||||
router.handleMessage(new GenericMessage<String>("test"));
|
||||
Message<?> reply = testChannel.receive(0);
|
||||
assertEquals("test", reply.getPayload());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanFactoryWithRouterAndChannelPrefix() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] { "MyChannel" });
|
||||
}
|
||||
};
|
||||
|
||||
router.setPrefix("testing_");
|
||||
|
||||
QueueChannel testChannel = new QueueChannel();
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.getBeanFactory().registerSingleton("testing_MyChannel", testChannel);
|
||||
router.setBeanFactory(context);
|
||||
router.handleMessage(new GenericMessage<String>("test"));
|
||||
Message<?> reply = testChannel.receive(0);
|
||||
assertEquals("test", reply.getPayload());
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void beanFactoryWithRouterAndChannelPrefixFailing() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] { "testing_MyChannel" });
|
||||
}
|
||||
};
|
||||
|
||||
router.setPrefix("testing_");
|
||||
|
||||
QueueChannel testChannel = new QueueChannel();
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.getBeanFactory().registerSingleton("testing_MyChannel", testChannel);
|
||||
router.setBeanFactory(context);
|
||||
router.handleMessage(new GenericMessage<String>("test"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanFactoryWithRouterAndChannelSuffix() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] { "MyChannel" });
|
||||
}
|
||||
};
|
||||
|
||||
router.setSuffix("_withSuffix");
|
||||
|
||||
QueueChannel testChannel = new QueueChannel();
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.getBeanFactory().registerSingleton("MyChannel_withSuffix", testChannel);
|
||||
router.setBeanFactory(context);
|
||||
router.handleMessage(new GenericMessage<String>("test"));
|
||||
Message<?> reply = testChannel.receive(0);
|
||||
assertEquals("test", reply.getPayload());
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void beanFactoryWithRouterAndChannelSuffixFailing() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new String[] { "MyChannel_withSuffix" });
|
||||
}
|
||||
};
|
||||
|
||||
router.setSuffix("_withSuffix");
|
||||
|
||||
QueueChannel testChannel = new QueueChannel();
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.getBeanFactory().registerSingleton("MyChannel_withSuffix", testChannel);
|
||||
router.setBeanFactory(context);
|
||||
router.handleMessage(new GenericMessage<String>("test"));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanFactoryWithRouterAndChannelIdentifiersInListWithinAList() {
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
|
||||
List<String> channelNames1 = CollectionUtils.arrayToList(new String[] { "channel1" });
|
||||
List<String> channelNames2 = CollectionUtils.arrayToList(new String[] { "channel2" });
|
||||
|
||||
List<Object> listWithListOfChannelNames = new ArrayList<Object>();
|
||||
|
||||
listWithListOfChannelNames.add(channelNames1);
|
||||
listWithListOfChannelNames.add(channelNames2);
|
||||
|
||||
return listWithListOfChannelNames;
|
||||
}
|
||||
};
|
||||
|
||||
QueueChannel testChannel1 = new QueueChannel();
|
||||
QueueChannel testChannel2 = new QueueChannel();
|
||||
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
|
||||
context.getBeanFactory().registerSingleton("channel1", testChannel1);
|
||||
context.getBeanFactory().registerSingleton("channel2", testChannel2);
|
||||
|
||||
router.setBeanFactory(context);
|
||||
router.handleMessage(new GenericMessage<String>("test"));
|
||||
|
||||
Message<?> reply1 = testChannel1.receive(0);
|
||||
assertEquals("test", reply1.getPayload());
|
||||
|
||||
Message<?> reply2 = testChannel2.receive(0);
|
||||
assertEquals("test", reply2.getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanFactoryWithRouterAndChannelIdentifiersInMessageChannelArrayWithinAList() {
|
||||
|
||||
final QueueChannel testChannel1 = new QueueChannel();
|
||||
final QueueChannel testChannel2 = new QueueChannel();
|
||||
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
|
||||
MessageChannel[] channelNames1 = new MessageChannel[] { testChannel1 };
|
||||
MessageChannel[] channelNames2 = new MessageChannel[] { testChannel2 };
|
||||
|
||||
List<Object> listWithListOfChannelNames = new ArrayList<Object>();
|
||||
|
||||
listWithListOfChannelNames.add(channelNames1);
|
||||
listWithListOfChannelNames.add(channelNames2);
|
||||
|
||||
return listWithListOfChannelNames;
|
||||
}
|
||||
};
|
||||
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
|
||||
context.getBeanFactory().registerSingleton("channel1", testChannel1);
|
||||
context.getBeanFactory().registerSingleton("channel2", testChannel2);
|
||||
|
||||
router.setBeanFactory(context);
|
||||
router.handleMessage(new GenericMessage<String>("test"));
|
||||
|
||||
Message<?> reply1 = testChannel1.receive(0);
|
||||
assertEquals("test", reply1.getPayload());
|
||||
|
||||
Message<?> reply2 = testChannel2.receive(0);
|
||||
assertEquals("test", reply2.getPayload());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void beanFactoryWithRouterAndRetrieveChannelIdentifiersUsingDefaultConversionService() {
|
||||
|
||||
final QueueChannel testChannel1 = new QueueChannel();
|
||||
final QueueChannel testChannel2 = new QueueChannel();
|
||||
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new Integer[] { 100, 200 });
|
||||
}
|
||||
};
|
||||
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
|
||||
context.getBeanFactory().registerSingleton("100", testChannel1);
|
||||
context.getBeanFactory().registerSingleton("200", testChannel2);
|
||||
|
||||
router.setBeanFactory(context);
|
||||
router.handleMessage(new GenericMessage<String>("test"));
|
||||
|
||||
Message<?> reply1 = testChannel1.receive(0);
|
||||
assertEquals("test", reply1.getPayload());
|
||||
|
||||
Message<?> reply2 = testChannel2.receive(0);
|
||||
assertEquals("test", reply2.getPayload());
|
||||
}
|
||||
|
||||
private class CustomObjectWithChannelName {
|
||||
|
||||
String channel = "channel1";
|
||||
|
||||
public String getChannel() {
|
||||
return this.channel;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test(expected = MessagingException.class)
|
||||
public void beanFactoryWithRouterAndRetrieveChannelIdentifierUsingDefaultConversionServiceFailing() {
|
||||
|
||||
final QueueChannel testChannel1 = new QueueChannel();
|
||||
|
||||
AbstractMessageRouter router = new AbstractMessageRouter() {
|
||||
@SuppressWarnings("unchecked")
|
||||
protected List<Object> getChannelIdentifiers(Message<?> message) {
|
||||
return CollectionUtils.arrayToList(new CustomObjectWithChannelName[] { new CustomObjectWithChannelName() });
|
||||
}
|
||||
};
|
||||
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
|
||||
context.getBeanFactory().registerSingleton("channel1", testChannel1);
|
||||
|
||||
router.setBeanFactory(context);
|
||||
router.handleMessage(new GenericMessage<String>("test"));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration-2.0.xsd">
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
|
||||
<int:router input-channel="inputChannel" default-output-channel="errorChannel" ignore-channel-name-resolution-failures="true" >
|
||||
<int:router input-channel="inputChannel" default-output-channel="errorChannel" resolution-required="false">
|
||||
<bean class="org.springframework.integration.router.config.RouterParserTests.NonExistingChannelRouter"/>
|
||||
</int:router>
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -49,6 +49,7 @@ import org.springframework.integration.test.util.TestUtils;
|
||||
/**
|
||||
* @author Mark Fisher
|
||||
* @author Jonas Partner
|
||||
* @author Gunnar Hillert
|
||||
*/
|
||||
public class RouterParserTests {
|
||||
|
||||
@@ -121,12 +122,11 @@ public class RouterParserTests {
|
||||
input.send(new GenericMessage<Integer>(3));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoreChannelNameResolutionFailures() {
|
||||
public void testResolutionRequiredIsTrue() {
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
|
||||
"routerParserTests.xml", this.getClass());
|
||||
context.start();
|
||||
MessageChannel input = (MessageChannel) context.getBean("ignoreChannelNameResolutionFailuresInput");
|
||||
MessageChannel input = (MessageChannel) context.getBean("resolutionRequiredIsTrueInput");
|
||||
input.send(new GenericMessage<String>("channelThatDoesNotExist"));
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ public class RouterParserTests {
|
||||
assertEquals(new Integer(3), message3.getHeaders().getSequenceNumber());
|
||||
assertEquals(new Integer(3), message3.getHeaders().getSequenceSize());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testErrorChannel(){
|
||||
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
|
||||
<router id="spelRouter" input-channel="expressionRouter" expression="payload.name"
|
||||
default-output-channel="defaultChannelForExpression"
|
||||
ignore-channel-name-resolution-failures="true">
|
||||
resolution-required="false">
|
||||
<mapping value="foo" channel="fooChannelForExpression"/>
|
||||
<mapping value="bar" channel="barChannelForExpression"/>
|
||||
</router>
|
||||
@@ -40,7 +40,7 @@
|
||||
|
||||
<router input-channel="pojoRouter" ref="testBean"
|
||||
default-output-channel="defaultChannelForPojo"
|
||||
ignore-channel-name-resolution-failures="true">
|
||||
resolution-required="false">
|
||||
<mapping value="foo" channel="fooChannelForPojo"/>
|
||||
<mapping value="bar" channel="barChannelForPojo"/>
|
||||
</router>
|
||||
|
||||
@@ -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.
|
||||
@@ -69,7 +69,6 @@ public class RouterWithMappingTests {
|
||||
@Autowired
|
||||
private PollableChannel defaultChannelForPojo;
|
||||
|
||||
|
||||
@Test
|
||||
public void expressionRouter() {
|
||||
Message<?> message1 = MessageBuilder.withPayload(new TestBean("foo")).build();
|
||||
@@ -115,7 +114,6 @@ public class RouterWithMappingTests {
|
||||
assertNull(barChannelForPojo.receive(0));
|
||||
}
|
||||
|
||||
|
||||
private static class TestBean {
|
||||
|
||||
private final String name;
|
||||
|
||||
@@ -73,9 +73,9 @@
|
||||
|
||||
<router id="resolutionRequiredRouter" ref="pojo" method="route" input-channel="inputForRouterRequiringResolution" resolution-required="true" />
|
||||
|
||||
<channel id="ignoreChannelNameResolutionFailuresInput"/>
|
||||
<channel id="resolutionRequiredIsTrueInput"/>
|
||||
<beans:bean id="payloadAsChannelNameRouter" class="org.springframework.integration.router.config.RouterParserTests$ReturnStringPassedInAsChannelNameRouter" />
|
||||
<router id="ignoreChannelNameResolutionFailuresRouter" ref="payloadAsChannelNameRouter" input-channel="ignoreChannelNameResolutionFailuresInput" ignore-channel-name-resolution-failures="true" />
|
||||
<router id="resolutionRequiredFalseRouter" ref="payloadAsChannelNameRouter" input-channel="resolutionRequiredIsTrueInput" resolution-required="false" />
|
||||
|
||||
<channel id="timeoutRouterChannel"/>
|
||||
<router id="routerWithTimeout" ref="payloadAsChannelNameRouter" timeout="1234" input-channel="timeoutRouterChannel"/>
|
||||
|
||||
@@ -342,98 +342,109 @@
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="xpath-router">
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an XPath router.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="xpath-expression" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="mapping" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="value" type="xsd:string" />
|
||||
<xsd:attribute name="channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type
|
||||
type="org.springframework.integration.core.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:string"/>
|
||||
<xsd:attribute name="evaluate-as-string" type="xsd:boolean" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
By default XPath expressions are evaluated as NODESET type and then converted
|
||||
to a List of channel names, thus handling single channel scenarios as well as multiple.
|
||||
However certain XPath expressions may evaluate as String type from the very
|
||||
beginning (e.g., 'name(./node())' - which will return the name of the root node) thus resulting in
|
||||
the exception if default evaluation type (NODESET) is used. This flag will allow you to manage the
|
||||
evaluation type. It is TRUE by default, however if set to FALSE, the String evaluation type will be used.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="input-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="xpath-expression-ref" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.xml.xpath.XPathExpression"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="channel-resolver" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.ChannelResolver"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="resolution-required" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify whether this router should always be required to return at least one channel or name.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="ignore-channel-name-resolution-failures" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify whether a failure to resolve a channel name returned by this router should be ignored.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="default-output-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type
|
||||
type="org.springframework.integration.core.MessageChannel" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<!-- XPath Router definition -->
|
||||
|
||||
<xsd:complexType name="commonXPathRouterType" abstract="true">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="integration:abstractRouterType">
|
||||
<xsd:attribute name="evaluate-as-string" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
By default XPath expressions are evaluated as NODESET type and then converted
|
||||
to a List of channel names, thus handling single channel scenarios as well as multiple.
|
||||
However certain XPath expressions may evaluate as String type from the very
|
||||
beginning (e.g., 'name(./node())' - which will return the name of the root node) thus resulting in
|
||||
the exception if default evaluation type (NODESET) is used.
|
||||
|
||||
This flag will allow you to manage the
|
||||
evaluation type. It is 'false' by default, however if
|
||||
set to 'true', then String evaluation type will be used.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:simpleType>
|
||||
<xsd:union memberTypes="xsd:boolean xsd:string" />
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="xpath-expression-ref" type="xsd:string" use="optional">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Reference to the XPathExpression instance to be
|
||||
evaluated against the input Message's payload. Either
|
||||
this or 'xpath-expression' must be provided, but not
|
||||
both.
|
||||
</xsd:documentation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.xml.xpath.XPathExpression"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="XPathRouterType">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="commonXPathRouterType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element ref="xpath-expression" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="mapping" type="integration:mappingValueChannelType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
If the values returned by the Xpaxth Expression
|
||||
do not represent the channel names itself, additional
|
||||
mappings can be specified using the mapping sub-element.
|
||||
|
||||
For example if the '/request/responders' expression
|
||||
results in two values 'responderA' and 'responderB'
|
||||
but you don't want to couple the responder names
|
||||
to channel names you may provide additional mappings
|
||||
such as:
|
||||
|
||||
<int-xml:mapping value="responderA" channel="channelA"/>
|
||||
<int-xml:mapping value="responderB" channel="channelB"/>
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attributeGroup ref="integration:topLevelRouterAttributeGroup"/>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="XPathRouterTypeChain">
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="commonXPathRouterType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="xpath-expression" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="mapping" type="integration:mappingValueChannelType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
If the values returned by the Xpaxth Expression
|
||||
do not represent the channel names itself, additional
|
||||
mappings can be specified using the mapping sub-element.
|
||||
|
||||
For example if the '/request/responders' expression
|
||||
results in two values 'responderA' and 'responderB'
|
||||
but you don't want to couple the responder names
|
||||
to channel names you may provide additional mappings
|
||||
such as:
|
||||
|
||||
<int-xml:mapping value="responderA" channel="channelA"/>
|
||||
<int-xml:mapping value="responderB" channel="channelB"/>
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="xpath-router" type="XPathRouterType"/>
|
||||
|
||||
<xsd:element name="xpath-selector">
|
||||
<xsd:complexType>
|
||||
@@ -468,12 +479,26 @@
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="xpath-expression">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines an XPath expression.
|
||||
|
||||
Internally XPath expressions will be evaluated as
|
||||
NODESET type and converted to a List<String>
|
||||
representing channel names. Typically such list
|
||||
will contain a single channel name. However, based
|
||||
on the result of an XPath Expression the XPath router
|
||||
can also take on the characteristics of the
|
||||
Recipient List Router if the XPath Expression
|
||||
returns more then one value, thus resulting in
|
||||
the List<String> containing more then one channel
|
||||
name.
|
||||
|
||||
In that case Message will be sent to all channels
|
||||
in the list.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an XPath expression.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="beans:map" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
|
||||
@@ -125,19 +125,6 @@ public class XPathRouterParserTests {
|
||||
inputChannel.send(docMessage);
|
||||
assertEquals("Wrong number of messages", 1, outputChannel.getQueueSize());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetChannelResolver() throws Exception {
|
||||
StringBuffer contextBuffer = new StringBuffer("<si-xml:xpath-router id='router' channel-resolver='stubResolver' input-channel='test-input'><si-xml:xpath-expression expression='/name'/></si-xml:xpath-router>");
|
||||
contextBuffer.append("<bean id='stubResolver' class='").append(StubChannelResolver.class.getName()).append("'/>");
|
||||
EventDrivenConsumer consumer = buildContext(contextBuffer.toString());
|
||||
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(consumer);
|
||||
Object handler = accessor.getPropertyValue("handler");
|
||||
accessor = new DirectFieldAccessor(handler);
|
||||
Object resolver = accessor.getPropertyValue("channelResolver");
|
||||
assertEquals("Wrong channel resolver ",StubChannelResolver.class, resolver.getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetResolutionRequiredFalse() throws Exception {
|
||||
@@ -163,32 +150,6 @@ public class XPathRouterParserTests {
|
||||
assertEquals("Resolution required not set to true ", true, resolutionRequired);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoreChannelNameResolutionFailuresFalse() throws Exception {
|
||||
StringBuffer contextBuffer = new StringBuffer(
|
||||
"<si-xml:xpath-router id='router' ignore-channel-name-resolution-failures='false' input-channel='test-input'><si-xml:xpath-expression expression='/name'/></si-xml:xpath-router>");
|
||||
EventDrivenConsumer consumer = buildContext(contextBuffer.toString());
|
||||
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(consumer);
|
||||
Object handler = accessor.getPropertyValue("handler");
|
||||
accessor = new DirectFieldAccessor(handler);
|
||||
Object ignoreChannelNameResolutionFailures = accessor.getPropertyValue("ignoreChannelNameResolutionFailures");
|
||||
assertEquals("ignoreChannelNameResolutionFailures not set to false", false, ignoreChannelNameResolutionFailures);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoreChannelNameResolutionFailuresTrue() throws Exception {
|
||||
StringBuffer contextBuffer = new StringBuffer(
|
||||
"<si-xml:xpath-router id='router' ignore-channel-name-resolution-failures='true' input-channel='test-input'><si-xml:xpath-expression expression='/name'/></si-xml:xpath-router>");
|
||||
EventDrivenConsumer consumer = buildContext(contextBuffer.toString());
|
||||
|
||||
DirectFieldAccessor accessor = new DirectFieldAccessor(consumer);
|
||||
Object handler = accessor.getPropertyValue("handler");
|
||||
accessor = new DirectFieldAccessor(handler);
|
||||
Object ignoreChannelNameResolutionFailures = accessor.getPropertyValue("ignoreChannelNameResolutionFailures");
|
||||
assertEquals("ignoreChannelNameResolutionFailures not set to true ", true, ignoreChannelNameResolutionFailures);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetDefaultOutputChannel() throws Exception {
|
||||
StringBuffer contextBuffer = new StringBuffer("<si-xml:xpath-router id='router' default-output-channel='defaultOutput' input-channel='test-input'><si-xml:xpath-expression expression='/name'/></si-xml:xpath-router>");
|
||||
|
||||
Reference in New Issue
Block a user