【问题标题】:OptimisticLockingException with Camunda Service TaskCamunda 服务任务的 OptimisticLockingException
【发布时间】:2013-11-05 11:22:54
【问题描述】:

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

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

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,这似乎与我的问题有关。但是,我不清楚这是否是(不)想要的行为以及如何从 UserTask 访问 DelegateExecution-Object。

【问题讨论】:

  • 您描述的行为不是预期的。 out 变量的本质是什么?是实现Serializable的复杂java对象吗?
  • 这是一个Serializable,到目前为止,我们可以肯定至少发现了一个错误。
  • 代替runtimeService.setVariable && taskService.completeTask,考虑加入两个调用:taskService.completeTask(id, Map)
  • 在我们大多数情况下都适用的好主意,但是在一种情况下,我们需要在执行期间和任务完成之前存储变量。这种情况也有机制吗?
  • 我无法使用this gist 复制它。你的情况有什么不同?你能提供一个失败的测试用例吗?

标签: java business-process-management camunda


【解决方案1】:

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

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

  2. 显然有两种方法可以设置变量。一种方法是使用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 实现中)读取或写入的过程变量组合时才会发生异常

非常感谢您的所有意见。

【讨论】:

    【解决方案2】:

    您可以考虑在服务任务上使用异步延续。这将确保服务任务在新的事务/命令上下文中执行。 考虑阅读camunda documentation on transactions and asynchronous continuations

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

    【讨论】:

    • 我们已经考虑过这一点,事实上,ServiceTask 和 UserTask 在同一个事务中执行是我们真正欢迎并希望保留的功能。我们尝试了异步延续,并希望坚持同步语义。
    • 是的,你应该只在你真正需要的时候添加异步延续。
    猜你喜欢
    • 2013-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-01
    • 1970-01-01
    • 2022-12-21
    • 1970-01-01
    相关资源
    最近更新 更多