Issues while getting 2nd latest user task from historyService

Hello everyone,

I’ve created a workflow based on our business requirements. In this workflow, we have different scenarios for the approval process. Let’s consider two examples:

Example 1:

  • Reviewer 1 (approved)
  • Reviewer 2 (approved)
  • Reviewer 3 (approved)
  • Reviewer 4 (rejected)

In this case, if Reviewer 4 rejects the request, I can retrieve the 2nd latest user task (HistoricActivityInstance) from the historyService and update the process variable to “false,” which will cause the workflow to revert to the previous user task (i.e., Reviewer 3).

When sorting the HistoricActivityInstances based on their start time (orderByHistoricActivityInstanceStartTime), the list looks like this:

  • HistoricActivityInstance of Reviewer 4
  • HistoricActivityInstance of Reviewer 3
  • HistoricActivityInstance of Reviewer 2
  • HistoricActivityInstance of Reviewer 1

However, I’m facing a challenge in the following scenario:

Example 2:

  • Reviewer 1 (approved)
  • Reviewer 2 (approved)
  • Reviewer 3 (approved)
  • Reviewer 4 (rejected) (So workflow goes to Reviewer 3)
  • Reviewer 3 (rejected) (Reviewer 3 also rejected so workflow should go to Reviewer 2)

In this case, the previous user task should be Reviewer 2. But the HistoricActivityInstances are ordered differently when I sort using orderByHistoricActivityInstanceStartTime(). Below is the list I received from historyService

  • HistoricActivityInstance of Reviewer 3
  • HistoricActivityInstance of Reviewer 4
  • HistoricActivityInstance of Reviewer 3
  • HistoricActivityInstance of Reviewer 2
  • HistoricActivityInstance of Reviewer 1

My question is, how can I reliably retrieve the parent or previous user task (in this case, always Reviewer 2 for Reviewer 3 and Reviewer 3 for Reviewer 4) without depending on the order of activities in HistoricActivityInstance, as the history order can be dynamic based on user actions? It’s also important to consider that the configuration of reviewers can be customized in a DMN file, and if a reviewer is not required (set to “false” in the DMN file), the flow should skip that reviewer. If Reviewer 3 is not required then then flow will be Reviewer 1 → Reviewer 2 → Reviewer 4

My Java code:
```

    List<HistoricActivityInstance> userTasks = historyService.createHistoricActivityInstanceQuery()
            .processInstanceId(processInstanceId)
            .activityType("userTask")
            .orderByHistoricActivityInstanceStartTime()
            .desc()
            .list();
    // Update the variable to false
    userTasks.stream()
            .skip(1)
            .findFirst()
            .ifPresent(secondLatestUserTask -> {
                String activityId = secondLatestUserTask.getActivityId();
                String variableName = getVariableNameFromActivityId(activityId);
                runtimeService.setVariable(processInstanceId, variableName, false);
            }); 

![image|690x210](upload://25bfTC8ZP58xuw1WwNQcmBIbvoN.png)


Thank you in advance

Generally, writing the business logic into code is counter productive, since you aren’t modeling it, so that meaning gets lost.

If it’s business logic, model it.
You can sort out the “how” of making it run once you’re clear on the logic.

Thank you for reply @GotnOGuts .
I’ve recently started my journey with Camunda, and I’m actively expanding my modeling expertise by studying documents and participating in forums. Given my current level of understanding, I’m currently relying on code to implement the business logic. Could you kindly recommend any documents or links that would aid me in fulfilling my requirements?

If you are in a place to be able to code it, then you should be able to model it, as almost every programming concept that I know is present to the model language.

Your business logic is really muddy to my, so I can’t really provide you any recommendations on how to implement. If you make the business logic clearer, then implementing it will likely become easier.

If Reviewer1Rquired is False, and Reviewer2Decision is rejected, what should happen?
If Reviewer3Decision is approved and Reviewer4Required is false, what should happen?

Try to list out the expected flows, not thinking about the “HOW” it happens.

Couldn’t you, for example, create an “Array” type process variable with the name reviewersList?

So you can create an execution listner in each task so that when the instance arrives there, it automatically searches for the reviewerList variable, adds the reviewer to this array, and then sets this process variable to update the list?

After this, you can access the array searching for reviewerList elements.

I believe this would be a good way for you to know the order of the reviewers without having to make crazy queries in the Camunda API hahaha… and you would still have this within your process!

I hope this helps!
Cya! :grin: :rocket:

William Robert Alves

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.