User Task

Overview

A User Task is a type of task that is assigned to a user or a group for manual completion within a business process. User tasks are integral to the workflow, allowing human participants to interact with the process by performing specific actions, making decisions, or providing input.

Single performer vs. group

In BPMN can be the only performer of the task. When we say "the task is assigned to group", it means there is a list of potential performers, not a UserGroup object. One of them must become an actual task performer by claiming the task on himself.

Graphical Notation

A user task is visualized as a typical task (rounded rectangle), with a small user icon in the left upper corner.

user task
XML Representation

A user task is defined in XML as follows. The id attribute is required, the name attribute is optional.

<userTask id="user-task-01" name="User task" />

Properties

User task has common properties as other activities have and three specific sections:

  • Assignee, where you can assign a single task performer or potential performers (candidates);

  • Form, where you can define a user interface for the task;

  • Task Listeners, where you can add listeners triggered by task lifecycle events.

Besides, it has an additional property in the General section — Due Date to inform the performer when the task must be completed.

user task properties

Due Date

The due date parameter in a user task specifies the deadline by which the task must be completed. This parameter is crucial for managing time-sensitive activities within a business process.

Take in account that due date doesn’t affect the process itself. When the appointed date arrives, nothing happens in the process — you should manage this event yourself. For example, in the custom task list.

Setting Due Date

There is a due date field at the user task properties panel in the General section:

due date field

The Due date parameter can be set in two variants:

  • Fixed date: Some date in the future that means a deadline. (The date in the past will be ignored, the task will be shown as overdue.)

  • Duration: A period of time started from the moment when the task is created.

Actually, due date is a text field that will be interpreted by the process engine at runtime. The following variants are available:

  • Literal string in ISO8601 format, representing fixed date or duration.

  • Process variable of the type:

    • java.lang.String — must contain a value in ISO8601 format.

    • java.util.Date — must contain date value.

  • Expression that must be resolved at runtime as one of the above variants, for example $/{someDateVariable/}.

  • If variable value is null it doesn’t cause an error. It means the task has no specified deadline.

  • Due date parameter isn’t validated during the process deployment. But at runtime wrong value will cause an error.

ISO 8601 examples

  • Fixed date:

    • 2024-02-01T08:40:37

    • 2050-01-01

  • Duration:

    • PT20M - in 20 minutes

    • PT5H - in 5 hours

    • PT3D - in 3 days

Accessing Due Date Programmatically

It is possible to manipulate due date parameter using Task class methods:

Task task = taskService.createTaskQuery()
                .taskId("taskId").singleResult(); (1)
task.getDueDate(); (2)
task.setDueDate(null); (3)
taskService.saveTask(task); (4)
1  — get task by id
2  — get the current value of due date
3  — set new due date value equals 'null'
4  — save task object

So, you can change due dates dynamically depending on your business logic. For example, the assignee can ask for additional time to complete the task.

Using Business Calendar

When you have a Business Calendars add-on installed, the corresponding field appears in the General properties section in the Web BPM Modeler:

busines calendar

Here you can select one of preconfigured business calendars from the pull-down list. In this case, the due date can be set only as duration, and the elapsed time will be calculated taking into account the business calendar.

For example, the user received the task at 04:00 PM. In the business calendar standard working time is set from 10:00 AM till 06:00 PM, and a due date parameter is set for 3 hours (PT3H).

The deadline will be set not at 07:00 PM right after 3 hours but at 11:00 AM the next working day. With business calendar, only working hours are counted.

With business calendar duration can be set in hours and minutes, not in days.

XML representation A user task with due date:

<userTask id="Activity_0gsy9yk" name="User task"
    flowable:dueDate="PT3H" (1)
    flowable:businessCalendarName="test-calendar"> (2)
. . .
</userTask>
1  — Due date as duration
2  — Business calendar attribute

See details in Business Calendars add-on.

User Assignment

In order for a task to be ultimately completed, it must be assigned a performer. Only one user can be assigned as the human performer for the task, this user is called an assignee.

