• Restoring the last state of process instances that have been erroneously canceled
  • Restarting process instances after a termination caused by a wrong decision
    To perform such an operation the process engine offers the process instance restart API, that is entered via . This API allows to specify multiple instantiation instructions in one call by using a fluent builder.

Note that these operations are also available via REST: Restart Process Instance and

Process Instance Restart by Example

As an example, consider the following process model where the red dots mark active tasks:

Let us assume that the process instance has been canceled externally by a worker using the following code:

After that, the manager decides to restore the last state of that process instance.

  1. runtimeService.restartProcessInstance(processInstance.getProcessDefinitionId())
  2. .startBeforeActivity("receivePayment")
  3. .startBeforeActivity("shipOrder")
  4. .processInstanceIds(processInstance.getId())
  5. .execute();

The process instance has been restarted with the last set of variables. However, only global variables are set in the restarted process instance.Local variables can be set manually, for example by calling RuntimeService.setVariableLocal(…).

Technically, a new process instance has been created.

Please note: The ids of the historic and the restarted process instance are different.

Operational Semantics

In the following, the exact semantics of the process instance restart feature are documented. Reading this section is recommended to fully understand the effects, power and limitations of this feature.

  • startBeforeActivity(String activityId)
  • startAfterActivity(String activityId)
  • startTransition(String transitionId)
    For information about the instruction types, please refer to the similar modification instruction types section.

Selecting process instances to restart

Process instances can be selected for restart by either providing a set of process instance idsor providing a historic process instance query. It is also possible to specify both, a list of process instance ids and a query.The process instances to be restarted will then be the union of the resulting sets.

The process instances which should be restarted can eitherbe specified as a list of the process instance ids:

  1. List<String> processInstanceIds = ...;
  2. runtimeService.restartProcessInstances(processDefinition.getId())
  3. .startBeforeActivity("activity")
  4. .processInstanceIds(processInstanceIds)
  5. .execute();

or, for a static number of process instances, there is a convenience varargs method:

If the instances are not known beforehand, the process instances can be selected by a historic process instance query:

  1. HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService
  2. .createHistoricProcessInstanceQuery()
  3. .processDefinitionId(processDefinition.getId())
  4. runtimeService.restartProcessInstances(processDefinition.getId())
  5. .startBeforeActivity("activity")
  6. .historicProcessInstanceQuery(historicProcessInstanceQuery)
  7. .execute();

It is possible to skip invocations of execution and task listeners as well as input/output mappings for the transaction that performs the restart. This can be useful when the restart is executed on a system that has no access to the involved process application deployments and their contained classes.

In the API, the two methods #skipCustomListeners and #skipIoMappingscan be used for this purpose:

  1. ProcessDefinition processDefinition = ...;
  2. List<String> processInstanceIds = ...;
  3. runtimeService.restartProcessInstances(processDefinition.getId())
  4. .startBeforeActivity("activity")
  5. .processInstanceIds(processInstanceIds)
  6. .skipCustomListeners()
  7. .execute();

Restarting a Process Instance With the Initial Set of Variables

By default, a process instance is restarted with the last set of variables.To alternatively choose the initial set of variables, the method is used.

This feature does not only copy the start variables, but will copy the first version of all process variables that have been set in the start activity of the old process instance.

The initial set of variables can not be set if the historic process instance has no unique start activity. In that case, no variables are taken over.

  1. ProcessDefinition processDefinition = ...;
  2. List<String> processInstanceIds = ...;
  3. runtimeService.restartProcessInstances(processDefinition.getId())
  4. .startBeforeActivity("activity")
  5. .processInstanceIds(processInstanceIds)
  6. .withoutBusinessKey()
  7. .execute();

Execution

The restart can either be executed synchronously (blocking) or asynchronously(non-blocking) by using a .

The following are some reasons to prefer either one or the other:

  • Use synchronous execution if:

    • the number of process instances is small
    • the restart should be atomic, i.e., it should be executedimmediately and should fail if at least one process instance cannotbe restarted
  • Use asynchronous execution if:

    • the number of process instances is large
    • all process instances should be restarted decoupled from the otherinstances, i.e., every instance is restarted in its own transaction
    • the restart should be executed by another thread, i.e., the jobexecutor should handle the execution

To execute the restart synchronously, the execute method is used. It willblock until the restart is completed.

  1. ProcessDefinition processDefinition = ...;
  2. List<String> processInstanceIds = ...;
  3. runtimeService.restartProcessInstances(processDefinition.getId())
  4. .startBeforeActivity("activity")
  5. .processInstanceIds(processInstanceIds)

Restart is successful if all process instances can be restarted.

To execute the restart asynchronously, the executeAsync method is used. It willreturn immediately with a reference to the batch that executes the restart.

Using a batch, the process instance restart is split into several jobs whichare executed asynchronously. These batch jobs are executed by the job executor.See the batch section for moreinformation. A batch is completed if all batch execution jobs are successfullycompleted. However, in contrast to the synchronous execution, it is not guaranteedthat either all or no process instances are restarted. As the restart is split intoseveral independent jobs, every single job may fail or succeed.

If a restart job fails, it is retried by the job executorand, if no retries are left, an incident is created. In this case, manual actionis necessary to complete the batch restart: The job’s retries can be incrementedor the job can be deleted. Deletion cancels restart of the specific instance butdoes not affect the batch beyond that.