交易完成不确定

时间:2016-08-19 15:01:15

标签: spring-integration

我的流程设置如下:

<int:channel id="channel1">
    <int:queue/>
</int:channel>
<int:channel id="channel2">
    <int:queue/>
</int:channel>

<int:chain id="chain1" input-channel="channel1" output-channel="channel2">
    <int:poller>
        <int:transactional propagation="REQUIRES_NEW"/>
    </int:poller>
    <Authorzier/>
    <JMS_put1/>
    <DB_update_state1/>
</int:chain>

<int:chain id="chain2" input-channel="channel2" output-channel="nullChannel">
    <int:poller>
        <int:transactional propagation="REQUIRES_NEW"/>
    </int:poller>
    <Transformer/>
    <JMS_put2/>
    <DB_update_state2/>
</int:chain>

现在在某些情况下,chain2的事务在chain1的事务之前完成,我在数据库中有DB_state_1。

如何在将消息发送到chain1的output-channel之前强制完成chain1的事务?

我知道我可以使用TransactionSynchronization将消息发送到afterCommit()中的channel2,但我认为必须有更优雅的解决方案。

EDIT CURRENT WORKAROUND

@ServiceActivator
public void sendToDestinationFlow(Message<?> message) {
    TxSenderSyncer s = new TxSenderSyncer(message, this.channel, this.errorChannel);
    TransactionSynchronizationManager.registerSynchronization(s);
}

private static class TxSenderSyncer implements TransactionSynchronization {

    private Message<?> message;
    private MessageChannel channel;
    private MessageChannel errorChannel;

    public TxSenderSyncer(Message<?> message, MessageChannel channel, MessageChannel errorChannel) {
        this.message = message;
        this.channel = channel;
        this.errorChannel = errorChannel;
    }

    @Override
    public void afterCompletion(int paramInt) {
        if (paramInt == STATUS_ROLLED_BACK) {
            errorChannel.send(MessageBuilder.withPayload(new MessagingException(message, "Transaction rolled back")).build());
        } else {
            channel.send(message);
        }
    }
 }

1 个答案:

答案 0 :(得分:1)

您的问题是您有两个队列,这些队列在自己的轮询线程上处理。

因此,即使在第一个链的线程中工作结束之前,也可以将消息发送到第二个消息并进行处理。

请考虑将function attachHttpResponseHandling(httpPromise) { httpPromise .success(function(response) { response.ipv4 = INT_TO_STR_IP(response.ipv4); // Show new updated data to user after operation $scope.donor.saved_data = response.saved_data; $location.path("/"); }) .error(function(response) { $scope.donor.validation_errors = SERVER_VALIDATION_ERROR(response); }) ; } // Delete permanenty button action $scope.delete_donor = function(form) { attachHttpResponseHandling($http.delete(url)); }; // Save changes button action $scope.update_donor = function(form) { var body = $scope.donor.data; delete body.ipv4; attachHttpResponseHandling($http.put(url, body)); }; <request-handler-advice-chain>用于<tx:advice>。在这种情况下,只有DB更新将被包装到TX。在<DB_update_state1/>:[{3}}

完成工作后,会发送output-channel

修改

我们做了一些调查,如果您的handleRequestMessage不是基于交易QueueChannel,那么看起来您没有太多选择。在这种情况下,你应该确保&#34;民意调查&#34;该部分TX MessageStore处于模式QueueChannel,其中&#34;发送&#34;部分也是TX边界。甚至我们在TX提交之前将消息发送到该队列,它仍然可用于轮询直到实际提交。但是,是的,它仅适用于像READ_COMMITED这样的交易MessageStore

如果您不这样做,则不应该扩展比TX资源更广泛的事务边界。

要将您的JMS和数据库服务包装到同一个事务中,我们建议配置如下:

JdbcChannelMessageStore