INT-3551: Idempotent Receiver: Add value-strategy

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

* Rename `MetadataKeyStrategy` -> `MetadataEntryStrategy`
* Add `valueStrategy` to the `MetadataStoreSelector`
* Add `value-strategy` and `value-expression` to the `<idempotent-receiver>`

INT-3551: Add `@IR` support on service methods

Rework `MetadataKeyStrategy` just to the `MessageProcessor`
Fix Docs

Minor Doc Polishing.
This commit is contained in:
Artem Bilan
2014-11-06 19:42:57 +02:00
committed by Gary Russell
parent 1018fcf361
commit 0cc9273a2e
14 changed files with 327 additions and 173 deletions

View File

@@ -16,11 +16,19 @@
<idempotent-receiver id="selectorInterceptor" endpoint="foo" selector="selector"/>
<beans:bean id="keyStrategy" class="org.mockito.Mockito" factory-method="mock">
<beans:constructor-arg value="org.springframework.integration.metadata.MetadataKeyStrategy"/>
<beans:constructor-arg value="org.springframework.integration.handler.MessageProcessor"/>
</beans:bean>
<idempotent-receiver id="strategyInterceptor" endpoint="foo" key-strategy="keyStrategy"
discard-channel="nullChannel" throw-exception-on-rejection="true"/>
<beans:bean id="valueStrategy" class="org.mockito.Mockito" factory-method="mock">
<beans:constructor-arg value="org.springframework.integration.handler.MessageProcessor"/>
</beans:bean>
<idempotent-receiver id="strategyInterceptor"
endpoint="foo"
key-strategy="keyStrategy"
value-strategy="valueStrategy"
discard-channel="nullChannel"
throw-exception-on-rejection="true"/>
<beans:bean id="store" class="org.springframework.integration.metadata.SimpleMetadataStore"/>
@@ -31,7 +39,7 @@
<context:property-placeholder properties-ref="properties"/>
<idempotent-receiver id="expressionInterceptor" endpoint="foo, ${bar}"
metadata-store="store"
key-expression="headers.foo"/>
metadata-store="store"
key-expression="headers.foo"/>
</beans:beans>

View File

