这个问题已经得到了回答,但解决方案对我来说还不是很有效。
Activiti异步行为相当简单,只允许用户启用一个标志,该标志告诉activiti引擎在执行队列(管理线程池)中插入此类任务。
我想要的不是将java服务任务插入池中,而是使其行为钝化,并且仅在接收到外部信号和/或调用回调时才完成此类任务。
我的尝试是:
class customAsyncTask extends TaskActivityBehavior {
override def execute(execution: ActivityExecution): Unit = {
val future = Future {
println(s"Executing customAsyncTask -> ${execution.getCurrentActivityName}, ${cur}")
}
future.onComplete {
case Success(result) => leave(execution)
case _ => // whatever
}
}
def signal(processInstanceId : String, transition : String) = {
val commandExecutor = main.processEngine.getProcessEngineConfiguration.asInstanceOf[ProcessEngineConfigurationImpl].getCommandExecutor
val command = new customSignal(processInstanceId, transition)
commandExecutor.execute(command)
}
}在我之前的代码示例中,我注册了一个scala future回调,当调用它时,它将终止当前的活动并转到下一个活动。
我还有一个signal方法,它构建一个自定义信号,它基于processId和一个名称调用execution.take,并进行适当的转换。
在这两种情况下,我都得到了以下错误(底层堆栈有一点变化)
java.lang.NullPointerException
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:636)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:629)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.take(ExecutionEntity.java:453)
at org.activiti.engine.impl.persistence.entity.ExecutionEntity.take(ExecutionEntity.java:431)
at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performOutgoingBehavior(BpmnActivityBehavior.java:140)
at org.activiti.engine.impl.bpmn.behavior.BpmnActivityBehavior.performDefaultOutgoingBehavior(BpmnActivityBehavior.java:66)
at org.activiti.engine.impl.bpmn.behavior.FlowNodeActivityBehavior.leave(FlowNodeActivityBehavior.java:44)
at org.activiti.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior.leave(AbstractBpmnActivityBehavior.java:47)不幸的是,引擎很可能会在execute方法返回时擦除有关执行的信息,即使没有调用complete/leave/take。即使我的回调在上下文中有execution对象,当我使用它的进程ID查询信息时,我收到的所有信息都是空的。
那么,我到底做错了什么呢?我怎样才能达到我想要的行为?
发布于 2016-05-11 22:48:49
我没有看到任何具体的东西,我会说你需要扩展一个实现SignalableActivityBehavior的类,但我认为TaskActivityBehavior实际上做到了这一点。
虽然堆栈表明NPE来自leave(),但我搞不懂为什么leave调用" take“,因为take是一个转换事件,实际上应该只在标记为同步的任务上发生。
我所能提供的是,Camunda有一个类似于您的场景的示例实现。你也许可以用这个来帮助你:
发布于 2016-05-12 00:41:32
看起来activiti使用了线程局部变量,这意味着从scala线程(scala执行器上下文)调用方法是没有意义的,因为它们不共享上下文。
要解决这个问题,我需要从回调中做的所有事情就是发出一个信号调用,就像我从远程系统调用一样。唯一的区别是我不需要保存我的流程实例标识符。
代码如下所示:
class AsynchronousServiceTask extends AbstractBpmnActivityBehavior {
val exec_id : String = "executionId"
override def execute(execution : ActivityExecution) = {
val future = Future { println("Something") }
future onComplete {
case _ => myobject.callSignalForMe(execution.getId)
}
}
override def signal(execution : ActivityExecution, signalName : String, signalData : AnyRef) = {
println("Signal called, leaving current activity..")
leave(execution)
}
}基本上,myobject持有runTimeEngine并将在ThreadLocal上下文中注入信号。一切都很干净,并按预期工作。
https://stackoverflow.com/questions/37139222
复制相似问题