Retrieve variables final state of a finished process instance

Hello,
I have a method to review finished processInstances. I use HistoryService to do so. I can get the historic processInstance from that service, but when I want to retrieve the final values of the variables, I get into trouble:

I am using this code:
historyService.createHistoricVariableInstanceQuery().processInstanceId(<id>).list()

But this is returning more than one value for each variable name (one for finished task?). Those come in an undetermined order. The only way I found the last value of each is thorugh a post-process of the result, where I only keep de HistoricVariableInstances with taskId == null (and indeed, this is a supposition, I really don’t know if I’m doing right)

So the question is:
Is there a way to limit HistoricVariableInstanceQuery to get only the last values of each variable? (and doing so, avoid a post-process)

I tried with some variants of .taskId() or .taskId(null) or .taskId(newArrayList()) to make the query only select varinstances related to the processInstances (taskId == null), but none of those lead to proper results.

I know I could use HistoricDetailQuery ordering by timestamp, but I would have to post-process to keep only the last values anyway, so it is not a proper solution.

PS: I have my audit level set to full.

Hi @mabertran,

Instead of doing the post processing, you can directly state a taskId for the query, e.g., `historyService.createHistoricVariableInstanceQuery().processInstanceId().taskIdIn(null).list();

In general, you can find all possible query parameters here. So currently there is not way to order the HistoricVariableInstanceQuery by a timestamp or alike. I think you have to go with the taskId solution.

Best,
Johannes

Thanks for your ultra-fast response.
I tried your solution, but it seems it is not allowed (camunda 7.5):

Task Ids is null. Stacktrace follows: org.camunda.bpm.engine.exception.NullValueException: Task Ids is null at org.camunda.bpm.engine.impl.util.EnsureUtil.generateException(EnsureUtil.java:334) ...

Order by a timestamp would be an acceptable solution, but on the other hand I think the operation of getting the last values of variables of a finished processInstance might be used quite frequently. Would it be a good idea to implement an easy and clear way to do it?

Oh yes, sorry for erroneous hint. I just looked it up and null is not allowed as input for taskIdIn. So you might have to do the post processing after all.

If you know the activtyInstanceId of the end event, you could probably also use that to achieve your desired goal. In my opinion OrderByTimestamp is probably more intuitive for most users, as we already have this filter in other queries so it would be more consistent. However, feel free to implement your suggestion and provide a pull request. I’m sure other users in the community would also benefit from that :wink:

Best,
Johannes

Hi @mabertran,

Please note that the table ACT_HI_VARINST contains always the last value of each variable. So, if you have more than one value for each variable, then it seems that you have named different variable with same name but in different scopes of a process instance.

Cheers,
Roman

I think it must be related with scopes, but the only thing I’m doing is assign some variables in some user or service tasks. Is this generating different scopes?

Then ACT_HI_VARINST contains a row for each task/activity that changes a variable value (done in tasks or activities), but the most relevant value when the processInstance is finished is the value of the main scope. I’m assuming this might be retrieved by checking if task_id_ is null in ACT_HI_VARINST. Being that true, I suggest a method to easily query this (task_id_ == null) might be available (for instance: HistoricVariableInstanceQuery.mainScopeOnly() or .processInstanceOnly()). At least a .taskIdsIn(null) or .taskIdsIn([]) might work, even this solution is not clear enough from my point of view.

I’ll try to!
Thanks,
Manu