From 57bb42270a908207c84660f6ede5dddcfe40e3e1 Mon Sep 17 00:00:00 2001 From: Mark Fisher Date: Wed, 2 Jan 2008 22:22:01 +0000 Subject: [PATCH] Implemented multi-channel routing with support for resolution by channel instance or channel name. --- .../router/AbstractRoutingMessageHandler.java | 113 ++++++++++++ .../router/MultiChannelNameResolver.java | 30 ++++ .../router/MultiChannelResolver.java | 33 ++++ .../router/MultiChannelRouter.java | 86 +++++++++ .../router/RoutingMessageHandler.java | 102 ----------- .../router/SingleChannelRouter.java | 84 +++++++++ .../router/MultiChannelRouterTests.java | 170 ++++++++++++++++++ ...sts.java => SingleChannelRouterTests.java} | 51 ++++-- 8 files changed, 556 insertions(+), 113 deletions(-) create mode 100644 spring-integration-core/src/main/java/org/springframework/integration/router/AbstractRoutingMessageHandler.java create mode 100644 spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelNameResolver.java create mode 100644 spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelResolver.java create mode 100644 spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelRouter.java delete mode 100644 spring-integration-core/src/main/java/org/springframework/integration/router/RoutingMessageHandler.java create mode 100644 spring-integration-core/src/main/java/org/springframework/integration/router/SingleChannelRouter.java create mode 100644 spring-integration-core/src/test/java/org/springframework/integration/router/MultiChannelRouterTests.java rename spring-integration-core/src/test/java/org/springframework/integration/router/{RoutingMessageHandlerTests.java => SingleChannelRouterTests.java} (71%) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractRoutingMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractRoutingMessageHandler.java new file mode 100644 index 0000000000..c9cd9e93a6 --- /dev/null +++ b/spring-integration-core/src/main/java/org/springframework/integration/router/AbstractRoutingMessageHandler.java @@ -0,0 +1,113 @@ +/* + * Copyright 2002-2007 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.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.integration.MessageHandlingException; +import org.springframework.integration.MessagingConfigurationException; +import org.springframework.integration.channel.ChannelRegistry; +import org.springframework.integration.channel.ChannelRegistryAware; +import org.springframework.integration.channel.MessageChannel; +import org.springframework.integration.handler.MessageHandler; +import org.springframework.integration.message.Message; + +/** + * Base class for message router implementations. + * + * @author Mark Fisher + */ +public abstract class AbstractRoutingMessageHandler implements MessageHandler, ChannelRegistryAware, InitializingBean { + + protected Log logger = LogFactory.getLog(this.getClass()); + + private ChannelRegistry channelRegistry; + + private boolean resolutionRequired = false; + + private long timeout = -1; + + + /** + * 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, set this value to 'true'. + */ + public void setResolutionRequired(boolean resolutionRequired) { + this.resolutionRequired = resolutionRequired; + } + + /** + * Set the timeout for sending a message to the resolved channel. By + * default, there is no timeout, meaning the send will block indefinitely. + */ + public void setTimeout(long timeout) { + this.timeout = timeout; + } + + public void setChannelRegistry(ChannelRegistry channelRegistry) { + this.channelRegistry = channelRegistry; + } + + protected ChannelRegistry getChannelRegistry() { + return this.channelRegistry; + } + + public final void afterPropertiesSet() { + this.validate(); + } + + public final Message handle(Message message) { + List channels = this.resolveChannels(message); + if (channels == null || channels.size() == 0) { + String errorMessage = "failed to resolve any channel for message"; + if (this.resolutionRequired) { + throw new MessageHandlingException(errorMessage); + } + if (logger.isWarnEnabled()) { + logger.warn(errorMessage); + } + return null; + } + for (MessageChannel channel : channels) { + this.sendMesage(message, channel); + } + return null; + } + + private void sendMesage(Message message, MessageChannel channel) { + boolean sent = false; + if (timeout < 0) { + sent = channel.send(message); + } + else { + sent = channel.send(message, timeout); + } + if (!sent) { + throw new MessageHandlingException("failed to send message to channel '" + channel.getName() + "'"); + } + } + + protected abstract void validate() throws MessagingConfigurationException; + + protected abstract List resolveChannels(Message message); + +} diff --git a/spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelNameResolver.java b/spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelNameResolver.java new file mode 100644 index 0000000000..12e25211e6 --- /dev/null +++ b/spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelNameResolver.java @@ -0,0 +1,30 @@ +/* + * Copyright 2002-2007 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 org.springframework.integration.message.Message; + +/** + * Strategy interface for content-based routing to multiple channel names. + * + * @author Mark Fisher + */ +public interface MultiChannelNameResolver { + + String[] resolve(Message message); + +} diff --git a/spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelResolver.java b/spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelResolver.java new file mode 100644 index 0000000000..4a41969641 --- /dev/null +++ b/spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelResolver.java @@ -0,0 +1,33 @@ +/* + * Copyright 2002-2007 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.List; + +import org.springframework.integration.channel.MessageChannel; +import org.springframework.integration.message.Message; + +/** + * Strategy interface for content-based routing to multiple channels. + * + * @author Mark Fisher + */ +public interface MultiChannelResolver { + + List resolve(Message message); + +} diff --git a/spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelRouter.java b/spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelRouter.java new file mode 100644 index 0000000000..0f89da60de --- /dev/null +++ b/spring-integration-core/src/main/java/org/springframework/integration/router/MultiChannelRouter.java @@ -0,0 +1,86 @@ +/* + * Copyright 2002-2007 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.List; + +import org.springframework.integration.MessagingConfigurationException; +import org.springframework.integration.channel.MessageChannel; +import org.springframework.integration.message.Message; + +/** + * A router implementation for sending to potentially multiple + * {@link MessageChannel MessageChannels}. Requires either a + * {@link MultiChannelResolver} or {@link MultiChannelNameResolver} strategy + * instance. In the case of the latter, the + * {@link org.springframework.integration.channel.ChannelRegistry} reference + * must also be provided. For convenience, the superclass does implement + * {@link org.springframework.integration.channel.ChannelRegistryAware}. + * + * @author Mark Fisher + */ +public class MultiChannelRouter extends AbstractRoutingMessageHandler { + + private MultiChannelResolver channelResolver; + + private MultiChannelNameResolver channelNameResolver; + + + public void setChannelResolver(MultiChannelResolver channelResolver) { + this.channelResolver = channelResolver; + } + + public void setChannelNameResolver(MultiChannelNameResolver channelNameResolver) { + this.channelNameResolver = channelNameResolver; + } + + @Override + public void validate() { + if (!(this.channelResolver != null ^ this.channelNameResolver != null)) { + throw new MessagingConfigurationException( + "exactly one of 'channelResolver' or 'channelNameResolver' must be provided"); + } + if (this.channelNameResolver != null && this.getChannelRegistry() == null) { + throw new MessagingConfigurationException("'channelRegistry' is required when resolving by channel name"); + } + } + + @Override + public List resolveChannels(Message message) { + if (this.channelResolver != null) { + return this.channelResolver.resolve(message); + } + if (this.channelNameResolver == null || this.getChannelRegistry() == null) { + throw new MessagingConfigurationException("router configuration requires either " + + "a 'channelResolver' or both 'channelNameResolver' and 'channelRegistry'"); + } + String[] channelNames = this.channelNameResolver.resolve(message); + if (channelNames == null) { + return null; + } + List channels = new ArrayList(channelNames.length); + for (String channelName : channelNames) { + MessageChannel channel = this.getChannelRegistry().lookupChannel(channelName); + if (channel != null) { + channels.add(channel); + } + } + return channels; + } + +} diff --git a/spring-integration-core/src/main/java/org/springframework/integration/router/RoutingMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/router/RoutingMessageHandler.java deleted file mode 100644 index 6ca3591a21..0000000000 --- a/spring-integration-core/src/main/java/org/springframework/integration/router/RoutingMessageHandler.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2002-2007 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 org.springframework.beans.factory.InitializingBean; -import org.springframework.integration.MessageHandlingException; -import org.springframework.integration.MessagingConfigurationException; -import org.springframework.integration.channel.ChannelRegistry; -import org.springframework.integration.channel.ChannelRegistryAware; -import org.springframework.integration.channel.MessageChannel; -import org.springframework.integration.handler.MessageHandler; -import org.springframework.integration.message.Message; - -/** - * @author Mark Fisher - */ -public class RoutingMessageHandler implements MessageHandler, ChannelRegistryAware, InitializingBean { - - private ChannelResolver channelResolver; - - private ChannelNameResolver channelNameResolver; - - private ChannelRegistry channelRegistry; - - private long timeout = -1; - - - /** - * Set the timeout for sending a message to the resolved channel. - * Default is no timeout, meaning the send will block indefinitely. - */ - public void setTimeout(long timeout) { - this.timeout = timeout; - } - - public void setChannelResolver(ChannelResolver channelResolver) { - this.channelResolver = channelResolver; - } - - public void setChannelNameResolver(ChannelNameResolver channelNameResolver) { - this.channelNameResolver = channelNameResolver; - } - - public void setChannelRegistry(ChannelRegistry channelRegistry) { - this.channelRegistry = channelRegistry; - } - - public void afterPropertiesSet() { - if(!(this.channelResolver != null ^ this.channelNameResolver != null)) { - throw new MessagingConfigurationException("exactly one of 'channelResolver' or 'channelNameResolver' must be provided"); - } - if (this.channelNameResolver != null && this.channelRegistry == null) { - throw new MessagingConfigurationException("'channelRegistry' is required when resolving by channel name"); - } - } - - public Message handle(Message message) { - MessageChannel channel = this.resolveChannel(message); - if (channel == null) { - throw new MessageHandlingException("failed to resolve channel"); - } - boolean sent = false; - if (timeout < 0) { - sent = channel.send(message); - } - else { - sent = channel.send(message, timeout); - } - if (!sent) { - throw new MessageHandlingException( - "failed to send message to channel '" + channel.getName() + "'"); - } - return null; - } - - private MessageChannel resolveChannel(Message message) { - if (this.channelResolver != null) { - return this.channelResolver.resolve(message); - } - else if (this.channelNameResolver != null && this.channelRegistry != null) { - String channelName = this.channelNameResolver.resolve(message); - return this.channelRegistry.lookupChannel(channelName); - } - throw new MessagingConfigurationException("router configuration requires either " + - "a 'channelResolver' or both 'channelNameResolver' and 'channelRegistry'"); - } - -} diff --git a/spring-integration-core/src/main/java/org/springframework/integration/router/SingleChannelRouter.java b/spring-integration-core/src/main/java/org/springframework/integration/router/SingleChannelRouter.java new file mode 100644 index 0000000000..7aa81e5fa7 --- /dev/null +++ b/spring-integration-core/src/main/java/org/springframework/integration/router/SingleChannelRouter.java @@ -0,0 +1,84 @@ +/* + * Copyright 2002-2007 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.List; + +import org.springframework.integration.MessagingConfigurationException; +import org.springframework.integration.channel.MessageChannel; +import org.springframework.integration.message.Message; + +/** + * A router implementation for sending to at most one {@link MessageChannel}. + * Requires either a {@link ChannelResolver} or {@link ChannelNameResolver} + * strategy instance. In the case of the latter, the + * {@link org.springframework.integration.channel.ChannelRegistry} reference + * must also be provided. For convenience, the superclass does implement + * {@link org.springframework.integration.channel.ChannelRegistryAware}. + * + * @author Mark Fisher + */ +public class SingleChannelRouter extends AbstractRoutingMessageHandler { + + private ChannelResolver channelResolver; + + private ChannelNameResolver channelNameResolver; + + + public void setChannelResolver(ChannelResolver channelResolver) { + this.channelResolver = channelResolver; + } + + public void setChannelNameResolver(ChannelNameResolver channelNameResolver) { + this.channelNameResolver = channelNameResolver; + } + + @Override + public void validate() { + if (!(this.channelResolver != null ^ this.channelNameResolver != null)) { + throw new MessagingConfigurationException( + "exactly one of 'channelResolver' or 'channelNameResolver' must be provided"); + } + if (this.channelNameResolver != null && this.getChannelRegistry() == null) { + throw new MessagingConfigurationException("'channelRegistry' is required when resolving by channel name"); + } + } + + @Override + public List resolveChannels(Message message) { + List channels = new ArrayList(); + MessageChannel channel = this.resolveChannel(message); + if (channel != null) { + channels.add(channel); + } + return channels; + } + + private MessageChannel resolveChannel(Message message) { + if (this.channelResolver != null) { + return this.channelResolver.resolve(message); + } + if (this.channelNameResolver == null || this.getChannelRegistry() == null) { + throw new MessagingConfigurationException("router configuration requires either " + + "a 'channelResolver' or both 'channelNameResolver' and 'channelRegistry'"); + } + String channelName = this.channelNameResolver.resolve(message); + return this.getChannelRegistry().lookupChannel(channelName); + } + +} diff --git a/spring-integration-core/src/test/java/org/springframework/integration/router/MultiChannelRouterTests.java b/spring-integration-core/src/test/java/org/springframework/integration/router/MultiChannelRouterTests.java new file mode 100644 index 0000000000..591644f769 --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/router/MultiChannelRouterTests.java @@ -0,0 +1,170 @@ +/* + * Copyright 2002-2007 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.ArrayList; +import java.util.List; + +import org.junit.Test; +import org.springframework.integration.MessageHandlingException; +import org.springframework.integration.MessagingConfigurationException; +import org.springframework.integration.channel.ChannelRegistry; +import org.springframework.integration.channel.DefaultChannelRegistry; +import org.springframework.integration.channel.MessageChannel; +import org.springframework.integration.channel.PointToPointChannel; +import org.springframework.integration.message.Message; +import org.springframework.integration.message.StringMessage; + +/** + * @author Mark Fisher + */ +public class MultiChannelRouterTests { + + @Test + public void testRoutingWithChannelResolver() { + final PointToPointChannel channel1 = new PointToPointChannel(); + final PointToPointChannel channel2 = new PointToPointChannel(); + MultiChannelResolver channelResolver = new MultiChannelResolver() { + public List resolve(Message message) { + List channels = new ArrayList(); + channels.add(channel1); + channels.add(channel2); + return channels; + } + }; + MultiChannelRouter router = new MultiChannelRouter(); + router.setChannelResolver(channelResolver); + router.afterPropertiesSet(); + Message message = new StringMessage("123", "test"); + router.handle(message); + Message result1 = channel1.receive(25); + assertNotNull(result1); + assertEquals("test", result1.getPayload()); + Message result2 = channel2.receive(25); + assertNotNull(result2); + assertEquals("test", result2.getPayload()); + } + + @Test + public void testRoutingWithChannelNameResolver() { + MultiChannelNameResolver channelNameResolver = new MultiChannelNameResolver() { + public String[] resolve(Message message) { + return new String[] {"channel1", "channel2"}; + } + }; + PointToPointChannel channel1 = new PointToPointChannel(); + PointToPointChannel channel2 = new PointToPointChannel(); + ChannelRegistry channelRegistry = new DefaultChannelRegistry(); + channelRegistry.registerChannel("channel1", channel1); + channelRegistry.registerChannel("channel2", channel2); + MultiChannelRouter router = new MultiChannelRouter(); + router.setChannelNameResolver(channelNameResolver); + router.setChannelRegistry(channelRegistry); + router.afterPropertiesSet(); + Message message = new StringMessage("123", "test"); + router.handle(message); + Message result1 = channel1.receive(25); + assertNotNull(result1); + assertEquals("test", result1.getPayload()); + Message result2 = channel2.receive(25); + assertNotNull(result2); + assertEquals("test", result2.getPayload()); + } + + @Test(expected=MessagingConfigurationException.class) + public void testConfiguringBothChannelResolverAndChannelNameResolverIsNotAllowed() { + MultiChannelResolver channelResolver = new MultiChannelResolver() { + public List resolve(Message message) { + return null; + } + }; + MultiChannelNameResolver channelNameResolver = new MultiChannelNameResolver() { + public String[] resolve(Message message) { + return null; + } + }; + MultiChannelRouter router = new MultiChannelRouter(); + router.setChannelResolver(channelResolver); + router.setChannelNameResolver(channelNameResolver); + router.afterPropertiesSet(); + } + + public void testChannelResolutionFailureIgnoredByDefault() { + MultiChannelResolver channelResolver = new MultiChannelResolver() { + public List resolve(Message message) { + return null; + } + }; + MultiChannelRouter router = new MultiChannelRouter(); + router.setChannelResolver(channelResolver); + router.setResolutionRequired(true); + router.afterPropertiesSet(); + Message message = new StringMessage("123", "test"); + router.handle(message); + } + + @Test(expected=MessageHandlingException.class) + public void testChannelResolutionFailureThrowsExceptionWhenResolutionRequired() { + MultiChannelResolver channelResolver = new MultiChannelResolver() { + public List resolve(Message message) { + return null; + } + }; + MultiChannelRouter router = new MultiChannelRouter(); + router.setChannelResolver(channelResolver); + router.setResolutionRequired(true); + router.afterPropertiesSet(); + Message message = new StringMessage("123", "test"); + router.handle(message); + } + + public void testChannelNameResolutionFailureIgnoredByDefault() { + MultiChannelNameResolver channelNameResolver = new MultiChannelNameResolver() { + public String[] resolve(Message message) { + return new String[] {"noSuchChannel"}; + } + }; + ChannelRegistry channelRegistry = new DefaultChannelRegistry(); + MultiChannelRouter router = new MultiChannelRouter(); + router.setChannelNameResolver(channelNameResolver); + router.setChannelRegistry(channelRegistry); + router.afterPropertiesSet(); + Message message = new StringMessage("123", "test"); + router.handle(message); + } + + @Test(expected=MessageHandlingException.class) + public void testChannelNameResolutionFailureThrowsExceptionWhenResolutionRequired() { + MultiChannelNameResolver channelNameResolver = new MultiChannelNameResolver() { + public String[] resolve(Message message) { + return new String[] {"noSuchChannel"}; + } + }; + ChannelRegistry channelRegistry = new DefaultChannelRegistry(); + MultiChannelRouter router = new MultiChannelRouter(); + router.setChannelNameResolver(channelNameResolver); + router.setChannelRegistry(channelRegistry); + router.setResolutionRequired(true); + router.afterPropertiesSet(); + Message message = new StringMessage("123", "test"); + router.handle(message); + } + +} diff --git a/spring-integration-core/src/test/java/org/springframework/integration/router/RoutingMessageHandlerTests.java b/spring-integration-core/src/test/java/org/springframework/integration/router/SingleChannelRouterTests.java similarity index 71% rename from spring-integration-core/src/test/java/org/springframework/integration/router/RoutingMessageHandlerTests.java rename to spring-integration-core/src/test/java/org/springframework/integration/router/SingleChannelRouterTests.java index b71c6b4f90..3f58204976 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/router/RoutingMessageHandlerTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/router/SingleChannelRouterTests.java @@ -33,7 +33,7 @@ import org.springframework.integration.message.StringMessage; /** * @author Mark Fisher */ -public class RoutingMessageHandlerTests { +public class SingleChannelRouterTests { @Test public void testRoutingWithChannelResolver() { @@ -43,7 +43,7 @@ public class RoutingMessageHandlerTests { return channel; } }; - RoutingMessageHandler router = new RoutingMessageHandler(); + SingleChannelRouter router = new SingleChannelRouter(); router.setChannelResolver(channelResolver); router.afterPropertiesSet(); Message message = new StringMessage("123", "test"); @@ -63,7 +63,7 @@ public class RoutingMessageHandlerTests { PointToPointChannel channel = new PointToPointChannel(); ChannelRegistry channelRegistry = new DefaultChannelRegistry(); channelRegistry.registerChannel("testChannel", channel); - RoutingMessageHandler router = new RoutingMessageHandler(); + SingleChannelRouter router = new SingleChannelRouter(); router.setChannelNameResolver(channelNameResolver); router.setChannelRegistry(channelRegistry); router.afterPropertiesSet(); @@ -86,37 +86,49 @@ public class RoutingMessageHandlerTests { return ""; } }; - RoutingMessageHandler router = new RoutingMessageHandler(); + SingleChannelRouter router = new SingleChannelRouter(); router.setChannelResolver(channelResolver); router.setChannelNameResolver(channelNameResolver); router.afterPropertiesSet(); } - @Test(expected=MessageHandlingException.class) - public void testChannelResolutionFailure() { + public void testChannelResolutionFailureIgnoredByDefault() { ChannelResolver channelResolver = new ChannelResolver() { public MessageChannel resolve(Message message) { return null; } }; - RoutingMessageHandler router = new RoutingMessageHandler(); + SingleChannelRouter router = new SingleChannelRouter(); router.setChannelResolver(channelResolver); + router.setResolutionRequired(true); router.afterPropertiesSet(); Message message = new StringMessage("123", "test"); router.handle(message); } @Test(expected=MessageHandlingException.class) - public void testChannelNameResolutionFailure() { + public void testChannelResolutionFailureThrowsExceptionWhenResolutionRequired() { + ChannelResolver channelResolver = new ChannelResolver() { + public MessageChannel resolve(Message message) { + return null; + } + }; + SingleChannelRouter router = new SingleChannelRouter(); + router.setChannelResolver(channelResolver); + router.setResolutionRequired(true); + router.afterPropertiesSet(); + Message message = new StringMessage("123", "test"); + router.handle(message); + } + + public void testChannelNameResolutionFailureIgnoredByDefault() { ChannelNameResolver channelNameResolver = new ChannelNameResolver() { public String resolve(Message message) { return "noSuchChannel"; } }; - PointToPointChannel channel = new PointToPointChannel(); ChannelRegistry channelRegistry = new DefaultChannelRegistry(); - channelRegistry.registerChannel("testChannel", channel); - RoutingMessageHandler router = new RoutingMessageHandler(); + SingleChannelRouter router = new SingleChannelRouter(); router.setChannelNameResolver(channelNameResolver); router.setChannelRegistry(channelRegistry); router.afterPropertiesSet(); @@ -124,4 +136,21 @@ public class RoutingMessageHandlerTests { router.handle(message); } + @Test(expected=MessageHandlingException.class) + public void testChannelNameResolutionFailureThrowsExceptionWhenResolutionRequired() { + ChannelNameResolver channelNameResolver = new ChannelNameResolver() { + public String resolve(Message message) { + return "noSuchChannel"; + } + }; + ChannelRegistry channelRegistry = new DefaultChannelRegistry(); + SingleChannelRouter router = new SingleChannelRouter(); + router.setChannelNameResolver(channelNameResolver); + router.setChannelRegistry(channelRegistry); + router.setResolutionRequired(true); + router.afterPropertiesSet(); + Message message = new StringMessage("123", "test"); + router.handle(message); + } + }