HistoryService reporting issue

Hi all,

I need detailed reporting of each processes together with the variables used. The process is a product order process and starts with a set of userTasks where a selection of products is made. Then a multi-instance subProcess (the workorders) is fired that loops over each woProducts element (as woProduct).

  • Of the first couple of userTasks I should have all global and locally defined variables listed.
  • Of the userTasks defined in the subProcess, I should only list the ones bound to the task scope or the subProcess Scope. This is mainly where things go wrong; eg I cannot see variable woProduct in any of the printed values.

This is the code I have so far;

    Predicate<HistoricActivityInstance> allowedInstancePredicate = i -> i.getActivityType().equals("userTask")
            || i.getActivityType().equals("serviceTask")
            || i.getActivityType().equals("subProcess");

    historyService
        .createHistoricActivityInstanceQuery()
        .processInstanceId(processInstanceId)
        .orderByHistoricActivityInstanceStartTime()
        .asc()
        .list()
        .stream()
        .filter(allowedInstancePredicate)
        .peek(i -> i.getActivityName())
        .forEach(instance -> {
            LOGGER.info("instance: {} - {} - {}", instance.getActivityName(), instance.getActivityType(), instance.getExecutionId());

            historyService
                .createHistoricVariableInstanceQuery()
                .executionIdIn(instance.getExecutionId())
                .list()
                .forEach(variable -> LOGGER.info("variable: [{} - {}]", variable.getName(), variable.getValue()));
        });

Most possible I should not query by executionId in the case of the subProcess tasks, but I’m a bit lost at this point.
Any help is welcome.

Hi Nico,

You can try finding historic variable instances by activity instance id, i.e.

historyService
    .createHistoricVariableInstanceQuery()
    .activityInstanceIdIn(instance.getId())
    .list()
    .forEach(variable -> LOGGER.info("variable: [{} - {}]", variable.getName(), variable.getValue()));

Does that return more?

Cheers,
Thorben

Hi Thorben,

When I change it to your code, I hardly get any variable. Furthermore the 2 variables I get, I got already when using executionId :slight_frown:

17:03:17,549 INFO [be.powerdale.bpm.rest.HistoricRestService] (default task-56) instance: workorder process [for each product] - subProcess - 3c633576-7f29-11e6-b8a7-34363bcb5566
17:03:17,564 INFO [be.powerdale.bpm.rest.HistoricRestService] (default task-56) variable: [woProductDefinition - be.powerdale.butler.domain.Product@119]
17:03:17,564 INFO [be.powerdale.bpm.rest.HistoricRestService] (default task-56) variable: [popWoId - POP-160767-1.1]

Hey Nico,

Could you post a simplified test case or the contents of of the tables ACT_HI_VARINST and ACT_HI_ACTINST for one such process instance?

Thanks,
Thorben

Hi Thorben,

I attached the table entries for 1 completed processInstanceId.

Kind regards,
Nico

h2_export_ACT_HI_ACTINST.csv (20.0 KB)

h2_export_ACT_HI_VARINST.csv (18.8 KB)

Hi Nico,

Thanks for providing the table entries. There is a bug in the assignment of loopCounter and element variables to historic activity instances. In particular, they are all assigned to the multi-instance body instance that is a parent of all inner instances that belong together (I hope that makes sense, read up on multi-instance bodies here: https://blog.camunda.org/post/2015/06/why-we-re-implemented-bpmn-multi/). I created a bug ticket: https://app.camunda.com/jira/browse/CAM-6777

So to fetch these variables as of now, you can include activity instances of type multiInstanceBody in your query and you should receive loopCounter and the multi-instance element variables (assuming you query for variable instances by activity instance id, not execution id).

However, I don’t think there is a possibility to tell which variable belongs to which instance of the MI activity. To achieve that, an ugly workaround comes to mind: you could copy the element variables in a start execution listener on the subprocess like so:

public class UglyWorkaroundListener implements ExecutionListener {
  public void notify(DelegateExecution execution) throws Exception {
    String elementVariableName = ...;
    TypedValue variableValue = execution.getVariableTyped(elementVariableName);
    execution.removeVariable(elementVariableName);
    execution.setVariableLocal(elementVariableName, variableValue);
  }
}

When setting that variable, the process engine should assign the correct activity instance id to the historic variable instance.

Cheers,
Thorben

1 Like

Hi Thorben,

Thank you for taking the time to investigate the issue. I’ll try your workaround and see what that gives me.
At least we are kind of happy now we know it’s not our own damn fault :stuck_out_tongue:

Kind regards,
Nico Van Belle