我们在具有以下场景的 Camunda 进程中看到 OptimisticLockingExceptions:
该过程由一个 UserTask 和一个 Gateway 和一个 ServiceTask 组成。 UserTask 执行
runtimeService.setVariable(execId, "object", out);`.
taskService.complete(taskId);
以下 ServiceTask 使用“对象”作为输入变量(不修改它),并在完成后抛出
OptimisticLockingException
。我的问题似乎源于这样一个事实,即 taskService.complete()
在刷新 UserTask 中设置的变量之前立即执行 ServiceTask。我遇到了另一个相关问题,当我在一个 UserTask 中执行
runtimeService.setVariable(Map<Strong, Boolean>)
并尝试访问 Map 的成员作为该 UserTask 之后的网关中的转换保护时。我找到了以下文章:http://forums.activiti.org/content/urgenterror-updated-another-transaction-concurrently 似乎与我的问题有关。但是,我不清楚这是否是(不)想要的行为以及如何从 UserTask 访问
DelegateExecution
-Object。 最佳答案
经过漫长而繁琐的搜索,我们认为,我们已经解决了 camunda 的两个问题,这些问题(加在一起)导致了原始问题的异常。
equals
来确定是否必须将流程变量写回数据库。这甚至在只读取变量而不设置变量时也会发生。由于 equals
由数组上的指针标识定义,如果序列化对象已被序列化多次,则它永远不会被确定为“相等”。我们发现,在 runtimeService.setVariable()
时,单个 completeTask()
会导致四个 db-updates(一个用于 setVariable 本身,另外三个用于各种 camunda 内部验证操作)。我们认为这是一个错误,并将向 camunda 提交错误报告。 runtimeService.setVariable()
,另一种方法是使用 delegateTask/delegateExecution.setVariable()
。同时使用两种方式时存在一些缺陷。虽然我们无法将设置简化为简单的单元测试,但我们已经确定了发生异常必须涉及的几个组件:2.1 我们在任务开始时使用
TaskListener
设置一些上下文变量这个任务监听器使用 runtimeService.setVariable()
而不是 delegateTask.setVariable()
。在我们更改之后,异常消失了。2.2 我们在任务执行期间使用(并且仍在使用)
runtimeService.setVariable()
。在我们切换到 completeTask(Variables)
并省略 runtimeService.setVariable()
调用之后,异常也消失了。然而,这不是一个永久的解决方案,因为我们必须在任务执行期间存储流程变量。2.3 异常仅在通过
delegate<X>.getVariable()
方式读取或写入流程变量时(通过我们的代码或隐含在带有网关和 serviceTasks 或 completeTask(HashMap)
的 juel-parsing 的 camunda 实现中)发生非常感谢您的所有意见。