Cancellation Design Pattern on UserTask via EscalationCatch + MessageThrow + Event Subprocess (cleanUp) = ENGINE-16004 PvmException has no current activity

Spring-Boot: (v3.1.4)
Camunda Platform: (v7.20.0)

Hi all,
My Cancellation Design Pattern:

  1. During work Dummy UserTask-1 (assigned or not) comes from UI … a command to cancel:

  2. Escalation throw: ESCE01_CancelProcess
    public void escalationThrowByTaskId(String escalationCode, String taskId) {
    Task task = getTask(taskId);
    Map<String, Object> variables = Variables.createVariables()
    .putValue(VAR_currentEscalation, escalationCode);
    taskService.handleEscalation(taskId/task.getExecutionId()/, escalationCode, variables);
    log.debug(“handleEscalation was fired! Code: ‘{}’, taskId: ‘{}’, processInstanceId: ‘{}’”, escalationCode, taskId, task.getProcessInstanceId());
    }

  3. EscalationCatch

  4. Token goes to throw a ME01_Cancelled_by_User

    public void messageThrowForPi(String messageId, String processInstanceId) {
    runtimeService.createMessageCorrelation(messageId)
    .processInstanceId(processInstanceId)
    .correlate();
    }

2nd possibility, to throw the message is: ( Whitch is the best one ?)
Execution e = runtimeService.createExecutionQuery()
.processInstanceId(processInstanceId)
.messageEventSubscriptionName(messageId)
.singleResult();
runtimeService.messageEventReceived(messageId, e.getId());

Message Throw is a End State, but Token should go to Event SubProcess (see left)

  1. After throwing of Message Event i have this exception:

2024-01-18 16:17:33,482 ERROR org.camunda.bpm.engine.context : ENGINE-16004 Exception while closing command context: Execution ‘aea08334-b614-11ee-a271-f47b096bd556’ has no current activity.: activity is null
org.camunda.bpm.engine.impl.pvm.PvmException: Execution ‘aea08334-b614-11ee-a271-f47b096bd556’ has no current activity.: activity is null
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at j

see longer log im Bottom!

Questions:

  1. What is wrong with the described Design Pattern ?
  • TA Frames ?
  • May be a Gap between UserTask abort + new Token ?
  1. Is throwing Code above Okay ?

Bpmn:
P0_Dummy_Gui_Process-AAA.bpmn (25.3 KB)

Picture:

Log:
024-01-18 16:17:33,482 ERROR org.camunda.bpm.engine.context : ENGINE-16004 Exception while closing command context: Execution ‘aea08334-b614-11ee-a271-f47b096bd556’ has no current activity.: activity is null
org.camunda.bpm.engine.impl.pvm.PvmException: Execution ‘aea08334-b614-11ee-a271-f47b096bd556’ has no current activity.: activity is null
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
at org.camunda.bpm.engine.impl.util.EnsureUtil.generateException(EnsureUtil.java:398)
at org.camunda.bpm.engine.impl.util.EnsureUtil.ensureNotNull(EnsureUtil.java:55)
at org.camunda.bpm.engine.impl.util.ActivityBehaviorUtil.getActivityBehavior(ActivityBehaviorUtil.java:51)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityLeave.execute(PvmAtomicOperationActivityLeave.java:44)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityLeave.execute(PvmAtomicOperationActivityLeave.java:32)
at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:99)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:130)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:110)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:85)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:622)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:596)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl$6.callback(PvmExecutionImpl.java:2021)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl$6.callback(PvmExecutionImpl.java:2018)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.continueExecutionIfNotCanceled(PvmExecutionImpl.java:2088)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.dispatchDelayedEventsAndPerformOperation(PvmExecutionImpl.java:2037)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.dispatchDelayedEventsAndPerformOperation(PvmExecutionImpl.java:2018)
at org.camunda.bpm.engine.impl.bpmn.behavior.FlowNodeActivityBehavior.leave(FlowNodeActivityBehavior.java:52)
at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskDelegateExpressionActivityBehavior$3.call(ServiceTaskDelegateExpressionActivityBehavior.java:119)
at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskDelegateExpressionActivityBehavior$3.call(ServiceTaskDelegateExpressionActivityBehavior.java:102)
at org.camunda.bpm.engine.impl.bpmn.behavior.AbstractBpmnActivityBehavior.executeWithErrorPropagation(AbstractBpmnActivityBehavior.java:90)
at org.camunda.bpm.engine.impl.bpmn.behavior.ServiceTaskDelegateExpressionActivityBehavior.performExecution(ServiceTaskDelegateExpressionActivityBehavior.java:127)
at org.camunda.bpm.engine.impl.bpmn.behavior.TaskActivityBehavior.execute(TaskActivityBehavior.java:69)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute$2.callback(PvmAtomicOperationActivityExecute.java:61)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute$2.callback(PvmAtomicOperationActivityExecute.java:50)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.continueIfExecutionDoesNotAffectNextOperation(PvmExecutionImpl.java:2082)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute.execute(PvmAtomicOperationActivityExecute.java:42)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityExecute.execute(PvmAtomicOperationActivityExecute.java:31)
at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:99)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:130)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:110)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:85)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:622)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:596)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl$6.callback(PvmExecutionImpl.java:2021)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl$6.callback(PvmExecutionImpl.java:2018)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.continueExecutionIfNotCanceled(PvmExecutionImpl.java:2088)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.dispatchDelayedEventsAndPerformOperation(PvmExecutionImpl.java:2037)
at org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.dispatchDelayedEventsAndPerformOperation(PvmExecutionImpl.java:2018)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionNotifyListenerStart.eventNotificationsCompleted(PvmAtomicOperationTransitionNotifyListenerStart.java:61)
at org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationTransitionNotifyListenerStart.eventNotificationsCompleted(PvmAtomicOperationTransitionNotifyListenerStart.java:30)
at org.camunda.bpm.engine.impl.core.operation.AbstractEventAtomicOperation.execute(AbstractEventAtomicOperation.java:70)
at org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:99)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:130)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:110)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:85)
at org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:75)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:631)
at org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperationSync(ExecutionEntity.java:606)

