Skip to content

Commit

Permalink
Merge branch 'main' into docs-aws-s3-connector
Browse files Browse the repository at this point in the history
  • Loading branch information
mesellings authored Jan 10, 2025
2 parents 930e0a4 + f66cf3c commit 373f6a2
Show file tree
Hide file tree
Showing 15 changed files with 330 additions and 2,151 deletions.
12 changes: 8 additions & 4 deletions docs/apis-tools/camunda-api-rest/camunda-api-rest-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ Ensure you [authenticate](./camunda-api-rest-authentication.md) before accessing

## Context paths

For SaaS: `https://${REGION}.zeebe.camunda.io:443/${CLUSTER_ID}/v2/`, and for Self-Managed installations: `http://localhost:8080/v2/`.
### SaaS

:::note
Find your region and cluster ID under **Connection information** in your client credentials (revealed when you click on your client under the **API** tab within your cluster).

For Self-Managed, the host and port depend on your configuration. The context path mentioned here is the default for the Zeebe component.
:::
Example path: `https://${REGION}.zeebe.camunda.io:443/${CLUSTER_ID}/v2/`

### Self-Managed

The context path should match the host and path defined in your Zeebe Gateway [configuration](/self-managed/setup/guides/ingress-setup.md). The path used here is the default.

Example path: `http://localhost:8080/v2/`

## API Explorer

