cancel
Showing results for 
Search instead for 
Did you mean: 

put 'null' to ProcessVariableMap

dognose
Champ in-the-making
Champ in-the-making
Hello,

for a save method of tasks i'm iterating over a list of available ProcessVariableKeys and using the
runtime service to flush variables without completing the task:


for (String varName : processVariableKeyList) {
   runtimeService.setVariable(businessProcess.getExecutionId(), varName, processVariables.get(varName));
}

This works perfectly fine for all variables.
However, if the user "removes" a entry from a Input, that is converted to a Double OR Date OR Long ….
The Converter returns "null" for that value, and therefore calls

processVariables.put("someDate",null);

calling
processVariables.get("someDate") afterwards will however return the PRIOR value of the date / double ….

Is this a known bug or expected behaviour and im doing something wrong?


processVariables.put("aDouble", 50.0); //works
processVariables.put("aDouble", null);
System.out.println(processVariables.get("aDouble")); //returns 50.0

Working with activiti 5.10
2 REPLIES 2

frederikherema1
Star Contributor
Star Contributor
processVariables.put("someDate",null);
Is this activiti-code or your code?

dognose
Champ in-the-making
Champ in-the-making
Hello,

sry for posting "a little" late. Until now we bypassed the problem, but now we need to reconsider a solution to this problem.

Basically a user is able to "empty" a textfield from the UI-Point of view. Until now, we putted an empty string, which worked fine.
But for Data-Maintenance Reasons we need to store a null value instead of an empty string, whenever a user is going to empty the text-field.

Therefore we setup the following in the web.xml:


<context-param>
    <param-name>
        javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL
    </param-name>
    <param-value>true</param-value>
  </context-param>

So, what has this to do with activiti?

Our form-elements are directly bounded to the entry in the ProcessvariableMap. Using a JSF 2.2 ViewScope, we perform some Ajax Operations and finally the submission of the form.

Every change to a field is stored properly, eccept when it resolves to `null`. We followed the Stacktrace down to the `ConversationScopeAssociation` of `DefaultContextAssociationManager` and found the following piece of code being executed:

DefaultContextAssociationManager


@Override
  public Object getVariable(String variableName) {
    ExecutionEntity execution = getExecutionFromContext();
    if(execution != null) {
      return execution.getVariable(variableName);
    } else {
      return getScopedAssociation().getVariable(variableName); 
    }
  }

Here, execution will resolve to null, and the else-case will call the ConversationScopedAssociation:


public <T> T getVariable(String variableName) {
      Object value = cachedVariables.get(variableName);
      if(value == null) {
        if(execution != null) {
          value = runtimeService.getVariable(execution.getId(), variableName);
          cachedVariables.put(variableName, value);
        }
      }
      return (T) value;
    }

At this point, the cachedVariable-Map may contain our desired "key=null" - for loging purposes we are iterating over the map and getting the values again, to log the change: And this "removes" the null value from the cachedVariable map:

If the "value" is null - it's reloaded by the runtimeService. However at this point, we did not yet save the variables (flush). That means: the null is removed and the "old" value is restored inside the cachedVariable-Map before actually saving the changes.

I'm not sure wheter this is a bug or serves some purpose, but it looks pretty strange. It is essentially saying: "You are not allowing to have null values in the cachedVariable Map".

So, the current event-sequence is like:

ProcessVariableMap.put("someKey", null); //old value was "Hello World"
-> stored in CachedMap
-> calling ProcessVariableMap.get("someKey") // returns "Hello World", cause of the code outlined above.
-> calling businessProcess.complete() // now stores "Hello World" again, because the getter writes back to the cachedVariable map.

edit: Running on activiti 5.13