DEV Community

DEV-AI
DEV-AI

Posted on

Creating Parallel Human Tasks in Camunda at Runtime

In many business processes, you may need to assign a task to several users in parallel. In Camunda, this is commonly achieved using a multi-instance user task configured for parallel execution. This approach transforms a single task into multiple instances dynamically, with each instance assigned to a different user from a collection that is determined at runtime.

This article explains how to model such a workflow, generate the dynamic user list, and configure task assignment using Camunda’s BPMN 2.0 extensions for multi-instance activities. The guidance below is based on the official Camunda documentation — see Task Markers for more details.


1. Model Your Workflow with a Parallel Multi-Instance User Task

To create parallel tasks, define a user task in your BPMN model and add a multiInstanceLoopCharacteristics element. This element uses the camunda:collection and camunda:elementVariable attributes to iterate over a collection of user IDs determined at runtime.

Below is an example BPMN snippet:

<bpmn:userTask id="Task_Review" name="Review Document">
  <bpmn:multiInstanceLoopCharacteristics 
      isSequential="false" 
      camunda:collection="${userIds}" 
      camunda:elementVariable="currentUser">
    <!-- Optional completion condition to decide when to end the multi-instance -->
    <bpmn:completionCondition>${nrOfCompletedInstances == nrOfInstances}</bpmn:completionCondition>
  </bpmn:multiInstanceLoopCharacteristics>
  <bpmn:extensionElements>
    <camunda:assignee>${currentUser}</camunda:assignee>
    <!-- Additional task configurations like forms can be added here -->
  </bpmn:extensionElements>
</bpmn:userTask>
Enter fullscreen mode Exit fullscreen mode

Key Points:

  • isSequential="false": This setting ensures that the tasks are executed in parallel.
  • camunda:collection: Resolves at runtime to a collection variable (e.g., userIds) that holds the list of user IDs.
  • camunda:elementVariable: Each instance will have its own variable (here, currentUser) that holds one user ID from the collection.
  • camunda:assignee: The task assignment leverages the dynamic element variable to assign the task to the correct user.

2. Generate the User List at Runtime

Before the multi-instance user task is reached in the process, you need to determine the list of users dynamically. This can be accomplished using a Service Task or a Java delegate that retrieves or calculates the list of appropriate user IDs. For instance:

Example Java Delegate:

package com.example.delegate;

import org.camunda.bpm.engine.delegate.DelegateExecution;
import org.camunda.bpm.engine.delegate.JavaDelegate;
import java.util.Arrays;
import java.util.List;

public class FetchUsersDelegate implements JavaDelegate {
  @Override
  public void execute(DelegateExecution execution) {
    // Example: Fetch user IDs dynamically from a database or an external service.
    List<String> userIds = Arrays.asList("user1", "user2", "user3");

    // Set the variable "userIds" so the multi-instance task can iterate over it.
    execution.setVariable("userIds", userIds);
  }
}
Enter fullscreen mode Exit fullscreen mode

In your BPMN model, the service task should be placed before the multi-instance task to ensure the userIds variable is available:

<bpmn:serviceTask id="FetchUsers" name="Fetch User IDs" camunda:class="com.example.delegate.FetchUsersDelegate" />
Enter fullscreen mode Exit fullscreen mode

3. Assign Tasks Dynamically

Each instance of the multi-instance user task will receive a single element from the userIds collection via the element variable currentUser. The task assignment is then achieved by referencing ${currentUser} in the task’s properties (using Camunda’s extension elements):

<camunda:assignee>${currentUser}</camunda:assignee>
Enter fullscreen mode Exit fullscreen mode

Ensure that the users referenced in the collection exist in Camunda’s identity service or are synchronized with your user management system (such as LDAP or SSO).


4. Handling Task Completion

The process waits for the multi-instance to finish based on the defined completion condition. In the example above, the sample condition waits until all tasks are completed:

<bpmn:completionCondition>${nrOfCompletedInstances == nrOfInstances}</bpmn:completionCondition>
Enter fullscreen mode Exit fullscreen mode

You can adjust the completion condition as needed—for instance, to continue the process when a certain percentage of tasks are completed.


5. Testing the Workflow

To test your workflow:

  1. Deploy the process definition to your Camunda Engine.
  2. Start a new instance of the process. When starting the process, supply the userIds variable either through a preceding service task (as shown above) or via the REST API:
   {
     "variables": {
       "userIds": {
         "value": ["user1", "user2", "user3"],
         "type": "Json"
       }
     }
   }
Enter fullscreen mode Exit fullscreen mode
  1. Verify that each task is correctly assigned to the user indicated by the currentUser variable in each instance.

Conclusion

By leveraging the parallel multi-instance capabilities in Camunda, you can efficiently create workflows where human tasks are dynamically generated and assigned to a varying number of users at runtime. The combination of BPMN 2.0 multi-instance loop characteristics and Camunda-specific extensions (such as camunda:collection and camunda:elementVariable) provides a flexible approach to managing parallel human tasks.


Sources

Top comments (0)