diff --git a/org.springframework.integration/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java b/org.springframework.integration/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java index 5b4eaecf3e..2bbc57b0c2 100644 --- a/org.springframework.integration/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java +++ b/org.springframework.integration/src/main/java/org/springframework/integration/config/annotation/AbstractMethodAnnotationPostProcessor.java @@ -24,12 +24,14 @@ import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.core.annotation.Order; import org.springframework.integration.channel.BeanFactoryChannelResolver; import org.springframework.integration.channel.ChannelResolver; import org.springframework.integration.channel.SubscribableChannel; import org.springframework.integration.core.MessageChannel; import org.springframework.integration.endpoint.AbstractEndpoint; import org.springframework.integration.endpoint.EventDrivenConsumer; +import org.springframework.integration.handler.AbstractMessageHandler; import org.springframework.integration.message.MessageHandler; import org.springframework.util.Assert; import org.springframework.util.StringUtils; @@ -58,6 +60,12 @@ public abstract class AbstractMethodAnnotationPostProcessor calls = testBean.calls; + assertEquals(5, calls.size()); + assertEquals(1, calls.get(0).intValue()); + assertEquals(2, calls.get(1).intValue()); + assertEquals(3, calls.get(2).intValue()); + assertEquals(4, calls.get(3).intValue()); + assertEquals(5, calls.get(4).intValue()); + } + + @Test + public void directChannelAndFailoverDispatcherWithMultipleCallsPerMethod() { + GenericApplicationContext context = new GenericApplicationContext(); + context.registerBeanDefinition("postProcessor", new RootBeanDefinition(MessagingAnnotationPostProcessor.class)); + RootBeanDefinition channelDefinition = new RootBeanDefinition(DirectChannel.class); + channelDefinition.getConstructorArgumentValues().addGenericArgumentValue(new FailOverDispatcher()); + context.registerBeanDefinition("input", channelDefinition); + RootBeanDefinition testBeanDefinition = new RootBeanDefinition(TestBean.class); + testBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue(2); + context.registerBeanDefinition("testBean", testBeanDefinition); + context.refresh(); + TestBean testBean = (TestBean) context.getBean("testBean"); + MessageChannel channel = (MessageChannel) context.getBean("input"); + channel.send(new StringMessage("test-1")); + channel.send(new StringMessage("test-2")); + channel.send(new StringMessage("test-3")); + channel.send(new StringMessage("test-4")); + channel.send(new StringMessage("test-5")); + channel.send(new StringMessage("test-6")); + channel.send(new StringMessage("test-7")); + channel.send(new StringMessage("test-8")); + channel.send(new StringMessage("test-9")); + channel.send(new StringMessage("test-10")); + assertEquals(10, testBean.calls.size()); + assertEquals(1, testBean.calls.get(0).intValue()); + assertEquals(1, testBean.calls.get(1).intValue()); + assertEquals(2, testBean.calls.get(2).intValue()); + assertEquals(2, testBean.calls.get(3).intValue()); + assertEquals(3, testBean.calls.get(4).intValue()); + assertEquals(3, testBean.calls.get(5).intValue()); + assertEquals(4, testBean.calls.get(6).intValue()); + assertEquals(4, testBean.calls.get(7).intValue()); + assertEquals(5, testBean.calls.get(8).intValue()); + assertEquals(5, testBean.calls.get(9).intValue()); + testBean.reset(); + channel.send(new StringMessage("test-11")); + assertEquals(1, testBean.calls.size()); + assertEquals(1, testBean.calls.get(0).intValue()); + } + + @Test + public void directChannelAndRoundRobinDispatcher() { + GenericApplicationContext context = new GenericApplicationContext(); + context.registerBeanDefinition("postProcessor", new RootBeanDefinition(MessagingAnnotationPostProcessor.class)); + RootBeanDefinition channelDefinition = new RootBeanDefinition(DirectChannel.class); + context.registerBeanDefinition("input", channelDefinition); + RootBeanDefinition testBeanDefinition = new RootBeanDefinition(TestBean.class); + testBeanDefinition.getConstructorArgumentValues().addGenericArgumentValue(1000); + context.registerBeanDefinition("testBean", testBeanDefinition); + context.refresh(); + TestBean testBean = (TestBean) context.getBean("testBean"); + MessageChannel channel = (MessageChannel) context.getBean("input"); + channel.send(new StringMessage("test-1")); + channel.send(new StringMessage("test-2")); + channel.send(new StringMessage("test-3")); + channel.send(new StringMessage("test-4")); + channel.send(new StringMessage("test-5")); + List calls = testBean.calls; + assertEquals(5, calls.size()); + assertEquals(1, calls.get(0).intValue()); + assertEquals(2, calls.get(1).intValue()); + assertEquals(3, calls.get(2).intValue()); + assertEquals(4, calls.get(3).intValue()); + assertEquals(5, calls.get(4).intValue()); + } + + + static abstract class AbstractTestBean { + + @Order(4) + abstract void fourth(Message message); + + @Order(2) + abstract void second(Message message); + + } + + + @MessageEndpoint + static class TestBean extends AbstractTestBean { + + private final int maxCallsPerMethod; + + private volatile List calls = new ArrayList(); + + + TestBean(int maxCallsPerMethod) { + this.maxCallsPerMethod = maxCallsPerMethod; + } + + + void reset() { + this.calls = new ArrayList(); + } + + @Order(3) + @ServiceActivator(inputChannel="input") + public void third(Message message) { + this.handle(3, message); + } + + @Override + @ServiceActivator(inputChannel="input") + public void second(Message message) { + this.handle(2, message); + } + + @Order(1) + @ServiceActivator(inputChannel="input") + public void first(Message message) { + this.handle(1, message); + } + + @Order(5) + @ServiceActivator(inputChannel="input") + public void fifth(Message message) { + this.handle(5, message); + } + + @Override + @ServiceActivator(inputChannel="input") + public void fourth(Message message) { + this.handle(4, message); + } + + private void handle(int methodNumber, Message message) { + int count = 0; + for (int callNumber : this.calls) { + if (callNumber == methodNumber) { + count++; + if (count >= this.maxCallsPerMethod) { + throw new MessageRejectedException(message); + } + } + } + this.calls.add(methodNumber); + } + } + +}