INT-2649: DelayHandler: tx & adviceChain support

* 'delayer-type' XSD: add `<transactional>` & `<advice-chain>`
* move `PollerParser#configureAdviceChain` into `IntegrationNamespaceUtils`
* DelayerParser: parsing `<transactional>` & `<advice-chain>` via `IntegrationNamespaceUtils#configureAdviceChain`
* DelayHandler: add `adviceChain` property
* DelayHandler: introduce `ReleaseMessageHandler` to apply `adviceChain` capabilities around `DelayHandler#doReleaseMessage`
* DelayerParserTests: tests for introduced sub-elements
* DelayerHandlerRescheduleIntegrationTests: test for transaction boundaries with intentional rollback in the message-flow after message release

JIRA: https://jira.springsource.org/browse/INT-2649

Resolve conflicts; polishing.
This commit is contained in:
Artem Bilan
2012-07-10 21:38:47 +03:00
committed by Gary Russell
parent fc1417ed39
commit d4e135b13d
10 changed files with 265 additions and 21 deletions

View File

@@ -2,11 +2,13 @@
<beans:beans xmlns="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration.xsd">
http://www.springframework.org/schema/integration/spring-integration.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
<channel id="input"/>
@@ -34,10 +36,37 @@
default-delay="0"
message-store="testMessageStore"/>
<delayer id="delayerWithTransactional"
input-channel="input"
output-channel="output"
default-delay="0">
<transactional/>
</delayer>
<delayer id="delayerWithAdviceChain"
input-channel="input"
output-channel="output"
default-delay="0">
<advice-chain>
<ref bean="testAdviceBean"/>
<tx:advice>
<tx:attributes>
<tx:method name="*" read-only="true" propagation="REQUIRES_NEW"/>
</tx:attributes>
</tx:advice>
</advice-chain>
</delayer>
<beans:bean id="testScheduler" class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler"
p:poolSize="7"
p:waitForTasksToCompleteOnShutdown="true"/>
<beans:bean id="testMessageStore" class="org.springframework.integration.store.SimpleMessageStore"/>
<beans:bean id="testAdviceBean" class="org.springframework.integration.config.xml.TestAdviceBean">
<beans:constructor-arg value="-1"/>
</beans:bean>
<beans:bean id="transactionManager" class="org.springframework.integration.util.TestTransactionManager"/>
</beans:beans>

View File

@@ -17,12 +17,17 @@
package org.springframework.integration.config.xml;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.HashMap;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
@@ -32,6 +37,11 @@ import org.springframework.integration.handler.DelayHandler;
import org.springframework.integration.test.util.TestUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.MatchAlwaysTransactionAttributeSource;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionAttributeSource;
import org.springframework.transaction.interceptor.TransactionInterceptor;
/**
* @author Mark Fisher
@@ -45,7 +55,6 @@ public class DelayerParserTests {
@Autowired
private ApplicationContext context;
@Test
public void defaultScheduler() {
Object endpoint = context.getBean("delayerWithDefaultScheduler");
@@ -91,4 +100,37 @@ public class DelayerParserTests {
assertEquals(context.getBean("testMessageStore"), accessor.getPropertyValue("messageStore"));
}
@Test //INT-2649
public void transactionalSubElement() {
Object endpoint = context.getBean("delayerWithTransactional");
DelayHandler delayHandler = TestUtils.getPropertyValue(endpoint, "handler", DelayHandler.class);
List adviceChain = TestUtils.getPropertyValue(delayHandler, "delayedAdviceChain", List.class);
assertEquals(1, adviceChain.size());
Object advice = adviceChain.get(0);
assertTrue(advice instanceof TransactionInterceptor);
TransactionAttributeSource transactionAttributeSource = ((TransactionInterceptor) advice).getTransactionAttributeSource();
assertTrue(transactionAttributeSource instanceof MatchAlwaysTransactionAttributeSource);
TransactionDefinition definition = transactionAttributeSource.getTransactionAttribute(null, null);
assertEquals(TransactionDefinition.PROPAGATION_REQUIRED, definition.getPropagationBehavior());
assertEquals(TransactionDefinition.ISOLATION_DEFAULT, definition.getIsolationLevel());
assertEquals(TransactionDefinition.TIMEOUT_DEFAULT, definition.getTimeout());
assertFalse(definition.isReadOnly());
}
@Test //INT-2649
public void adviceChainSubElement() {
Object endpoint = context.getBean("delayerWithAdviceChain");
DelayHandler delayHandler = TestUtils.getPropertyValue(endpoint, "handler", DelayHandler.class);
List adviceChain = TestUtils.getPropertyValue(delayHandler, "delayedAdviceChain", List.class);
assertEquals(2, adviceChain.size());
assertSame(context.getBean("testAdviceBean"), adviceChain.get(0));
Object txAdvice = adviceChain.get(1);
assertEquals(TransactionInterceptor.class, txAdvice.getClass());
TransactionAttributeSource transactionAttributeSource = ((TransactionInterceptor) txAdvice).getTransactionAttributeSource();
assertEquals(NameMatchTransactionAttributeSource.class, transactionAttributeSource.getClass());
HashMap nameMap = TestUtils.getPropertyValue(transactionAttributeSource, "nameMap", HashMap.class);
assertEquals("{*=PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT,readOnly}", nameMap.toString());
}
}

View File

@@ -37,7 +37,13 @@
<chain input-channel="delayerInsideChain" output-channel="outputA">
<transformer expression="payload.toUpperCase()"/>
<delayer id="delayerInsideChain" default-delay="1000"/>
<delayer id="delayerInsideChain" default-delay="1000">
<advice-chain>
<beans:bean class="org.springframework.integration.config.xml.TestAdviceBean">
<beans:constructor-arg value="0"/>
</beans:bean>
</advice-chain>
</delayer>
<transformer expression="payload.toLowerCase()"/>
</chain>