我的流程设置如下:
<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);
}
}
}
答案 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