INT-1969 fixed PayloadTypeRouter to introspect sub-interfaces of the interfaces implemented by the payload type
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user