INT-721 PayloadTypeRouter now considers the weight of the match so that an exact match is no longer required. Now interface and superclass types can also be valid candidates.

This commit is contained in:
Mark Fisher
2009-08-31 19:36:04 +00:00
parent c2d77a8c87
commit 50fc478102
5 changed files with 237 additions and 55 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 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.
@@ -18,7 +18,9 @@ package org.springframework.integration.router;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.io.Serializable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -28,6 +30,7 @@ import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.core.Message;
import org.springframework.integration.core.MessageChannel;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.message.MessageHandlingException;
import org.springframework.integration.message.StringMessage;
/**
@@ -36,7 +39,7 @@ import org.springframework.integration.message.StringMessage;
public class PayloadTypeRouterTests {
@Test
public void resolveByPayloadType() {
public void resolveExactMatch() {
QueueChannel stringChannel = new QueueChannel();
QueueChannel integerChannel = new QueueChannel();
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
@@ -52,6 +55,136 @@ public class PayloadTypeRouterTests {
assertEquals(integerChannel, result2);
}
@Test
public void resolveSubclass() {
QueueChannel defaultChannel = new QueueChannel();
defaultChannel.setBeanName("defaultChannel");
QueueChannel numberChannel = new QueueChannel();
numberChannel.setBeanName("numberChannel");
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
payloadTypeChannelMap.put(Number.class, numberChannel);
PayloadTypeRouter router = new PayloadTypeRouter();
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<Integer> message = new GenericMessage<Integer>(99);
router.handleMessage(message);
Message<?> result = numberChannel.receive(0);
assertNotNull(result);
assertEquals(99, result.getPayload());
assertNull(defaultChannel.receive(0));
}
@Test
public void exactMatchFavoredOverSuperClass() {
QueueChannel defaultChannel = new QueueChannel();
defaultChannel.setBeanName("defaultChannel");
QueueChannel numberChannel = new QueueChannel();
numberChannel.setBeanName("numberChannel");
QueueChannel integerChannel = new QueueChannel();
integerChannel.setBeanName("integerChannel");
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
payloadTypeChannelMap.put(Number.class, numberChannel);
payloadTypeChannelMap.put(Integer.class, integerChannel);
PayloadTypeRouter router = new PayloadTypeRouter();
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<Integer> message = new GenericMessage<Integer>(99);
router.handleMessage(message);
Message<?> result = integerChannel.receive(0);
assertNotNull(result);
assertEquals(99, result.getPayload());
assertNull(numberChannel.receive(0));
assertNull(defaultChannel.receive(0));
}
@Test
public void interfaceMatch() {
QueueChannel defaultChannel = new QueueChannel();
defaultChannel.setBeanName("defaultChannel");
QueueChannel comparableChannel = new QueueChannel();
comparableChannel.setBeanName("comparableChannel");
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
payloadTypeChannelMap.put(Comparable.class, comparableChannel);
PayloadTypeRouter router = new PayloadTypeRouter();
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<Integer> message = new GenericMessage<Integer>(99);
router.handleMessage(message);
Message<?> result = comparableChannel.receive(0);
assertNotNull(result);
assertEquals(99, result.getPayload());
assertNull(defaultChannel.receive(0));
}
@Test
public void directInterfaceFavoredOverSuperClass() {
QueueChannel defaultChannel = new QueueChannel();
defaultChannel.setBeanName("defaultChannel");
QueueChannel numberChannel = new QueueChannel();
numberChannel.setBeanName("numberChannel");
QueueChannel comparableChannel = new QueueChannel();
comparableChannel.setBeanName("comparableChannel");
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
payloadTypeChannelMap.put(Number.class, numberChannel);
payloadTypeChannelMap.put(Comparable.class, comparableChannel);
PayloadTypeRouter router = new PayloadTypeRouter();
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<Integer> message = new GenericMessage<Integer>(99);
router.handleMessage(message);
Message<?> result = comparableChannel.receive(0);
assertNotNull(result);
assertEquals(99, result.getPayload());
assertNull(numberChannel.receive(0));
assertNull(defaultChannel.receive(0));
}
@Test(expected = IllegalStateException.class)
public void ambiguityFailure() throws Throwable {
QueueChannel defaultChannel = new QueueChannel();
defaultChannel.setBeanName("defaultChannel");
QueueChannel serializableChannel = new QueueChannel();
serializableChannel.setBeanName("serializableChannel");
QueueChannel comparableChannel = new QueueChannel();
comparableChannel.setBeanName("comparableChannel");
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
payloadTypeChannelMap.put(Serializable.class, serializableChannel);
payloadTypeChannelMap.put(Comparable.class, comparableChannel);
PayloadTypeRouter router = new PayloadTypeRouter();
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<String> message = new GenericMessage<String>("test");
try {
router.handleMessage(message);
}
catch (MessageHandlingException e) {
throw e.getCause();
}
}
@Test
public void superClassFavoredOverIndirectInterface() {
QueueChannel defaultChannel = new QueueChannel();
defaultChannel.setBeanName("defaultChannel");
QueueChannel numberChannel = new QueueChannel();
numberChannel.setBeanName("numberChannel");
QueueChannel serializableChannel = new QueueChannel();
serializableChannel.setBeanName("serializableChannel");
Map<Class<?>, MessageChannel> payloadTypeChannelMap = new ConcurrentHashMap<Class<?>, MessageChannel>();
payloadTypeChannelMap.put(Number.class, numberChannel);
payloadTypeChannelMap.put(Serializable.class, serializableChannel);
PayloadTypeRouter router = new PayloadTypeRouter();
router.setPayloadTypeChannelMap(payloadTypeChannelMap);
router.setDefaultOutputChannel(defaultChannel);
Message<Integer> message = new GenericMessage<Integer>(99);
router.handleMessage(message);
Message<?> result = numberChannel.receive(0);
assertNotNull(result);
assertEquals(99, result.getPayload());
assertNull(serializableChannel.receive(0));
assertNull(defaultChannel.receive(0));
}
@Test
public void resolveByPayloadTypeWithRouterEndpoint() {
QueueChannel stringChannel = new QueueChannel();

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2008 the original author or authors.
* Copyright 2002-2009 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.
@@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
@@ -40,26 +41,26 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ContextConfiguration
@RunWith(SpringJUnit4ClassRunner.class)
public class PayloadTypeRouterParserTests {
@Autowired
private ConfigurableApplicationContext context;
@Autowired
private TestService testService;
@Test
public void testPayloadTypeRouter() {
context.start();
MessageBuilder channel1MessageBuilder = MessageBuilder.withPayload("Hello");
Message message1 = channel1MessageBuilder.build();
MessageBuilder channel2MessageBuilder = MessageBuilder.withPayload(25);
Message message2 = channel2MessageBuilder.build();
Message<?> message1 = MessageBuilder.withPayload("Hello").build();
Message<?> message2 = MessageBuilder.withPayload(25).build();
testService.foo(message1);
testService.foo(message2);
PollableChannel chanel1 = (PollableChannel) context.getBean("channel1");
PollableChannel chanel2 = (PollableChannel) context.getBean("channel2");
assertTrue(chanel1.receive().getPayload() instanceof String);
assertTrue(chanel2.receive().getPayload() instanceof Integer);
assertTrue(chanel1.receive(0).getPayload() instanceof String);
assertTrue(chanel2.receive(0).getPayload() instanceof Integer);
}
@Test(expected=BeanDefinitionStoreException.class)
public void testFakeTypes(){
ByteArrayInputStream stream = new ByteArrayInputStream(routerConfigFakeType.getBytes());
@@ -68,7 +69,7 @@ public class PayloadTypeRouterParserTests {
reader.setValidationMode(XmlBeanDefinitionReader.VALIDATION_XSD);
reader.loadBeanDefinitions(new InputStreamResource(stream));
}
@Test(expected=BeanDefinitionStoreException.class)
public void testNoMappingElement(){
ByteArrayInputStream stream = new ByteArrayInputStream(routerConfigNoMaping.getBytes());
@@ -104,8 +105,9 @@ public class PayloadTypeRouterParserTests {
" <payload-type-router input-channel=\"routingChannel\"/>" +
"</beans:beans>";
public static interface TestService{
public void foo(Message message);
public void foo(Message<?> message);
}
}