Expand Down
10 changes: 5 additions & 5 deletions docs/apis-tools/zeebe-api/gateway-service.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,11 @@ message JobResult{
optional bool denied = 1;
// Attributes that were corrected by the worker.
// The following attributes can be corrected, additional attributes will be ignored:
// * `assignee` - reset by providing an empty string
// * `dueDate` - reset by providing an empty string
// * `followUpDate` - reset by providing an empty string
// * `candidateGroups` - reset by providing an empty list
// * `candidateUsers` - reset by providing an empty list
// * `assignee` - clear by providing an empty string
// * `dueDate` - clear by providing an empty string
// * `followUpDate` - clear by providing an empty string
// * `candidateGroups` - clear by providing an empty list
// * `candidateUsers` - clear by providing an empty list
// * `priority` - minimum 0, maximum 100, default 50
// Omitting any of the attributes will preserve the persisted attribute's value.
optional JobResultCorrections corrections = 2;
Expand Down
37 changes: 37 additions & 0 deletions docs/components/concepts/job-workers.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,43 @@ There are several advantages when failing a job with variables. Consider the fol

:::

### Using job result

Job workers can provide a **job result** for [user task listeners](components/concepts/user-task-listeners.md).

Job results are used to define:

1. **Corrections**: Updates to specific user task attributes, such as assignee, due date, follow-up date, candidate users, candidate groups, and priority, before the task transition is finalized. For more details, see [correcting user task data](components/concepts/user-task-listeners.md/#correcting-user-task-data).
2. **Denial**: Indicates that the lifecycle transition should be explicitly denied. Denying the task lifecycle transition rolls back the user task to the previous state, and discards any corrections made by previous listeners. For more details, see [denying the operation](components/concepts/user-task-listeners.md/#denying-the-operation).

Below is an example of using job result:

```java
final JobHandler userTaskListenerHandler =
(jobClient, job) -> {
boolean shouldDeny = someValidationLogic(job);

jobClient
.newCompleteCommand(job)
// highlight-start
.withResult(
new CompleteJobResult()
.correctAssignee("john_doe")
.correctPriority(42)
.deny(shouldDeny)) // deny based on validation logic
// highlight-end
.send();
};
```

If both corrections and denial are provided in the same job result (for example, `.correctAssignee(...)` and `.deny(true)`), the job completion command will be rejected. To avoid this, ensure the job is either completed with corrections (without denial set to `true`) or denied (without corrections).

:::info

The `corrections` and `deny` features are currently available only for user task listener jobs.

:::

## Timeouts

If the job is not completed or failed within the configured job activation timeout, Zeebe reassigns the job to another job worker. This does not affect the number of `remaining retries`.
Expand Down
183 changes: 183 additions & 0 deletions docs/components/concepts/user-task-listeners.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
---
id: user-task-listeners
title: "User task listeners"
description: "User task listeners allow users to react to specific user task lifecycle events."
---

A user task listener allows users to react to specific user task lifecycle events.

## About user task listeners

User task listeners provide flexibility and control over user task behavior:

- They can react to user task lifecycle events, such as assigning and completing.
- They can access user task data, such as the assignee, to execute task-specific business logic.
- They can dynamically correct user task data during execution, allowing adjustments to key attributes such as the assignee, due date, and priority.
- They can deny state transitions, rolling back the task to its previous state, which enables validation of task lifecycle changes.

### Use cases

User task listeners are useful in the following scenarios:

- Implementing complex user task assignment or reassignment logic.
- Validating user task lifecycle changes, e.g. completing with valid variables.
- Notifying users of new task assignments with contextual information.
- Reacting to task completions with custom logic.

### Blocking behavior

User task listeners operate in a blocking manner, meaning the user task lifecycle transition is paused until the task listener completes. This ensures that any corrections or validations defined by the task listener are fully applied before the task transition continues.

## Define a user task listener

You can configure user task listeners per BPMN user task element.

### Supported events

Currently, user task listeners support the following events:

- **Assigning**: Triggered when assigning a user task.
- **Completing**: Triggered when completing a user task.

### User task listener properties

Each user task listener has the following properties:

| Property | Description |
| :---------- | :----------------------------------------------------------------------------------------------------------- |
| `eventType` | Specifies the user task event that triggers the listener. Supported values are `assigning` and `completing`. |
| `type` | The name of the job type. |
| `retries` | The number of retries for the user task listener job. |

:::note
If multiple user task listeners of the same `eventType` (such as multiple `assigning` listeners) are defined on the same user task, they are executed sequentially, one after the other, in the order they are defined in the BPMN model.
:::

## Implement a user task listener

User task listeners are implemented using [job workers](/components/concepts/job-workers.md), similar to execution listeners and service task jobs. The job worker processes the task listener job, can apply corrections, and may optionally deny the lifecycle transition.

See [open a job worker](/apis-tools/java-client-examples/job-worker-open.md) for an example of how to create a job worker and handler that can also process user task listener jobs.

### Accessing user task data

User task-specific data, such as `assignee` and `priority`, is accessible through the job headers of the user task listener job. The following properties can be retrieved using reserved header names:

| Property | Header name |
| ----------------- | ---------------------------------- |
| `action` | `io.camunda.zeebe:action` |
| `assignee` | `io.camunda.zeebe:assignee` |
| `candidateGroups` | `io.camunda.zeebe:candidateGroups` |
| `candidateUsers` | `io.camunda.zeebe:candidateUsers` |
| `dueDate` | `io.camunda.zeebe:dueDate` |
| `followUpDate` | `io.camunda.zeebe:followUpDate` |
| `formKey` | `io.camunda.zeebe:formKey` |
| `priority` | `io.camunda.zeebe:priority` |
| `userTaskKey` | `io.camunda.zeebe:userTaskKey` |

Below is an example of accessing the `assignee` value from the headers in Java:

```java
final JobHandler userTaskListenerHandler =
(jobClient, job) -> {
// Access the 'assignee' from the job headers
// highlight-start
final String assignee = job.getCustomHeaders()
.get("io.camunda.zeebe:assignee");
// highlight-end

System.out.println("The assignee for this user task is: " + assignee);

// remaining job handler logic
};
```

Each header provides user task metadata that can be leveraged to customize the behavior of the user task listener job. Use these headers to retrieve necessary information about the user task in your job handler implementation.

### Correcting user task data

User task listeners can correct user task data before the lifecycle transition is finalized. Corrections allow user task listeners to update specific attributes of the user task, such as the assignee, due date, follow-up date, candidate users, candidate groups, and priority. These corrections are immediately available to any subsequent task listeners and are applied to the user task when the lifecycle transition is finalized, without triggering the `UPDATING` lifecycle event.

If a lifecycle transition is denied by a listener, no corrections are applied to the user task.

Below is an example of how to correct the user task data from a job worker while completing the user task listener job in Java:

```java
final JobHandler completeTaskListenerJobWithCorrectionsHandler =
(jobClient, job) ->
jobClient
.newCompleteCommand(job)
// highlight-start
.withResult(
new CompleteJobResult()
.correctAssignee("john_doe") // assigns the user task to 'john_doe'
.correctDueDate(null) // preserves the current 'dueDate' of the user task
.correctFollowUpDate("") // clears the 'followUpDate'
.correctCandidateUsers(List.of("alice", "bob")) // sets candidate users
.correctCandidateGroups(List.of()) // clears the candidate groups
.correctPriority(80)) // sets the priority to 80
// highlight-end
.send();

client.newWorker()
.jobType("user-task-listener-completion") // type of the user task listener job
.handler(completeTaskListenerJobWithCorrectionsHandler)
.open();
```

### Denying the lifecycle transition

User task listeners can deny the user task lifecycle transition belonging to the lifecycle event. For example, it can deny the completion of a task in reaction to the completing event, effectively preventing a user request to complete the task.

When a lifecycle transition is denied:

- **Corrections discarded**: Any corrections made by preceding listeners within the same lifecycle transition are discarded.
- **Task state preserved**: The user task retains its state and data as if the lifecycle event never occurred.

This capability is particularly useful for implementing validation logic or enforcing business rules before allowing a user task lifecycle transition to proceed.

Below is an example of how to deny a user task lifecycle transition from a job worker while completing the user task listener job in Java:

```java
final JobHandler denyUserTaskLifecycleTransitionHandler =
(jobClient, job) ->
jobClient
.newCompleteCommand(job)
// highlight-start
.withResult()
.deny(true)
// highlight-end
.send();
```

## Expression evaluation and incident behavior

### Expression evaluation

User task listener properties, such as job `type` or `retries`, are evaluated right before the job creation for the listener.

### Incident recovery

If a user task listener job fails or its expression evaluation raises an [incident](/components/concepts/incidents.md), the lifecycle transition is paused until the incident is resolved.

There are two types of incidents for task listeners:

- **Expression evaluation failure**: Raised when a listener property expression fails to evaluate. After the incident is resolved, the entire lifecycle transition is retried, re-executing all listeners configured for the transition, including those that previously completed successfully.
- **Job failure**: If a listener job fails, it is retried according to the `retries` property. If all retries are exhausted and the job still fails, an incident is raised. Once resolved, only the failed listener job is retried, allowing the lifecycle transition to resume without re-executing successfully completed listeners.

## Limitations

User task listeners have the following limitations:

- **Limited events support**: Currently, only `assigning` and `completing` events are supported.
- **No variable handling**: User task listener jobs cannot be completed if variables are provided.
- **No BPMN error throwing**: Throwing BPMN errors from user task listener jobs is not supported.

## Related resources

- [Job workers (basics)](/components/concepts/job-workers.md)
- [Job workers (Java client)](/apis-tools/java-client/job-worker.md)
- [Incidents](/components/concepts/incidents.md)
- [Expressions](/components/concepts/expressions.md)
- [Execution listeners](/components/concepts/execution-listeners.md)
- [User tasks](/components/modeler/bpmn/user-tasks/user-tasks.md)
38 changes: 38 additions & 0 deletions docs/components/modeler/bpmn/user-tasks/user-tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,27 @@ A user task can define an arbitrary number of `taskHeaders`; they are static
metadata stored with the user task in Zeebe. The headers can be used as
configuration parameters for tasklist applications.

### User task listeners

User tasks support **user task listeners**, which allow you to react to user task lifecycle events.

#### Supported events

Currently, user task listeners can react to the following events:

- **Assigning**: Triggered while assigning a user task.
- **Completing**: Triggered while completing a user task.

#### Configuration

To define a user task listener, include the `zeebe:taskListeners` extension element within the user task in your BPMN model. This element can contain one or more `zeebe:taskListener` elements, each specifying the following attributes:

- The `eventType` that triggers the listener (`"assigning"` or `"completing"`).
- The `type` of the listener (job type used by the external worker).
- The number of `retries` for the user task listener job (defaults to 3 if omitted).

For more details, see [user task listeners](components/concepts/user-task-listeners.md).

## Job worker implementation

A user task does not have to be managed by Zeebe. Instead, you can also use
Expand Down Expand Up @@ -285,9 +306,26 @@ A job-based user task with an embedded Camunda Form:
</bpmn:process>
```

#### User task listeners

A user task with user task listeners configured:

```xml
<bpmn:userTask id="configure" name="Configure">
<bpmn:extensionElements>
<zeebe:taskListeners>
<zeebe:taskListener eventType="assigning" type="assigning-user-task-listener" retries="5" />
<zeebe:taskListener eventType="completing" type="completing-user-task-listener" />
</zeebe:taskListeners>
<zeebe:userTask/>
</bpmn:extensionElements>
</bpmn:userTask>
```

### References

- [Tasklist](/components/tasklist/introduction-to-tasklist.md)
- [Form linking in Modeler](/components/modeler/web-modeler/advanced-modeling/form-linking.md)
- [Job handling](/components/concepts/job-workers.md)
- [Variable mappings](/components/concepts/variables.md#inputoutput-variable-mappings)
- [User task listeners](/components/concepts/user-task-listeners.md)
Loading

0 comments on commit 373f6a2

Please sign in to comment.