【问题标题】:Keep transaction within Spring Integration flow在 Spring Integration 流程中保持事务
【发布时间】:2013-09-19 17:41:50
【问题描述】:

入站网关:

<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 时,事务还没有执行。

所以事务似乎是在入站网关输出级别提交的。

【问题讨论】:

  • 这取决于您的流程是如何开始的 - 您在 v1.getEvent.channel.input 的上游有什么?
  • 我有一个连接到一条链的入站网关,而这条链有 v1.getEvent.channel.input 作为输出通道,所以:(inbound-gateway) -> (chain) -> (code I have posted)

标签: transactions spring-integration


【解决方案1】:

一个更神奇的技巧,无需编写任何 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

【讨论】:

  • 您好,Artem。回到这个话题来确定。我将这种方法与链输入通道一起使用,因此将在链完成时进行事务提交,对吗?因为我意识到,当我在持久化它后请求它时,对象 id 为空,但它正确存储在数据库中。
  • 对,因为底层链通道的所有其他send 都在您的input 通道的线程内完成。
  • 嗨,Artem,我已更改问题以向您展示当前的简化上下文,因为在链完成时交易并未执行(我已通过 ecliselink FINE 日志确认)。
  • 安东尼奥,如果你开始新的问题,那就更好了。但看起来你误解了我的回答。事务绑定到方法调用的线程。在您的情况下,它是“transactional.channel.input”bean 的“send()”。但是,如果所有其他通道在下游流中都是直接,那么所有其他“发送”和“处理消息”都将在该事务中。为了满足您对 TX 提交的要求,您将“non.transactional.channel.input”设置为执行程序通道或队列。希望清楚
  • 我已经对其进行了编辑,因为我认为其他与此相关的情况的人可以通过新示例最容易地看到这一点……无论如何,对不起。顺便说一句,我发现 object id null 这是一个与合并方法有关的问题,所以它工作得很好:)
【解决方案2】:

如果它是一个注入到您的代码中的 MessagingGateway,您可以简单地在网关处启动您的事务,并且由于所有通道都是直接的,因此整个流程将在同一个事务中运行。只需使用 @Transactional 注释您的网关方法,并将 &lt;tx:annotation-driven/&gt;@EnableTransactionManagement 添加到您的上下文(和事务管理器)中。

或者,如果您想要交易中的其他内容,您可以更早地开始交易......

@Transactional
public void foo() {
    ...
    Object reply = myGateway.exchange(Object foo);
    ...
}

请务必从另一个 bean 调用 foo(),以便将包含 foo() 的类包装在事务代理中(通过 @EnableTransactionManagement 或 &lt;tx:annotation-driven/&gt;)。

如果是http入站网关等网关,在入站网关后添加@Transactional网关,开始事务。 (添加一个服务激活器,refs 和 &lt;gateway/&gt; 交换 Message&lt;?&gt; 并带有 @Transactional 注释)。

【讨论】:

  • 感谢加里的回复!我终于选择了 Artem 解决方案,但还是谢谢 :)
猜你喜欢
  • 2019-08-04
  • 2016-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
  • 1970-01-01
相关资源
最近更新 更多