Replace via process instance modification

Hallo everyone,
I integrated the process engine modifications into our own process operation GUI. I now found out that I was a bit naive in my approach. The main concept of our GUI are executions. I know that this does not comply with the camunda philosophy, but my problems would be the same if I worked with activity instances.

So I’d like to have three simple commands 1. start new execution, 2. cancel execution, 3. replace execution. The last one seems to be problematic. It’s supposed to first start a new execution before a given activity and then cancel an existing execution. That pretty much what cockpit does if you move an activity instance, right? But I have no clue how cockpit does that reliably.

Let’s consider the following (slightly artificial) scenario. I have a process with a single execution/activity instance and I want to move the activity instance to the very same activity it is already at. I specify two process instance modifications. The first creates a new activity instance at that activity and the second needs to cancel the original one. But how can I specify the cancel command in advance in such a way that the engine knows which execution/activity instance it needs to cancel. The problem is that after the startBefore command has been executed, the process instance has three executions/activity instances: a root execution with two sub-executions both of which are placed on the same activity. Both sub-executions have execution ids and activity instance ids, which did not exist before the start command. So it is neither possible to use the activity id nor the execution id or activity instance id to specify the correct activity instance.

As I said, the scenario is a bit artificial, but the question remains. How can I specify both commands at once when I have to face a re-structuring of the acitivity instance/execution tree? As far as I can see from https://docs.camunda.org/manual/7.7/webapps/cockpit/bpmn/process-instance-modification/ that should be possible.

Thanks for any help,
Peter

Hi Peter,

While this is correct for execution IDs, the activity instance ID of the original instance should remain stable (because the conceptual activity instance does not change by spawning a second instance). If this is not the case, then this is a bug in the process engine and I’d be grateful if you could proivde a test case for that behavior. Assuming there is no such bug, cancellation via activity instance ID should work in the scenario you describe.

Best regards,
Thorben

Hi Thorben,
I have case, where the ID does not remain stable, but it’s actually a transition ID, not an activity instance id. I’m not sure what you expect for those.

So the process consists of start node, service task, and end node. The service task throws an exception and runs out of retries. In this scenario, the exectuion at the service task has no act_inst_id_ in the DB and the activityInstanceTree shows a transitionInstance with the same Id as the processInstance. When I now start a new execution before the service task, both executions have no act_inst_id_ in the DB while the activityInstanceTree shows two transitionInstances, whose IDs are the respecitive executionIds both of which are different from the processInstanceId. So here, the cancel-command would not work.

With this example, can you say if there are more scenarios like this one? How do you judge the scenario?

Best, Peter

We had the idea of converting a transition instance as described in my last comment into an activity instance by deleting the job on the respective execution. That did not work. Although the execution has no more jobs, it is still represented as a transition instance in the activity instance tree. That does not sound consistent, is it?

Hi Peter,

Transition instance IDs are indeed not stable. They are derived from the execution structure as there is no dedicated database field for them (unlike activity instance IDs). With this limitation, I am afraid you cannot implement the feature the way you describe it. I can’t really think of a practicable workaround that works in the general case. Transforming a transition instance into an activity instance like you propose is not possible unless you execute the job successfully.

You could raise a feature request in our JIRA for making transition instance IDs stable.

Cheers,
Thorben

One more thought about a workaround: You can create a custom engine command that performs the modification in two steps. The first step starts the new instance, the second step cancels the previous instance. In between, you fetch the activity instance tree again and use the new transition instance ID for cancellation. Using a custom command, you would still have transactional behavior.

So the code would be along the lines of the following:

public void doModification()
{
  ProcessEngine engine = BpmPlatform.getDefaultProcessEngine();

  ProcessEngineConfigurationImpl engineConfiguration = (ProcessEngineConfigurationImpl) engine.getProcessEngineConfiguration();
  engineConfiguration.getCommandExecutorTxRequired().execute(new Command<Void>(){
    @Override
    public Void execute(CommandContext commandContext) {
      // 1. do first modification => start new Instance

      // 2. fetch new activity instance tree and determine transition instance to cancel

      // 3. do second modification => cancel transition instance

      return null;
    }
  });
}

Of course this requires that it is possible to identify the transition instance in step 2. This should be doable because you know the job that belongs to the transition. The job references the execution and the execution id can be used to identify the transition instance (in fact, currently the execution id is the transition instance id, but code should not rely on that).

Lastly the usual disclaimer: This uses internal API and may not be future-compatible.

Hi Thorben,
thanks for the idea using the jobs. I did not think about that. The command is not much of a problem, we already have several custom commands.
Gruesse aus Karlsruhe,
Peter