From dc867821950af9939976644692a263ab2b1b5385 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Mon, 11 Jul 2011 18:08:54 -0400 Subject: [PATCH] INT-1969 fixed PayloadTypeRouter to introspect sub-interfaces of the interfaces implemented by the payload type --- .../integration/router/PayloadTypeRouter.java | 56 +++++++++++++------ .../router/PayloadTypeRouterTests.java | 35 ++++++++++++ 2 files changed, 74 insertions(+), 17 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/router/PayloadTypeRouter.java b/spring-integration-core/src/main/java/org/springframework/integration/router/PayloadTypeRouter.java index dc3b0404da..41e9b8bbb0 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/router/PayloadTypeRouter.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/router/PayloadTypeRouter.java @@ -16,6 +16,7 @@ package org.springframework.integration.router; +import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -68,29 +69,50 @@ public class PayloadTypeRouter extends AbstractMessageRouter { if (StringUtils.hasText(channelName)) { return channelName; } - // next, check for interfaces of this type - Class matchedInterface = null; - Class[] interfaces = type.getInterfaces(); - for (Class currentInterface : interfaces) { - String currentChannelName = this.channelIdentifierMap.get(currentInterface.getName()); - if (StringUtils.hasText(currentChannelName)) { - if (matchedInterface != null) { - throw new MessageHandlingException(message, - "Unresolvable ambiguity while attempting to find closest match for [" + type.getName() + - "]. Candidate types [" + matchedInterface.getName() + "] and [" + - currentInterface.getName() + "] have equal weight."); - } - matchedInterface = currentInterface; - channelName = currentChannelName; - } - } + // next, check for interfaces (super inluded) of this type + + channelName = this.introspectInterfaces(type, message); + if (channelName != null) { return channelName; - } + } + // finally, continue up the hierarchy type = type.getSuperclass(); } return null; } + + private String introspectInterfaces(Class type, Message message){ + Class[] interfaces = type.getInterfaces(); + List matchedInterfaces = new ArrayList(); + + this.doInitrospect(interfaces, matchedInterfaces); + + if (matchedInterfaces.isEmpty()){ + return null; + } + else { + if (matchedInterfaces.size() > 1){ + throw new MessageHandlingException(message, + "Unresolvable ambiguity while attempting to find closest match for [" + type.getName() + + "]. Candidate types " + matchedInterfaces + " have equal weight."); + } + else { + return matchedInterfaces.get(0); + } + } + } + + public void doInitrospect(Class[] interfaces, List matchedInterfaces){ + for (Class extendedInterface : interfaces) { + String currentChannelName = this.channelIdentifierMap.get(extendedInterface.getName()); + if (StringUtils.hasText(currentChannelName)) { + matchedInterfaces.add(extendedInterface.getName()); + } + Class[] extendedInterfaces = extendedInterface.getInterfaces(); + this.doInitrospect(extendedInterfaces, matchedInterfaces); + } + } } diff --git a/spring-integration-core/src/test/java/org/springframework/integration/router/PayloadTypeRouterTests.java b/spring-integration-core/src/test/java/org/springframework/integration/router/PayloadTypeRouterTests.java index ed82414937..b473fcfa0c 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/router/PayloadTypeRouterTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/router/PayloadTypeRouterTests.java @@ -26,6 +26,7 @@ import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import org.junit.Test; + import org.springframework.beans.factory.support.DefaultListableBeanFactory; import org.springframework.integration.Message; import org.springframework.integration.MessageHandlingException; @@ -172,6 +173,31 @@ public class PayloadTypeRouterTests { assertEquals(99, result.getPayload()); assertNull(defaultChannel.receive(0)); } + + @Test + public void extendedInterfaceMatch() { + QueueChannel defaultChannel = new QueueChannel(); + defaultChannel.setBeanName("defaultChannel"); + QueueChannel bChannel = new QueueChannel(); + bChannel.setBeanName("bChannel"); + + DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); + beanFactory.registerSingleton("defaultChannel", defaultChannel); + beanFactory.registerSingleton("bChannel", bChannel); + + Map payloadTypeChannelMap = new ConcurrentHashMap(); + payloadTypeChannelMap.put(B.class.getName(), "bChannel"); + PayloadTypeRouter router = new PayloadTypeRouter(); + + router.setBeanFactory(beanFactory); + router.setChannelIdentifierMap(payloadTypeChannelMap); + + router.setDefaultOutputChannel(defaultChannel); + Message message = new GenericMessage(new Foo()); + router.handleMessage(message); + Message result = bChannel.receive(0); + assertNotNull(result); + } @Test public void directInterfaceFavoredOverSuperClass() { @@ -335,4 +361,13 @@ public class PayloadTypeRouterTests { assertNotNull(result2); assertEquals(123, result2.getPayload()); } + + @SuppressWarnings("serial") + public static class Foo implements Bar, A {} + + public interface Bar extends Serializable {} + + public interface A extends B {} + + public interface B {} }