4

我们在 Camunda 进程中看到 OptimisticLockingExceptions,场景如下:

该流程由一个用户任务、一个网关和一个服务任务组成。用户任务执行

runtimeService.setVariable(execId, "object", out);`. 
taskService.complete(taskId);

以下 ServiceTask 使用“object”作为输入变量(不修改它),并且在完成时抛出OptimisticLockingException. 我的问题似乎源于这样一个事实,即taskService.complete()在刷新 UserTask 中设置的变量之前立即执行 ServiceTask。

我遇到了另一个相关的问题,当我在一个 UserTask 中执行runtimeService.setVariable(Map<Strong, Boolean>)并尝试访问 Map 的成员作为该 UserTask 之后的网关中的转换守卫时。

我找到了以下文章:http ://forums.activiti.org/content/urgenterror-updated-another-transaction-concurrently这似乎与我的问题有某种关系。但是,我不清楚这是否是(不)想要的行为以及如何DelegateExecution从 UserTask 访问 -Object。

4

2 回答 2

2

经过我们认为的漫长而繁琐的搜索,我们已经确定了 camunda 的两个问题(加在一起)导致原始问题的异常。

  1. Camunda 使用equals序列化对象(由字节数组表示)来确定是否必须将流程变量写回数据库。这甚至发生在仅读取而不设置变量时。正如equals数组上的指针标识所定义的那样,如果序列化对象被序列化了多次,则永远不会确定它“相等”。我们发现,一次runtimeService.setVariable()会导致四个数据库更新completeTask()(一个用于 setVariable 本身,另外三个用于各种 camunda 内部验证操作)。我们认为这是一个错误,并将向 camunda 提交错误报告。

  2. 显然有两种方法可以设置变量。一种方式是使用runtimeService.setVariable(),另一种是使用delegateTask/delegateExecution.setVariable()。同时使用两种方式时存在一些缺陷。虽然我们无法将设置简化为简单的单元测试,但我们已经确定了发生异常必须涉及的几个组件:

2.1 我们使用 aTaskListener在任务开始时设置一些上下文变量,这个任务侦听器使用runtimeService.setVariable()而不是delegateTask.setVariable(). 在我们改变它之后,异常消失了。

runtimeService.setVariable()2.2 我们在任务执行期间使用(并且仍在使用) 。在我们切换到completeTask(Variables)并省略runtimeService.setVariable()调用后,异常也消失了。然而,这不是一个永久的解决方案,因为我们必须在任务执行期间存储流程变量。

2.3 异常仅在通过方式读取或写入过程变量时发生delegate<X>.getVariable()(通过我们的代码或隐含在使用网关和 serviceTasks 的 juel-parsing 的 camunda 实现中completeTask(HashMap)

非常感谢您的所有意见。

于 2013-11-06T20:52:35.340 回答
0

您可以考虑在服务任务上使用异步延续。这将确保服务任务在新的事务/命令上下文中执行。考虑阅读有关事务和异步延续的 camunda 文档

DelegateExecution对象旨在为服务任务 ( JavaDelegate) 实现提供对流程实例变量的访问。它不适用于用户任务。

于 2013-11-05T13:35:43.557 回答