INT-1969 fixed PayloadTypeRouter to introspect sub-interfaces of the interfaces implemented by the payload type

This commit is contained in:
Oleg Zhurakousky
2011-07-11 18:08:54 -04:00
parent ccb0edc2ee
commit dc86782195
2 changed files with 74 additions and 17 deletions

View File

@@ -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<String> matchedInterfaces = new ArrayList<String>();
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<String> 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);
}
}
}

View File

@@ -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<String, String> payloadTypeChannelMap = new ConcurrentHashMap<String, String>();
payloadTypeChannelMap.put(B.class.getName(), "bChannel");
PayloadTypeRouter router = new PayloadTypeRouter();
router.setBeanFactory(beanFactory);
router.setChannelIdentifierMap(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<Foo> message = new GenericMessage<Foo>(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 {}
}