The assignee attribute can be empty. It means there is no user who sees this task in his task list. Such a task usually is considered as a group task, when there is a list of potential performers or candidates. As well, you can set the assignee at runtime — by using administrative functions or programmatically.

Assignee Sources

In Jmix BPM, the assignee source refers to the mechanism used to determine which way the user will be selected to be an assignee for a specific user task in a business process. There are three options, how to do that:

Expression

 — here must be an expression that result is a String containing username.

Process variable

 — a variable that refers to User entity.

User provider

 — a special Java class with the method returning a username.

assignee sources

Assigning Task by Expression

Expression is a default assignee source. You will need to write an expression that evaluates a username of an assignee. For example, if the User entity is stored in a process variable called manager, then the expression will be ${manager.username}:

assign by expression

XML representation

<userTask id="user-task-01" name="User task"
    flowable:assignee="${manager.username}"
    jmix:assigneeSource="expression"
    jmix:assigneeValue="${manager.username}" />

If you want to assign a task to a specific user, you can write a username directly:

assigne by expression direct

Also, you can invoke Spring bean method that returns username:

${smpl_MyBean.evaluateManager(methodParam1, 'methodParam2')}

Assigning Task by Process Variable

If you select the Process variable assignee source, the ComboBox component will be displayed in the properties panel. This field displays those fields and process variables that are of the Entity type, and their entity class implements the UserDetails interface.

Built-in initiator variable

The build-in initiator process variable is available for assigning tasks while modeling a process. It contains an entity of the user that started the process:

assignee initiator

XML representation

A user task with the performer assigned by process variable:

<userTask id="user-task-01" name="User task"
    camunda:assignee="${initiator.username}"
    jmix:assigneeSource="processVariable"
    jmix:assigneeValue="initiator" />

If the process was started via API or by message/signal, initiator variable isn’t defined. Using it may cause a runtime error.

You can disable the initiator process variable using the following property:

jmix.bpm.process-initiator-variable-enabled=false

Also, you can change the name of the initiator property:

jmix.bpm.process-initiator-variable-name=manager

Assigning Task by User Provider

If you need to apply a complicated business logic to define a task performer, better to choose a User provider option. In this case, the system offers to select an existing user provider Java class or allows to create a new one:

selecting user provider

User provider should implement one or more methods with the String returned type. A method gets parameter values that are specified in the modeler and returns a username of the user that should become a task assignee. If the class has the only method, it’d be applied automatically:

assign by user provider

XML representation

A user task with performer assigned by User Provider:

<userTask id="user-task" name="User task" jmix:assigneeSource="userProvider" jmix:assigneeValue="smpl_MyUserProvider">
  <extensionElements>
    <jmix:springBean beanName="smpl_MyUserProvider" methodName="getUser" />
  </extensionElements>
</userTask>

User provider class is a common Spring bean, annotated by @UserProvider annotation. Here is an example of the user provider that reads a process variable with the user email and finds the user in the database.

@UserProvider(value = "smpl_MyUserProvider", description = "Returns a user with the specified email")
public class MyUserProvider {

    @Autowired
    private DataManager dataManager;

    public String getUserByEmail(String parameter) {
        return dataManager.load(User.class)
                .query("select u from smpl_User u where u.email = :email")
                .parameter("email", parameter)
                .one()
                .getUsername();
    }
}

You can implement any business rules in UserProvider class. For example, select the less busy user from the role or from the department; select next in turn; at least, select a random user from the group.

Assigning Task Programmatically

To set the task assignee programmatically, you can use the setAssignee method on the TaskService. Here’s an example:

Task task = taskService.createTaskQuery()
                       .taskId("taskId")
                       .singleResult(); (1)

taskService.setAssignee(task.getId(), "jane"); (2)
1  — getting task object by Query API
2  — setting assignee by username

Tasks assigned to the certain user can be retrieved through the TaskService as follows:

List<Task> tasks = taskService.createTaskQuery()
    .taskAssignee("jane") (1)
    .list();
1  — username

Task Candidate Users and Groups

