INT-2685 Transaction Synchronization
Remove M3 disposition-* attributes on File/(S)FTP inbound adapters. Add <pseudo-transactional/> and <transaction-synchronization/> elements to <poller/>. These elements provide the following attributes: * on-success-expression * on-success-result-channel * on-failure-expression * on-failure-result-channel * send-timeout <transaction-synchronization/> synchronizes these expression evaluations with the transaction, such that they are executed immediately after the commit/rollback. <psuedo-transactional/> is used for a non-transactional poller. When an <advice-chain/> is provided to the poller, <psuedo-transactional/> and <transaction-synchronization/> are synonyms; and the behavior is dictated by whether or not the <advice-chain/> contains a transaction advice. It is recommended that <pseudo-transactional/> is used when the <advice-chain/> does not have a txAdvice, and <transaction-synchronization/> when it does, but the framework does not enforce this. The expressions have the original (polled) message as the #root variable. In addition, a BeanResolver is provided, allowing expressions such as '@someBean.handleSuccess(payload)'. MessageSources may also implement PseudoTransactionalMessageSource. This has a number of methods allowing more flexibility in transactional and non-transactional environents. For example, for backwards compatibility. the mail-inbound-channel-adapter deletes its polled message after the receive() rather than after the polled message is sent (when running in a non-transactional poller). However, when running in a transactional poller, the delete is done after the transaction commits (but not when it rolls back). In addition, MessageSources that implement this interface can optionally provide an arbitrary object to the success/failure expressions in a variable named '#resource'. INT-2685 Polishing PR Review Comments Add tests for non-tx PseudoTransactionalMessageSource
This commit is contained in:
committed by
Oleg Zhurakousky
parent
d6623bda82
commit
4de02fa75e
@@ -218,42 +218,6 @@
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="disposition-expression" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
SpEL expression to be executed after the message has been sent. If running in a transactional
|
||||
poller, it will be executed after the transaction commits. If running in a non-transactional
|
||||
poller it will execute after the message is sent. Note that the actual point of execution
|
||||
depends on any asynchronous handoffs on the downstream flow. It will be executed when the
|
||||
current thread returns from the channel send. The root object of the expression is the
|
||||
original message (with a File payload). Examples: "payload.delete()",
|
||||
"payload.renameTo('/foo/bar/' + payload.name)", "@someBean.doSomething(payload)".
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="disposition-result-channel" type="xsd:string" default="nullChannel">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
If a 'disposition-expression' is provided, and that expression returns a result, the result
|
||||
is sent to this channel, with the original message payload and a 'file_dispositionResult'
|
||||
header containing the result of the expression execution.
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.MessageChannel"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="disposition-send-timeout" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
If a 'disposition-expression' is provided, and that expression returns a result, the result
|
||||
is sent to this disposition-result-channel. This timeout specifies how long to wait if
|
||||
that channel might block (such as a bounded queue channel that is full). Default infinity.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
@@ -24,14 +24,19 @@
|
||||
local-filename-generator-expression="#this.toUpperCase() + '.a'"
|
||||
comparator="comparator"
|
||||
temporary-file-suffix=".foo"
|
||||
remote-directory="foo/bar"
|
||||
disposition-expression="'foo'"
|
||||
disposition-result-channel="dispoChannel"
|
||||
disposition-send-timeout="123">
|
||||
<int:poller fixed-rate="1000"/>
|
||||
remote-directory="foo/bar">
|
||||
<int:poller fixed-rate="1000">
|
||||
<int:psuedo-transactional on-success-expression="'foo'"
|
||||
on-success-result-channel="successChannel"
|
||||
on-failure-expression="'bar'"
|
||||
on-failure-result-channel="failureChannel"
|
||||
send-timeout="123" />
|
||||
</int:poller>
|
||||
</int-ftp:inbound-channel-adapter>
|
||||
|
||||
<int:channel id="dispoChannel" />
|
||||
<int:channel id="successChannel" />
|
||||
|
||||
<int:channel id="failureChannel" />
|
||||
|
||||
<bean id="comparator" class="org.mockito.Mockito" factory-method="mock">
|
||||
<constructor-arg value="java.util.Comparator"/>
|
||||
|
||||
@@ -35,7 +35,6 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.expression.Expression;
|
||||
import org.springframework.integration.MessageChannel;
|
||||
import org.springframework.integration.endpoint.SourcePollingChannelAdapter;
|
||||
import org.springframework.integration.file.FileReadingMessageSource;
|
||||
import org.springframework.integration.file.remote.session.CachingSessionFactory;
|
||||
import org.springframework.integration.file.remote.session.Session;
|
||||
import org.springframework.integration.ftp.filters.FtpSimplePatternFileListFilter;
|
||||
@@ -78,12 +77,16 @@ public class FtpInboundChannelAdapterParserTests {
|
||||
assertNotNull(filter);
|
||||
Object sessionFactory = TestUtils.getPropertyValue(fisync, "sessionFactory");
|
||||
assertTrue(DefaultFtpSessionFactory.class.isAssignableFrom(sessionFactory.getClass()));
|
||||
FileReadingMessageSource source = TestUtils.getPropertyValue(inbound, "fileSource", FileReadingMessageSource.class);
|
||||
assertEquals("foo", TestUtils.getPropertyValue(source, "dispositionExpression", Expression.class).getValue());
|
||||
assertSame(ac.getBean("dispoChannel"), TestUtils.getPropertyValue(
|
||||
TestUtils.getPropertyValue(source, "dispositionMessagingTemplate"), "defaultChannel"));
|
||||
assertEquals("foo", TestUtils.getPropertyValue(adapter, "onSuccessExpression", Expression.class).getValue());
|
||||
assertSame(ac.getBean("successChannel"), TestUtils.getPropertyValue(
|
||||
TestUtils.getPropertyValue(adapter, "onSuccessMessagingTemplate"), "defaultChannel"));
|
||||
assertEquals(123L, TestUtils.getPropertyValue(
|
||||
TestUtils.getPropertyValue(source, "dispositionMessagingTemplate"), "sendTimeout"));
|
||||
TestUtils.getPropertyValue(adapter, "onSuccessMessagingTemplate"), "sendTimeout"));
|
||||
assertEquals("bar", TestUtils.getPropertyValue(adapter, "onFailureExpression", Expression.class).getValue());
|
||||
assertSame(ac.getBean("failureChannel"), TestUtils.getPropertyValue(
|
||||
TestUtils.getPropertyValue(adapter, "onFailureMessagingTemplate"), "defaultChannel"));
|
||||
assertEquals(123L, TestUtils.getPropertyValue(
|
||||
TestUtils.getPropertyValue(adapter, "onFailureMessagingTemplate"), "sendTimeout"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user