diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelParser.java b/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelParser.java index 6b68b056d6..66cdeb32cb 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelParser.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/ChannelParser.java @@ -29,6 +29,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.BeanDefinitionParser; import org.springframework.beans.factory.xml.ParserContext; import org.springframework.integration.channel.DispatcherPolicy; +import org.springframework.integration.channel.PriorityChannel; import org.springframework.integration.channel.SimpleChannel; import org.springframework.integration.channel.interceptor.MessageSelectingInterceptor; import org.springframework.integration.message.selector.MessageSelector; @@ -56,9 +57,13 @@ public class ChannelParser implements BeanDefinitionParser { private static final String INTERCEPTORS_PROPERTY = "interceptors"; + private static final String COMPARATOR_REF_ATTRIBUTE = "comparator-ref"; + public BeanDefinition parse(Element element, ParserContext parserContext) { - RootBeanDefinition channelDef = new RootBeanDefinition(SimpleChannel.class); + boolean isPriorityChannel = (element.getLocalName().equals("priority-channel")); + Class channelClass = (isPriorityChannel) ? PriorityChannel.class : SimpleChannel.class; + RootBeanDefinition channelDef = new RootBeanDefinition(channelClass); channelDef.setSource(parserContext.extractSource(element)); boolean isPublishSubscribe = "true".equals(element.getAttribute(PUBLISH_SUBSCRIBE_ATTRIBUTE)); DispatcherPolicy dispatcherPolicy = new DispatcherPolicy(isPublishSubscribe); @@ -81,6 +86,12 @@ public class ChannelParser implements BeanDefinitionParser { int capacity = (StringUtils.hasText(capAttr)) ? Integer.parseInt(capAttr) : SimpleChannel.DEFAULT_CAPACITY; channelDef.getConstructorArgumentValues().addIndexedArgumentValue(0, capacity); channelDef.getConstructorArgumentValues().addIndexedArgumentValue(1, dispatcherPolicy); + if (isPriorityChannel) { + String comparatorRef = element.getAttribute(COMPARATOR_REF_ATTRIBUTE); + if (StringUtils.hasText(comparatorRef)) { + channelDef.getConstructorArgumentValues().addIndexedArgumentValue(2, new RuntimeBeanReference(comparatorRef)); + } + } String datatypeAttr = element.getAttribute(DATATYPE_ATTRIBUTE); if (StringUtils.hasText(datatypeAttr)) { String[] datatypes = StringUtils.commaDelimitedListToStringArray(datatypeAttr); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationNamespaceHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationNamespaceHandler.java index 49c89610f6..3ee613657c 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationNamespaceHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/IntegrationNamespaceHandler.java @@ -48,6 +48,7 @@ public class IntegrationNamespaceHandler extends NamespaceHandlerSupport { registerBeanDefinitionParser("message-bus", new MessageBusParser()); registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenParser()); registerBeanDefinitionParser("channel", new ChannelParser()); + registerBeanDefinitionParser("priority-channel", new ChannelParser()); registerBeanDefinitionParser("source-adapter", new ChannelAdapterParser(true)); registerBeanDefinitionParser("target-adapter", new ChannelAdapterParser(false)); registerBeanDefinitionParser("endpoint", new EndpointParser()); diff --git a/spring-integration-core/src/main/java/org/springframework/integration/config/spring-integration-core-1.0.xsd b/spring-integration-core/src/main/java/org/springframework/integration/config/spring-integration-core-1.0.xsd index 91634b179e..5975357374 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/config/spring-integration-core-1.0.xsd +++ b/spring-integration-core/src/main/java/org/springframework/integration/config/spring-integration-core-1.0.xsd @@ -44,24 +44,39 @@ - + + + - Defines a message channel. + Defines a channel with priority-ordering for message reception. - - - - - - - - + + + + + + + + + Defines a message channel. + + + + + + + + + + + + diff --git a/spring-integration-core/src/test/java/org/springframework/integration/channel/PriorityChannelTests.java b/spring-integration-core/src/test/java/org/springframework/integration/channel/PriorityChannelTests.java index 94f1bef8f8..3cdefe36f6 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/channel/PriorityChannelTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/channel/PriorityChannelTests.java @@ -91,7 +91,7 @@ public class PriorityChannelTests { } - private static class StringPayloadComparator implements Comparator> { + public static class StringPayloadComparator implements Comparator> { public int compare(Message message1, Message message2) { String s1 = (String) message1.getPayload(); diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelParserTests.java b/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelParserTests.java index 25821fe921..f1484bba9a 100644 --- a/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelParserTests.java +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/ChannelParserTests.java @@ -205,6 +205,47 @@ public class ChannelParserTests { assertEquals(1, interceptor.getReceiveCount()); } + @Test + public void testPriorityChannelWithDefaultComparator() { + ApplicationContext context = new ClassPathXmlApplicationContext( + "priorityChannelParserTests.xml", this.getClass()); + MessageChannel channel = (MessageChannel) context.getBean("priorityChannelWithDefaultComparator"); + Message lowPriorityMessage = new StringMessage("low"); + lowPriorityMessage.getHeader().setPriority(777); + Message midPriorityMessage = new StringMessage("mid"); + midPriorityMessage.getHeader().setPriority(77); + Message highPriorityMessage = new StringMessage("high"); + highPriorityMessage.getHeader().setPriority(7); + channel.send(lowPriorityMessage); + channel.send(highPriorityMessage); + channel.send(midPriorityMessage); + Message reply1 = channel.receive(0); + Message reply2 = channel.receive(0); + Message reply3 = channel.receive(0); + assertEquals("high", reply1.getPayload()); + assertEquals("mid", reply2.getPayload()); + assertEquals("low", reply3.getPayload()); + } + + @Test + public void testPriorityChannelWithCustomComparator() { + ApplicationContext context = new ClassPathXmlApplicationContext( + "priorityChannelParserTests.xml", this.getClass()); + MessageChannel channel = (MessageChannel) context.getBean("priorityChannelWithCustomComparator"); + channel.send(new StringMessage("C")); + channel.send(new StringMessage("A")); + channel.send(new StringMessage("D")); + channel.send(new StringMessage("B")); + Message reply1 = channel.receive(0); + Message reply2 = channel.receive(0); + Message reply3 = channel.receive(0); + Message reply4 = channel.receive(0); + assertEquals("A", reply1.getPayload()); + assertEquals("B", reply2.getPayload()); + assertEquals("C", reply3.getPayload()); + assertEquals("D", reply4.getPayload()); + } + private static class TestHandler implements MessageHandler { diff --git a/spring-integration-core/src/test/java/org/springframework/integration/config/priorityChannelParserTests.xml b/spring-integration-core/src/test/java/org/springframework/integration/config/priorityChannelParserTests.xml new file mode 100644 index 0000000000..fd4d2aa40c --- /dev/null +++ b/spring-integration-core/src/test/java/org/springframework/integration/config/priorityChannelParserTests.xml @@ -0,0 +1,17 @@ + + + + + + + + + +