Candidates refer to users or groups who are eligible to claim and complete a task. When a task has multiple candidates assigned to it, the task appears in the task lists of all the candidates. The first candidate who claims the task becomes the assignee and can then complete the task. After that, the task becomes not visible to other candidates.

The term "groups" here technically means a list of User group codes.

Claiming Group Tasks

It often happens that we don’t need it a certain user performs the task. For example, it doesn’t matter for a manager who from two accountants make a decision about his order.

In this case, Jmix BPM allows assigning the task to candidates list — and any of its members can become a performer. But previously he or she must claim the task. Claiming is an action of taking task ownership by user.

The task with candidates appears in My tasks view in the Group tasks section for each candidate.

my tasks claim

After any of the candidates claims the task, the task moves to the Assigned tasks list for this user and disappears from the Group tasks list of other candidates.

claiming form

To claim the task user must open it and take one of the actions:

  • Claim and resume — the user becomes a task assignee, the task form will be reopened in normal mode, and he or she can continue to work with it.

  • Claim and close — the user becomes a task assignee, the task form will be closed; he or she can find it later in the Assigned tasks section of a task list:

my tasks claimed task

Claiming Task Programmatically

It’s possible to claim the task on the specified user via API:

taskService.claim("taskId", "userId");

Setting Candidates in Studio

To set up candidates in Studio use corresponding user task properties in BPMN Inspector:

setting candidates

To enter values in these fields, click an Edit button edit button, and type user groups codes or usernames in editor window as a comma-separated list:

edit candidates
edit candidate users

XML representation

<userTask id="Activity_0cu0xtq" name="User task"
    camunda:candidateUsers="bob, peter"
    camunda:candidateGroups="accountants, sales"
    jmix:candidateGroupsValue="accountants, sales"
    jmix:candidateUsersValue="bob, peter" />
 . . .
</userTask>

Studio doesn’t see real user groups and users. So it is on developer’s responsibility to use only valid group codes and usernames as candidates. Otherwise, it causes a runtime error.

Setting Candidates in Web BPM Modeler

In the Web BPM Modeler, more options for setting candidate groups and users are available. For setting candidate groups, click the Edit button:

web modeler candidate groups

Then the Candidate groups editor window will be opened where you’d be able to select the candidate groups source:

candidate groups sources
  • User groups — pick user groups from the list.

  • User groups provider — select a special Java class that returns a list of user groups.

  • Expression — get a list of user groups from expression, for example, from the process variable defined earlier in the process.

Set Candidates by User Groups

If you have chosen a User groups option as a source, you can select any from existing user groups:

selecting candidate grouos

User Groups Provider

If you need to implement a complicated logic when setting candidate groups, better choose the User groups provider option.

selecting user group provider

It allows to select one of previously created Java beans provided with the @UserGroupListProvider annotation. This bean must implement one or more methods returning List<String> containing user group codes.

The @UserGroupListProvider annotation has two attributes:

  • value — a name that will be displayed in the modeler.

  • description — an explanation of the method’s purpose, optional.

Here is an example:

@UserGroupListProvider(value="allGroups",
                       description = "Returns a list of all groups")
public class MyGroupListProvider {

    @Autowired
    private UserGroupService userGroupService;

    public List<String> getAllUserGroups() {
        List<UserGroup> allUserGroups = userGroupService.getAllUserGroups();
        if (!allUserGroups.isEmpty()) {
            return allUserGroups.stream().map(UserGroup::getCode).toList();
        } else {
            return Collections.emptyList();
        }
    }
}

See the User groups section for more information.

Set Candidate Groups by Expression

The most general way of setting BPMN parameters is expression. For candidate groups, it is also available:

candidate groups expression

Candidate Users Options

Setting candidate users in the Web BPM Modeler is very similar to setting candidate groups. Here are sources you can choose from:

candidate users options
  • User groups — pick usernames from the list.

  • User groups provider — select a special Java class that returns a list of usernames.

  • Expression — get a list of usernames from expression.

User List Provider