@@ -46,9 +46,9 @@ import org.springframework.context.support.GenericApplicationContext;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.InputStreamResource;
import org.springframework.integration.core.MessageSelector;
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
import org.springframework.integration.handler.MessageProcessor;
import org.springframework.integration.handler.advice.IdempotentReceiverInterceptor;
import org.springframework.integration.metadata.ExpressionMetadataKeyStrategy;
import org.springframework.integration.metadata.MetadataKeyStrategy;
import org.springframework.integration.metadata.MetadataStore;
import org.springframework.integration.selector.MetadataStoreSelector;
import org.springframework.messaging.MessageChannel;
@@ -79,7 +79,10 @@ public class IdempotentReceiverParserTests {
private IdempotentReceiverInterceptor strategyInterceptor;
@Autowired
private MetadataKeyStrategy keyStrategy;
private MessageProcessor<String> keyStrategy;
@Autowired
private MessageProcessor<String> valueStrategy;
@Autowired
@Qualifier("nullChannel")
@@ -113,6 +116,7 @@ public class IdempotentReceiverParserTests {
Object messageSelector = getPropertyValue(this.strategyInterceptor, "messageSelector");
assertThat(messageSelector, instanceOf(MetadataStoreSelector.class));
assertSame(this.keyStrategy, getPropertyValue(messageSelector, "keyStrategy"));
assertSame(this.valueStrategy, getPropertyValue(messageSelector, "valueStrategy"));
@SuppressWarnings("unchecked")
Map<String, List<String>> idempotentEndpoints =
(Map<String, List<String>>) getPropertyValue(this.idempotentReceiverAutoProxyCreator,
@@ -129,7 +133,7 @@ public class IdempotentReceiverParserTests {
assertThat(messageSelector, instanceOf(MetadataStoreSelector.class));
assertSame(this.store, getPropertyValue(messageSelector, "metadataStore"));
Object keyStrategy = getPropertyValue(messageSelector, "keyStrategy");
assertThat(keyStrategy, instanceOf(ExpressionMetadataKeyStrategy.class));
assertThat(keyStrategy, instanceOf(ExpressionEvaluatingMessageProcessor.class));
assertThat(keyStrategy.toString(), containsString("headers.foo"));
@SuppressWarnings("unchecked")
Map<String, List<String>> idempotentEndpoints =
@@ -176,40 +180,66 @@ public class IdempotentReceiverParserTests {
catch (BeanDefinitionParsingException e) {
assertThat(e.getMessage(),
containsString("The 'selector' attribute is mutually exclusive with 'metadata-store', " +
"'key-strategy' or 'key-expression'"));
"'key-strategy', 'key-expression', 'value-strategy' or 'value-expression'"));
}
}
@Test
public void testSelectorAndStrategy() throws Exception {
public void testSelectorAndKeyStrategy() throws Exception {
try {
bootStrap("selector-and-strategy");
bootStrap("selector-and-key-strategy");
fail("BeanDefinitionParsingException expected");
}
catch (BeanDefinitionParsingException e) {
assertThat(e.getMessage(),
containsString("The 'selector' attribute is mutually exclusive with 'metadata-store', " +
"'key-strategy' or 'key-expression'"));
"'key-strategy', 'key-expression', 'value-strategy' or 'value-expression'"));
}
}
@Test
public void testSelectorAndExpression() throws Exception {
public void testSelectorAndKeyExpression() throws Exception {
try {
bootStrap("selector-and-expression");
bootStrap("selector-and-key-expression");
fail("BeanDefinitionParsingException expected");
}
catch (BeanDefinitionParsingException e) {
assertThat(e.getMessage(),
containsString("The 'selector' attribute is mutually exclusive with 'metadata-store', " +
"'key-strategy' or 'key-expression'"));
"'key-strategy', 'key-expression', 'value-strategy' or 'value-expression'"));
}
}
@Test
public void testStrategyAndExpression() throws Exception {
public void testSelectorAndValueStrategy() throws Exception {
try {
bootStrap("strategy-and-expression");
bootStrap("selector-and-value-strategy");
fail("BeanDefinitionParsingException expected");
}
catch (BeanDefinitionParsingException e) {
assertThat(e.getMessage(),
containsString("The 'selector' attribute is mutually exclusive with 'metadata-store', " +
"'key-strategy', 'key-expression', 'value-strategy' or 'value-expression'"));
}
}
@Test
public void testSelectorAndValueExpression() throws Exception {
try {
bootStrap("selector-and-value-expression");
fail("BeanDefinitionParsingException expected");
}
catch (BeanDefinitionParsingException e) {
assertThat(e.getMessage(),
containsString("The 'selector' attribute is mutually exclusive with 'metadata-store', " +
"'key-strategy', 'key-expression', 'value-strategy' or 'value-expression'"));
}
}
@Test
public void testKeyStrategyAndKeyExpression() throws Exception {
try {
bootStrap("key-strategy-and-key-expression");
fail("BeanDefinitionParsingException expected");
}
catch (BeanDefinitionParsingException e) {
@@ -218,6 +248,18 @@ public class IdempotentReceiverParserTests {
}
}
@Test
public void testValueStrategyAndValueExpression() throws Exception {
try {
bootStrap("value-strategy-and-value-expression");
fail("BeanDefinitionParsingException expected");
}
catch (BeanDefinitionParsingException e) {
assertThat(e.getMessage(),
containsString("The 'value-strategy' and 'value-expression' attributes are mutually exclusive"));
}
}
private ApplicationContext bootStrap(String configProperty) throws Exception {
PropertiesFactoryBean pfb = new PropertiesFactoryBean();
pfb.setLocation(new ClassPathResource(

View File

@@ -13,8 +13,17 @@ without-endpoint=<int:idempotent-receiver endpoint="" selector="selector"/>
selector-and-store=<int:idempotent-receiver endpoint="foo" selector="selector" metadata-store="store"/>
selector-and-strategy=<int:idempotent-receiver endpoint="foo" selector="selector" key-strategy="strategy"/>
selector-and-key-strategy=<int:idempotent-receiver endpoint="foo" selector="selector" key-strategy="strategy"/>
selector-and-expression=<int:idempotent-receiver endpoint="foo" selector="selector" key-expression="expression"/>
selector-and-key-expression=<int:idempotent-receiver endpoint="foo" selector="selector" key-expression="expression"/>
strategy-and-expression=<int:idempotent-receiver endpoint="foo" key-strategy="strategy" key-expression="expression"/>
selector-and-value-strategy=<int:idempotent-receiver endpoint="foo" selector="selector" value-strategy="strategy"/>
selector-and-value-expression=<int:idempotent-receiver endpoint="foo" selector="selector" \
value-expression="expression"/>
key-strategy-and-key-expression=<int:idempotent-receiver endpoint="foo" key-strategy="strategy" \
key-expression="expression"/>
value-strategy-and-value-expression=<int:idempotent-receiver endpoint="foo" key-strategy="strategy" \
value-strategy="strategy" value-expression="expression"/>

View File

@@ -33,16 +33,14 @@ import org.mockito.Mockito;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.integration.IntegrationMessageHeaderAccessor;
import org.springframework.integration.MessageRejectedException;
import org.springframework.integration.handler.ExpressionEvaluatingMessageProcessor;
import org.springframework.integration.metadata.ConcurrentMetadataStore;
import org.springframework.integration.metadata.ExpressionMetadataKeyStrategy;
import org.springframework.integration.metadata.MetadataStore;
import org.springframework.integration.metadata.SimpleMetadataStore;
import org.springframework.integration.selector.MetadataStoreSelector;
import org.springframework.integration.support.DefaultMessageBuilderFactory;
import org.springframework.integration.support.MessageBuilderFactory;
import org.springframework.integration.support.utils.IntegrationUtils;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageChannel;
@@ -86,7 +84,8 @@ public class IdempotentReceiverTests {
@Test
public void testIdempotentReceiverInterceptor() {
ConcurrentMetadataStore store = new SimpleMetadataStore();
ExpressionMetadataKeyStrategy idempotentKeyStrategy = new ExpressionMetadataKeyStrategy("payload");
ExpressionEvaluatingMessageProcessor<String> idempotentKeyStrategy =
new ExpressionEvaluatingMessageProcessor<>(new SpelExpressionParser().parseExpression("payload"));
BeanFactory beanFactory = Mockito.mock(BeanFactory.class);
idempotentKeyStrategy.setBeanFactory(beanFactory);
IdempotentReceiverInterceptor idempotentReceiverInterceptor =