INT-3402: Late Resolution for Channel Names

JIRA: https://jira.spring.io/browse/INT-3402

* Move `channel name to channel` resolution logic to the action, e.g. `sendReplyMessage`
* Remove resolution logic from `MessagingAnnotation` Processors
* Fix `AggregatorAnnotationPostProcessor` to invoke `handler.afterPropertiesSet()` one more time,
because of `AbstractMethodAnnotationPostProcessor` `this.beanFactory.initializeBean(handler, handlerBeanName)`
* `Filter` annotation: allow `property-placeholder` for the `discardWithinAdvice`
* Fix `EnricherParserTests4-context.xml` duration: use just `0` for the `reply-timeout`

INT-3402: Add `synchronized double check`

INT-3402: Polishing according PR comments

INT-3402: Optimization for `AbstractCorrelatingMH`
This commit is contained in:
Artem Bilan
2014-07-28 18:02:16 +03:00
committed by Gary Russell
parent 403c91801d
commit 1458f56102
17 changed files with 202 additions and 169 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2014 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.
@@ -37,11 +37,8 @@ import org.springframework.integration.aggregator.MethodInvokingReleaseStrategy;
import org.springframework.integration.aggregator.SequenceSizeReleaseStrategy;
import org.springframework.integration.channel.NullChannel;
import org.springframework.integration.endpoint.EventDrivenConsumer;
import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.core.DestinationResolver;
/**
* @author Marius Bogoevici
@@ -71,10 +68,8 @@ public class AggregatorAnnotationTests {
final String endpointName = "endpointWithCustomizedAnnotation";
MessageHandler aggregator = this.getAggregator(context, endpointName);
assertTrue(getPropertyValue(aggregator, "releaseStrategy") instanceof SequenceSizeReleaseStrategy);
DestinationResolver<MessageChannel> channelResolver = new BeanFactoryChannelResolver(context);
assertEquals(channelResolver.resolveDestination("outputChannel"), getPropertyValue(aggregator, "outputChannel"));
assertEquals(channelResolver.resolveDestination("discardChannel"), getPropertyValue(aggregator,
"discardChannel"));
assertEquals("outputChannel", getPropertyValue(aggregator, "outputChannelName"));
assertEquals("discardChannel", getPropertyValue(aggregator, "discardChannelName"));
assertEquals(98765432l, getPropertyValue(aggregator, "messagingTemplate.sendTimeout"));
assertEquals(true, getPropertyValue(aggregator, "sendPartialResultOnExpiry"));
}

View File

@@ -198,7 +198,7 @@ public class FilterAnnotationPostProcessorTests {
@MessageEndpoint
private static class TestFilterWithBooleanPrimitive {
@Filter(inputChannel="input", outputChannel="output")
@Filter(inputChannel = "input", outputChannel = "output")
public boolean filter(String s) {
return !s.contains("bad");
}
@@ -207,7 +207,7 @@ public class FilterAnnotationPostProcessorTests {
@MessageEndpoint
private static class TestFilterWithAdviceDiscardWithin {
@Filter(inputChannel="input", outputChannel="output", adviceChain="adviceChain")
@Filter(inputChannel = "input", outputChannel = "output", adviceChain = "adviceChain")
public boolean filter(String s) {
return !s.contains("bad");
}
@@ -216,7 +216,7 @@ public class FilterAnnotationPostProcessorTests {
@MessageEndpoint
private static class TestFilterWithAdviceDiscardWithinTwice {
@Filter(inputChannel="input", outputChannel="output", adviceChain={"adviceChain1", "adviceChain2"})
@Filter(inputChannel = "input", outputChannel = "output", adviceChain = {"adviceChain1", "adviceChain2"})
public boolean filter(String s) {
return !s.contains("bad");
}
@@ -225,8 +225,8 @@ public class FilterAnnotationPostProcessorTests {
@MessageEndpoint
private static class TestFilterWithAdviceDiscardWithout {
@Filter(inputChannel="input", outputChannel="output",
adviceChain="adviceChain", discardWithinAdvice=false)
@Filter(inputChannel = "input", outputChannel = "output",
adviceChain = "adviceChain", discardWithinAdvice = "false")
public boolean filter(String s) {
return !s.contains("bad");
}
@@ -235,7 +235,7 @@ public class FilterAnnotationPostProcessorTests {
@MessageEndpoint
private static class TestFilterWithBooleanWrapperClass {
@Filter(inputChannel="input", outputChannel="output")
@Filter(inputChannel = "input", outputChannel = "output")
public Boolean filter(String s) {
return !s.contains("bad");
}
@@ -245,7 +245,7 @@ public class FilterAnnotationPostProcessorTests {
@MessageEndpoint
private static class TestFilterWithStringReturnType {
@Filter(inputChannel="input", outputChannel="output")
@Filter(inputChannel = "input", outputChannel = "output")
public String filter(String s) {
return s;
}
@@ -255,7 +255,7 @@ public class FilterAnnotationPostProcessorTests {
@MessageEndpoint
private static class TestFilterWithVoidReturnType {
@Filter(inputChannel="input", outputChannel="output")
@Filter(inputChannel = "input", outputChannel = "output")
public void filter(String s) {
}
}

View File

@@ -26,7 +26,7 @@
<enricher id="enricher" input-channel="input"
request-channel="requests1" request-timeout="1234"
reply-timeout="9876" reply-channel="replies"
reply-timeout="0" reply-channel="replies"
order="99" should-clone-payload="true" output-channel="output">
<property name="name" expression="payload.sourceName" null-result-expression="'Could not determine the name'"/>
<property name="age" value="42" null-result-expression="'11'"/>

View File

@@ -17,7 +17,15 @@
package org.springframework.integration.configuration;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import java.lang.annotation.ElementType;
@@ -402,19 +410,19 @@ public class EnableIntegrationTests {
assertFalse(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class));
assertEquals(23, TestUtils.getPropertyValue(consumer, "phase"));
assertSame(context.getBean("annInput"), TestUtils.getPropertyValue(consumer, "inputChannel"));
assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel"));
assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName"));
assertSame(context.getBean("annAdvice"), TestUtils.getPropertyValue(consumer,
"handler.adviceChain", List.class).get(0));
assertEquals(1000L, TestUtils.getPropertyValue(consumer, "trigger.period"));
consumer = this.context.getBean(
"enableIntegrationTests.AnnotationTestService.annCount1.serviceActivator",
PollingConsumer.class);
"enableIntegrationTests.AnnotationTestService.annCount1.serviceActivator",
PollingConsumer.class);
consumer.stop();
assertTrue(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class));
assertEquals(23, TestUtils.getPropertyValue(consumer, "phase"));
assertSame(context.getBean("annInput1"), TestUtils.getPropertyValue(consumer, "inputChannel"));
assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel"));
assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName"));
assertSame(context.getBean("annAdvice1"), TestUtils.getPropertyValue(consumer,
"handler.adviceChain", List.class).get(0));
assertEquals(2000L, TestUtils.getPropertyValue(consumer, "trigger.period"));
@@ -425,7 +433,7 @@ public class EnableIntegrationTests {
assertFalse(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class));
assertEquals(23, TestUtils.getPropertyValue(consumer, "phase"));
assertSame(context.getBean("annInput"), TestUtils.getPropertyValue(consumer, "inputChannel"));
assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel"));
assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName"));
assertSame(context.getBean("annAdvice"), TestUtils.getPropertyValue(consumer,
"handler.adviceChain", List.class).get(0));
assertEquals(1000L, TestUtils.getPropertyValue(consumer, "trigger.period"));
@@ -437,7 +445,7 @@ public class EnableIntegrationTests {
assertFalse(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class));
assertEquals(23, TestUtils.getPropertyValue(consumer, "phase"));
assertSame(context.getBean("annInput3"), TestUtils.getPropertyValue(consumer, "inputChannel"));
assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel"));
assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName"));
assertSame(context.getBean("annAdvice"), TestUtils.getPropertyValue(consumer,
"handler.adviceChain", List.class).get(0));
assertEquals(1000L, TestUtils.getPropertyValue(consumer, "trigger.period"));
@@ -448,8 +456,8 @@ public class EnableIntegrationTests {
assertFalse(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class));
assertEquals(23, TestUtils.getPropertyValue(consumer, "phase"));
assertSame(context.getBean("annInput"), TestUtils.getPropertyValue(consumer, "inputChannel"));
assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel"));
assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.discardChannel"));
assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName"));
assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.discardChannelName"));
assertEquals(1000L, TestUtils.getPropertyValue(consumer, "trigger.period"));
assertEquals(1000L, TestUtils.getPropertyValue(consumer, "handler.messagingTemplate.sendTimeout"));
assertFalse(TestUtils.getPropertyValue(consumer, "handler.sendPartialResultOnExpiry", Boolean.class));
@@ -460,8 +468,8 @@ public class EnableIntegrationTests {
assertFalse(TestUtils.getPropertyValue(consumer, "autoStartup", Boolean.class));
assertEquals(23, TestUtils.getPropertyValue(consumer, "phase"));
assertSame(context.getBean("annInput"), TestUtils.getPropertyValue(consumer, "inputChannel"));
assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.outputChannel"));
assertSame(context.getBean("annOutput"), TestUtils.getPropertyValue(consumer, "handler.discardChannel"));
assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.outputChannelName"));
assertEquals("annOutput", TestUtils.getPropertyValue(consumer, "handler.discardChannelName"));
assertEquals(1000L, TestUtils.getPropertyValue(consumer, "trigger.period"));
assertEquals(75L, TestUtils.getPropertyValue(consumer, "handler.messagingTemplate.sendTimeout"));
assertTrue(TestUtils.getPropertyValue(consumer, "handler.sendPartialResultOnExpiry", Boolean.class));
@@ -795,8 +803,8 @@ public class EnableIntegrationTests {
return new MessageHandler() {
@Override
public void handleMessage(Message<?> message) throws MessagingException {
asyncAnnotationProcessLatch().countDown();
asyncAnnotationProcessThread().set(Thread.currentThread());
asyncAnnotationProcessLatch().countDown();
asyncAnnotationProcessThread().set(Thread.currentThread());
}
};
}
@@ -996,7 +1004,7 @@ public class EnableIntegrationTests {
}
@MyServiceActivator1(inputChannel = "annInput1", autoStartup = "true",
adviceChain = { "annAdvice1" }, poller = @Poller(fixedRate = "2000") )
adviceChain = {"annAdvice1"}, poller = @Poller(fixedRate = "2000"))
public Integer annCount1() {
return 0;
}
@@ -1074,11 +1082,11 @@ public class EnableIntegrationTests {
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@ServiceActivator(autoStartup = "false",
phase = "23",
inputChannel = "annInput",
outputChannel = "annOutput",
adviceChain = { "annAdvice" },
poller = @Poller(fixedDelay = "1000"))
phase = "23",
inputChannel = "annInput",
outputChannel = "annOutput",
adviceChain = {"annAdvice"},
poller = @Poller(fixedDelay = "1000"))
public static @interface MyServiceActivator {
String inputChannel() default "";
@@ -1181,22 +1189,22 @@ public class EnableIntegrationTests {
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@ServiceActivator(autoStartup = "false",
phase = "23",
inputChannel = "annInput",
outputChannel = "annOutput",
adviceChain = { "annAdvice" },
poller = @Poller(fixedDelay = "1000"))
phase = "23",
inputChannel = "annInput",
outputChannel = "annOutput",
adviceChain = {"annAdvice"},
poller = @Poller(fixedDelay = "1000"))
public static @interface MyServiceActivatorNoLocalAtts {
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Aggregator(autoStartup = "false",
phase = "23",
inputChannel = "annInput",
outputChannel = "annOutput",
discardChannel = "annOutput",
poller = @Poller(fixedDelay = "1000"))
phase = "23",
inputChannel = "annInput",
outputChannel = "annOutput",
discardChannel = "annOutput",
poller = @Poller(fixedDelay = "1000"))
public static @interface MyAggregator {
String inputChannel() default "";
@@ -1219,13 +1227,13 @@ public class EnableIntegrationTests {
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Aggregator(autoStartup = "false",
phase = "23",
inputChannel = "annInput",
outputChannel = "annOutput",
discardChannel = "annOutput",
sendPartialResultsOnExpiry = false,
sendTimeout = 1000L,
poller = @Poller(fixedDelay = "1000"))
phase = "23",
inputChannel = "annInput",
outputChannel = "annOutput",
discardChannel = "annOutput",
sendPartialResultsOnExpiry = false,
sendTimeout = 1000L,
poller = @Poller(fixedDelay = "1000"))
public static @interface MyAggregatorDefaultOverrideDefaults {
boolean sendPartialResultsOnExpiry() default true;

View File

@@ -16,8 +16,12 @@
package org.springframework.integration.router;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.util.ArrayList;
import java.util.Collections;
@@ -333,7 +337,7 @@ public class RecipientListRouterTests {
assertNotNull(result1a);
assertNotNull(result1b);
assertEquals("test", result1a.getPayload());
assertEquals(1,new IntegrationMessageHeaderAccessor(result1a).getSequenceNumber().intValue());
assertEquals(1, new IntegrationMessageHeaderAccessor(result1a).getSequenceNumber().intValue());
assertEquals(2, new IntegrationMessageHeaderAccessor(result1a).getSequenceSize().intValue());
assertEquals(message.getHeaders().getId(), new IntegrationMessageHeaderAccessor(result1a).getCorrelationId());
assertEquals("test", result1b.getPayload());
@@ -426,6 +430,8 @@ public class RecipientListRouterTests {
router.setBeanFactory(beanFactory);
router.afterPropertiesSet();
router.handleMessage(new GenericMessage<String>("foo"));
assertSame(defaultChannel, TestUtils.getPropertyValue(router, "defaultOutputChannel"));
Mockito.verify(beanFactory).getBean(Mockito.eq("defaultChannel"), Mockito.eq(MessageChannel.class));
}