Similar to User Groups Provider, you can get a list of candidate users programmatically via calling a method of the Spring bean annotated by @UserListProvider annotation:

candidate user list provider

Here is an example:

@UserListProvider(value = "smpl_UserListProviderDemo",
                  description = "Get all users")
public class UserListProviderDemo {

    @Autowired
    private DataManager dataManager;
    @Autowired
    private SystemAuthenticator authenticator;

    public List<String> getAllUsers() {
        authenticator.begin();
        try {
            List<User> users = dataManager.load(User.class).all().list();
            return users.stream().map(User::getUsername).toList();
        } finally {
            authenticator.end();
        }
    }
}

Set Candidate Users by Expression

As well, you can use the most common way of setting parameter of the process model — by expression:

candidate users expression

For example, this way you can refer to the username of the User entity variable:

${initiator.username}

CandidateUsers and candidateGroups can both be defined on the same user task.

Defining User Task Forms

User task can be configured to use a process form to visualize it for performer. Jmix BPM offers the following options for process forms:

form type selection

By default, a new user task is created with no form. You can select one while configuring the task.

Recommendations on using process forms

Choose Input dialog forms for the rapid prototyping or for uncomplicated forms not needed customization even in production. Such forms usually operate with simple data types — strings, numbers, enums, dates.

When you need to show on the form complex data objects like entities or collections of entities with many fields, validations, and formatting requirements, it’d be better to choose Jmix view. However, this requires more efforts.

User Task Outcomes

When users complete a user task, they often have to make a decision, for example, approve or reject the document. After that, the process should go one or another way. You can use task outcomes for modeling such cases.

Outcomes appear on process forms as buttons that may be provided with icon. Wherein, default Complete button becomes not visible.

outcome buttons

You can create outcomes both in input dialog forms and Jmix views but different ways. See details below.

Outcomes in Input Dialog Forms

For input dialog process forms, outcomes are defined in the Outcomes section in the BPMN Inspector panel.

outcomes in proprties

You can create outcomes using Outcomes editor, set its id, caption, and icon:

outcomes editor

Later you can edit outcomes directly in the BPMN Inspector panel:

outcomes created

In the Web BPM Modeler, you can see outcomes in the properties panel:

web outcomes

To create or edit the outcome, use Outcome editor:

web outcome edit

XML representation

When outcomes are used with the input dialog form, a special jmix:formOutcomes section is added. Here you can see your outcomes with jmix:formOutcome attributes.

<userTask id="Activity_0cu0xtq" name="User task" camunda:candidateUsers="bob, peter" camunda:candidateGroups="accountants, sales" jmix:candidateGroupsValue="accountants, sales" jmix:candidateUsersValue="bob, peter">
  <extensionElements>
    <jmix:formData type="input-dialog" openMode="DIALOG">
      <jmix:formOutcomes> (1)
        <jmix:formOutcome id="approve" caption="Approve" icon="CHECK" /> (2)
        <jmix:formOutcome id="reject" caption="Reject" icon="BAN" /> (3)
      </jmix:formOutcomes>
    </jmix:formData>
  </extensionElements>
</userTask>
1  — outcomes section
2  — "approve" outcome
3  — "reject" outcome

Outcomes in Jmix View Forms

For Jmix screen forms, outcomes are defined in the screen controller.

However, in the Studio you can see outcomes in the Form section just for reference — it helps to design the process without looking in the Jmix view controller code.

outcomes jmix form

How to create and use outcomes in Jmix views, see in the corresponding section.

Using Outcomes

When the user clicks one of the outcome buttons, the task is completed and the decision is written to a special process variable which name is built according to the following name pattern: <user-task-id>_result. You can find it in the list of variables in the Process instance edit view.

outcome container

It has type OutcomesContainer that contains a list of Outcome objets for the case when the given user task is multi-instanced.

You can access outcomes container programmatically:

String outcomeContainerName = taskIdValue + "_result"; (1)
OutcomesContainer outcomesContainer = (OutcomesContainer) execution
        .getVariable(outcomeContainerName); (2)