BPMN Message events can’t be thrown and caught within the same process instance.
I’d suggest you change the message throw and catch to escalation or error events.

1 Like

Thanks Niall !

little Problem:
If a make Escalation as start Event in Event SubProcess (for clean up, see above),
but want to have second possibility to Cancel a process (regardles of position),
then I have a little Problem:
a). I cannot throw programatically Escalation for processeInstanceId (only) !
( There is only one possblility to throw it via taskId and taskManager … )

b). And cannot throw an Error programatically too…

c). And multiple Start Events (Messager XOR Escalation) are not permitted in Event SubProcess …

If you want to cancel a process from an external source OR locally by one of the tasks you can use an interrupting signal event. It doesn’t have the same restriction as message events - BUT it is a broadcast so you need to make sure that the signal name is generated in runtime to include a key of the process instance you want to cancel. e.g. a buinessKey.

2 Likes

Hi Niall,

unfortunately there is a problem to throw (explicitelly = transparent) a Signal from User task:
Signal Throw will broad cast at ALL ProcessInstances !

So,

Summary: Imposible (camunda7):

1). throw catch Msg same process
2). throw escalation programmtically with processInstanceId (process-wide)
3). mix of two different start events: escalation + message
4). use a start Event signal for UserTask or Process-wide pattern with explicitelly call
5). Throw Errors process-wide / when not from Delegate (on other places)

I try with:
a). Conditional Events (Catch)
OR:
b). make this Cancel Design-Pattern: one CleanUp for UserTask or Process-wide
hidden!
Than I can throw a Signal restricted to special processInstanceId

Thanks & Regards
Stanislaw

I know, thats why i mentioned:

you need to make sure that the signal name is generated in runtime to include a key of the process instance

So you can generate the signal name in runtime as an ID unique to the process - then it’s only possible to trigger the process that it’s in.

Conditional events would work - but it’s not explicitly modeled where the condition is being triggered from. But if that doesn’t matter to you, i’d go with that.

1 Like

Thanks a lot Niall !
I disided to go with Signals:
up to this Signal-based pattern you can (just in case) a shout down all processes.

But customer should deside !

Question:
How I can trigger by code a escalation boundary on expanded calling actitity (embedded sub process) ?

//Background: Escalation could be throwed by code only for taskId…
BUT not for processInstanceId (executionId)… Or not?

Okay I can make Event SubProcess for Mapping or Transformation like this:

Start Message Event → Escalation Throw (End Event) // ohne Start + End events…

Than I can throw by code Message Event, that will be transformated zu Escalation … goind to Boundary…
:wink: