Inboud网关:
<int-http:inbound-gateway id="inbound.gateway"
request-channel="transactional.channel.input"
reply-channel="channel.output"
error-channel="channel.error"
request-payload-type="java.lang.String"
</int-http:inbound-gateway>
建议定义:
<tx:advice id="advice">
<tx:attributes>
<tx:method name="send" propagation="REQUIRES_NEW" rollback-for="MyClassException"/>
</tx:attributes>
</tx:advice>
建议配置:
<aop:config>
<aop:advisor advice-ref="advice" pointcut="bean(transactional.channel.input)"/>
</aop:config>
需要交易的链:
<int:chain input-channel="transactional.channel.input" output-channel="non.transactional.channel.input>
<int:service-activator ref="v1.registerUser.service" method="registerUser"/>
<int:service-activator ref="v1.saveObject.service" method="saveObject"/>
</int:chain>
需要事先执行的链以获取在最后一个跨期链步骤中生成的对象ID:
<int:chain input-channel="non.transactional.channel.input" output-channel="channel.output">
<int:service-activator ref="v1.getObjectId.service" method="getObjectId"/>
<int:object-to-json-transformer/>
</int:chain>
有了这个简化的上下文,当我访问getObjectId服务中的id时,事务尚未执行。
因此,事务似乎是在入站网关输出级别提交的。
答案 0 :(得分:9)
没有编写任何Java代码的另一个惊人的技巧:
<channel id="input"/>
<aop:config>
<aop:advisor advice-ref="txAdvice" pointcut="bean(input)"/>
</aop:config>
<tx:advice id="txAdvice">
<tx:attributes>
<tx:method name="send"/>
</tx:attributes>
</tx:advice>
有了这个,所有直接的单线程消息流将被包裹到发送到频道的消息上的TX 输入
答案 1 :(得分:4)
如果将MessagingGateway注入到您的代码中,您只需在网关处启动您的事务,并且由于所有通道都是直接的,因此整个流程将在同一事务中运行。只需使用@Transactional
注释您的网关方法,然后将<tx:annotation-driven/>
或@EnableTransactionManagement
添加到您的上下文(以及事务管理器)。
或者,如果您想要交易中的其他内容,您甚至可以更早地开始交易......
@Transactional
public void foo() {
...
Object reply = myGateway.exchange(Object foo);
...
}
请务必从另一个bean调用foo()
,以便包含foo()
的类包装在事务代理中(通过@EnableTransactionManagement或<tx:annotation-driven/>
)。
如果它是http入站网关等网关,请在入站网关后添加@Transaction
网关以启动事务。 (添加ref
与<gateway/>
交换Message<?>
并注明@Transactional
的{{1}}服务激活器。