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):
Either:
- 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).
Hints (optional):
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.