Inconsistent procvar behaviour

I found some strange behaviour regarding the storing and updating of process variables. Suppose we have the following process:

Process A:Service 1 -> Task 1 -> Service 2 -> Task 2 -> Service 3

Service 1 creates a new process variable:

Book book = new Book("12345");execution.setVariable("book", book);

Service 2 changes a property:

Book book = execution.getVariable("book");book.setTitle("Activiti in Action");

Service 3 prints the content of the process variable:

Book book = execution.getVariable("book");System.out.println("book=" + book);

Result: book=Book [isbn=12345, title=Activiti in Action]

This is as (I) expected. However, now we remove Task 1. Lets see what happens.

Process B:Service 1 -> Service 2 -> Task 2 -> Service 3

Result: book=Book [isbn=12345, title=null]

This is strange… the variable is not updated whereas it was in the first process.

ConclusionIt seems that changes to process variables are only persisted if there is a waitstate between the creation and the update of the var.

Also, when debugging this issue I noticed that VariableType.serialize is called twice every time setVariable (or rather createVariableLocal) is called: once by VariableInstanceEntity.createAndInsert and once by VariableScopeImpl.setVariableInstanceValue.

I've tried to attach a patch with a testcase, but this results in the error "The extension diff is not allowed"…

So the variable is created and added to the SqlSession, and the cachedValue is set (twice actually).

The next step in the process is a task, so the db session is flushed, causing the ExecutionEntity (and the variable) to be written to the database.

After that the next step is Service2, which calls getVariable. The call hierarchy looks like this:

ExecutionEntity(VariableScopeImpl).getVariable—-ExecutionEntity(VariableScopeImpl).ensureVariableInstancesInitialized (not initialized yet, so fetch from db)—-VariableInstanceEntity.getValue (cachedValue is null)——–SerializableType.getValue (only called if cachedValue is null)————DbSqlSession.addDeserializedObject

So ultimately getVariable causes DbSqlSession.addDeserializedObject to be called. As I understand it, this ensures that variables with updated values are flushed at the end of the transaction.

What about Process B?

The difference with Process A is the task between Service1 and Service2, so we need only look at what happens in Service2.