Exception while closing command context (How skip task ending)

I delete process by RuntimeService#deleteProcessInstances.
If it happened during service task i get I exception:
ENGINE-16004 Exception while closing command context: null: java.lang.NullPointerException
It seems like task can’t be ended. It is not error for me.
Can I skip task ending?

More stack trace:

│2019-11-22 10:22:33,975 ERROR [org.camunda.bpm.engine.context] (pool-9-thread-343) ENGINE-16004 Exception while closing command context: null: java.lang.NullPointerException                                                               │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.getNonEventScopeExecutions(PvmExecutionImpl.java:1036)                                                                                   │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.tree.LeafActivityInstanceExecutionCollector.visit(LeafActivityInstanceExecutionCollector.java:34)                                                                     │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.tree.LeafActivityInstanceExecutionCollector.visit(LeafActivityInstanceExecutionCollector.java:29)                                                                     │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.tree.ReferenceWalker.walkUntil(ReferenceWalker.java:87)                                                                                                               │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.tree.ReferenceWalker.walkUntil(ReferenceWalker.java:65)                                                                                                               │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.createActivityExecutionMapping(PvmExecutionImpl.java:1425)                                                                               │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.pvm.runtime.PvmExecutionImpl.createActivityExecutionMapping(PvmExecutionImpl.java:1457)                                                                               │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityEnd.execute(PvmAtomicOperationActivityEnd.java:53)                                                                    │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.pvm.runtime.operation.PvmAtomicOperationActivityEnd.execute(PvmAtomicOperationActivityEnd.java:32)                                                                    │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.interceptor.AtomicOperationInvocation.execute(AtomicOperationInvocation.java:91)                                                                                      │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.invokeNext(CommandInvocationContext.java:125)                                                                                    │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performNext(CommandInvocationContext.java:104)                                                                                   │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.interceptor.CommandInvocationContext.performOperation(CommandInvocationContext.java:79)                                                                               │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:618)                                                                                         │
│       at org.camunda.bpm.camunda-engine//org.camunda.bpm.engine.impl.persistence.entity.ExecutionEntity.performOperation(ExecutionEntity.java:594)
2 Likes

Hi @neki,

Can you provide some more information about your setup (application server, JDK version, database + version)? It would also be useful if you could provide a small example so that I can replicate it on my side.

Best,
Nikola

I tried to repeat the problem with a simple example, but was not successful.
I keep trying to recreate the problem with a simple example.
I will let to know when I get more specifics.
Thank you!

  1. WildFly 11
  2. java-1.8.0-openjdk
  3. MariaDB-10.2.8

I created this simple process:
image
I created this service task handler also:

 @Named("Test_Delegate")
 public class TestDelegate implements JavaDelegate {
     @Override
     public void execute(DelegateExecution execution) throws Exception {
         Thread.sleep(10000);
         throw new MyChildBpmnError();
     }
 }

It works correct. I see next message:

Execution with id ‘Test_Delegate’ throws an error event with errorCode ‘CUSTOM_ERROR_CODE’, but no catching boundary event was defined. Execution is ended (none end event semantics)

It is great! But if I call
runtimeService.deleteProcessInstance(pId, "Test", false, true);
before end of the sleep i see long stack trace started with:

ERROR [org.camunda.bpm.engine.context] (pool-10-thread-7) ENGINE-16004 Exception while closing command context: null: java.lang.NullPointerException

Is it correct?

Hi @neki,

I suspect the problem is related to how process execution is mapped to transactions.

  1. When you execute an instance of the example process you provided above, it’s actually executed in a single transaction and once the Process Instance is finished, the related data is committed to the database.
  2. If you decide to delete this Process Instance, this call will be executed in a transaction concurrent to the first one. The call won’t be able to find the Process Instance in the database since it hasn’t been committed yet, resulting in an NPE.

I agree that getting an NPE is not really descriptive, but it’s actually an expected behavior.

What you can do, as a workaround, is to introduce a transaction barrier on the Start event of the process, through an asynBefore or asynAfter flag. This will create the Process Instance in one transaction (and commit it to the database), and continue with its execution in a second transaction after the commit (through a Job). If a delete call is executed during the process execution, the Process Instance ID will already be present in the database now.

Does this solve your problem?

Best,
Nikola

1 Like

Thank you! It resolve my problem!