Environment (Required on creation):
All distros, all databases.
Description (Required on creation; please attach any relevant screenshots, stacktraces, log files, etc. to the ticket):
Deleting a transient variable followed by setting a non-transient variable with the same name leads to a NullPointerException.
java.lang.NullPointerException at org.camunda.bpm.engine.impl.db.entitymanager.cache.DbEntityCache.undoDelete(DbEntityCache.java:385) at org.camunda.bpm.engine.impl.db.entitymanager.DbEntityManager.undoDelete(DbEntityManager.java:560) at org.camunda.bpm.engine.impl.core.variable.scope.AbstractVariableScope.setVariableLocal(AbstractVariableScope.java:337) at org.camunda.bpm.engine.impl.core.variable.scope.AbstractVariableScope.setVariable(AbstractVariableScope.java:307) at org.camunda.bpm.engine.impl.core.variable.scope.AbstractVariableScope.setVariable(AbstractVariableScope.java:288) at com.hannoverre.hippo.hppp501.process.listener.MappingOrderLinkedEventListener.execute(MappingOrderLinkedEventListener.java:63) at org.camunda.bpm.engine.impl.bpmn.delegate.JavaDelegateInvocation.invoke(JavaDelegateInvocation.java:40)
Steps to reproduce (Required on creation):
- Start a process with a transient variable A
- Before reaching a transaction boundary, remove the variable by calling execution.removeVariable("A");, followed by setting a non-transient variable with the same name, e.g. via execution.setVariable("A", "foo");
Observed Behavior (Required on creation):
A NullPointerException is thrown.
Expected behavior (Required on creation):
- An error message is thrown similar to the one thrown when trying to overwrite a transient variable with a non-transient one and vice versa
- This chain of command is allowed and the non-transient variable is treated as a new variable that will be persisted
Root Cause (Required on prioritization):
- In the AbstractVariableScope#setVariableLocal, a specific branch is handling setting a variable after its removal: https://github.com/camunda/camunda-bpm-platform/blob/a455e6a8ce80b188613a1a982fa25ef5541cf85a/engine/src/main/java/org/camunda/bpm/engine/impl/core/variable/scope/AbstractVariableScope.java#L351-L360
- This currently makes no differentiation between transient and non-transient variables having been removed. Therefore, the DbEntityManager#undoDelete is called. For a transient value, the entity manager will however not have an entry and currently fails with an NPE.
Solution Ideas (Optional):
- Decide, if this chain of command
- Yields an error message similar to the one when overriding a transient variable with a non-transient one
- Is allowed and transforms a transient variable to a non-transient one and vice versa with all necessary considerations (like history events and correct initial DB state).
Deciding for allowing this chain of command would finally allow transforming transient variables to non-transient ones and vice versa. Since this would now require an explicit removal followed by a set, one could argue that the intent is clearly conveyed now and therefore less error-prone and more transparent compared to allowing a simple override via the setVariable method.