我们在具有以下场景的 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 的两个问题,这些问题(加在一起)导致了原始问题的异常。

  • 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 实现中)发生

    非常感谢您的所有意见。

    10-08 02:25