1  — Generate a name of the outcomes container.
2  — Get the outcomes container, that is a list of outcomes.

This variable value holds information about the users (if many) that completed the task and outcomes they selected. Yuo can see it in the Process variable editor window.

outcome container esitor

Outcome-Based Conditions

After you set outcomes for the task, you need to specify conditions for sequence flows after the exclusive gateway element. You can write a condition expression or select an outcome from the drop-down list.

Let’s look at the example of configuring a sequence flow using outcome-based conditions. Here is a fragment of the process with user task and exclusive gateway having two outgoing sequence flows.

approve invoice process

To specify conditions for the approved sequence flow, select it on the canvas and configure its properties.

Change the Condition source to the User task outcome and select the task and its outcome in the drop-down lists.

sequence flow condition

Outcome-Based Conditions in Multi-Instance Mode

User tasks can be multi-instanced. See details on this mode in the Multi-Instance section. Here we look at only multi-instance mode affects outcome-based conditions.

In this example, the Approve invoice task is multi-instance. It means there is a collection of users performing this task, and each of them works with his or her own instance.

outcomes multi instance

So, regarding this document, there will be made as many distinct decisions as there are users in the collection. But all their decisions will be accumulated in the one outcome container.

Therefore, we can specify an additional parameter – Condition type, that may have the following values:

  • Anyone completed with the outcome

  • Everyone completed with the outcome

  • No one completed the outcome

outcome multi condittions

Thus, you can organize some kind of voting using this feature.

XML representation

<sequenceFlow id="Flow_15f0sh3" name="Approved" sourceRef="Gateway_1kb7ltq" targetRef="Activity_0xl938c">
  <extensionElements>
    <jmix:conditionDetails
        conditionSource="userTaskOutcome" (1)
        conditionType="anyoneCompleted" (2)
        userTaskId="approve-invoice" (3)
        userTaskOutcome="approve" /> (4)
  </extensionElements>
  <conditionExpression xsi:type="tFormalExpression">${execution.getVariable('approve-invoice_result') != null &amp;&amp; bpm_UserTaskResults.containsOutcome(execution.getVariable('approve-invoice_result'), 'approve')}</conditionExpression>
</sequenceFlow>
1  — Condition source selected.
2  — Condition type, by default equals anyoneCompleted even for not multi-instance tasks. In this case, it is hidden from the properties panel.
3  — Reference to the user task.
4  — The outcome selected.

Setting Task Listeners

User tasks in Jmix BPM support the use of task listeners to execute custom logic in response to specific events. Task listeners allow you to define Java classes or expressions that will be triggered when certain events occur related to the user task.

Available events for task listeners on user tasks include:

  • create: Triggered when the user task is created

  • assignment: Triggered when the user task is assigned to a user or group

  • complete: Triggered when the user task is completed

  • delete: Triggered when the user task is deleted

task listeners field
task listener editor
creating task listener

To configure a task listener for a user task, you can use the flowable:taskListener extension element in the BPMN XML or the addTaskListener method in the Java API.

Task listeners provide a powerful mechanism to extend the behavior of user tasks and integrate custom logic into your processes. They allow you to perform actions such as sending notifications, updating external systems, or performing additional validations based on the events that occur during the lifecycle of a user task.

XML representation

<userTask id="approve-invoice" name="Approve invoice" jmix:assigneeSource="expression">
  <extensionElements>
    . . .
    <flowable:taskListener class="com.company.demo.listener.ApproverAssignment" (1)
                           event="assignment" /> (2)
  </extensionElements>
 . . .
</userTask>
1  — Task listener class
2  — Task event

See details in the Task Listeners section.

Task Documentation (Description)

To provide user with additional information, we have parameter documentation like it named in BPMN, or description as it is named in API. It can be no more than 4000 characters long.

Originally documentation field was intended to document a process model by analytics. But in the case of User task it can be considered as instruction for user, explaining what to do.

You can find this field at the very end of the properties panel.

You can update the documentation field every time you change your process. Thus, it’s the easiest and effective way to provide users with actual information.