Skip to content

Delivery modes and their impact#

The adapter delivers service tasks and user tasks through independent strategies. The selected strategy decides which Camunda API is used, which completion API is wired, how quickly task changes are visible, and which metadata is available in TaskInformation.getMeta().

Service Tasks#

Strategy Implementation Impact
SUBSCRIPTION Opens Camunda job workers for TaskType.EXTERNAL subscriptions. The subscription taskDescriptionKey is used as the job type. Service tasks are pushed by Camunda jobs. Payload variables are fetched according to the subscription payloadDescription. workerLockDurationInMilliseconds can override the configured worker lock time per subscription.
CUSTOM No built-in service task delivery bean is created. Provide your own delivery implementation. The default service task completion API is still available unless you replace it with your own bean.

User Tasks#

Strategy Implementation Impact
SCHEDULED Periodically searches Camunda user tasks with state CREATED. Uses the Camunda user task search and variable search APIs. Task delivery is delayed by schedule-delivery-fixed-rate-in-seconds. A task is delivered with reason create the first time and update when delivered again to the same subscription. The Camunda client is fetching tasks from the secondary storage, so some delay is expected.
SUBSCRIPTION_REFRESHING Opens Zeebe job workers for the Legacy Camunda user task job type and refreshes the job timeout periodically. User tasks are delivered as jobs and remain locked until completed or the lock refresh detects that the job is gone. Completion uses the job completion API. If timeout refresh returns NOT_FOUND, the subscription termination handler receives reason delete.
LISTENER Opens a worker for Camunda user task listener jobs. User task changes are delivered from task listener events. On startup, the adapter can preload already-created native user tasks once by reusing the pull delivery search. Completion uses the Camunda user task completion API.
CUSTOM No built-in user task delivery or completion bean is created. Provide your own delivery and completion implementation.

The listener strategy requires user task listener jobs with the configured topic. You can define these listeners in BPMN or enable global listener auto-registration. Auto-registration feature is supported and uses Camunda's Orchestration Cluster API and will fail startup if the API call fails.

By default, listener delivery also performs a one-shot preload of existing native user tasks during startup. This catches tasks that reached CREATED before the listener worker opened. After that preload, LISTENER remains event-driven; it does not create a scheduled polling binding.

Configuration Overview#

Spring Boot configuration is rooted at dev.bpm-crafters.process-api.adapter.c8. The adapter autoconfiguration is only active when enabled is explicitly set to true.

dev:
  bpm-crafters:
    process-api:
      adapter:
        c8:
          enabled: true
          service-tasks:
            delivery-strategy: SUBSCRIPTION
            worker-id: worker
            retries: 3
            retry-timeout-in-seconds: 5
            lock-time-in-seconds: 300
          user-tasks:
            delivery-strategy: LISTENER
            schedule-delivery-fixed-rate-in-seconds: 5
            listener:
              topic: process-engine-user-tasks
              worker-id: process-engine-user-tasks-worker
              max-jobs-active: 32
              stream-enabled: true
              lock-time-in-seconds: 300
              retry-timeout-in-seconds: 5
              auto-register-global-listener: false
              global-listener-id: process-engine-user-tasks
              global-listener-retries: 3
              global-listener-after-non-global: true
              global-listener-priority: 0
              preload-existing-tasks: true
Property Default Description
enabled Must be set Enables the C8 adapter autoconfiguration. Although the properties class defaults to true, the condition requires this property to be explicitly bound.
service-tasks.delivery-strategy Required SUBSCRIPTION or CUSTOM.
service-tasks.worker-id Required Worker name used for service task job workers and for SUBSCRIPTION_REFRESHING user task workers.
service-tasks.retries 3 Default retries used by the failure retry supplier.
service-tasks.retry-timeout-in-seconds 5 Backoff used when failing service task jobs after handler errors.
service-tasks.lock-time-in-seconds 300 Default service task worker lock time. Can be overridden by workerLockDurationInMilliseconds on a service task subscription.
user-tasks.delivery-strategy Required SCHEDULED, SUBSCRIPTION_REFRESHING, LISTENER, or CUSTOM.
user-tasks.schedule-delivery-fixed-rate-in-seconds 5 Polling interval for SCHEDULED delivery and timeout refresh interval for SUBSCRIPTION_REFRESHING.
user-tasks.listener.topic process-engine-user-tasks Camunda user task listener job type consumed by the LISTENER strategy.
user-tasks.listener.worker-id process-engine-user-tasks-worker Worker name used by the listener job worker.
user-tasks.listener.max-jobs-active 32 Maximum active listener jobs.
user-tasks.listener.stream-enabled true Enables Camunda job streaming for listener jobs.
user-tasks.listener.lock-time-in-seconds 300 Listener job lock time.
user-tasks.listener.retry-timeout-in-seconds 5 Backoff used when failing listener jobs after handler errors.
user-tasks.listener.auto-register-global-listener false If true, the adapter registers a global user task listener on startup.
user-tasks.listener.global-listener-id process-engine-user-tasks Id used for global listener auto-registration.
user-tasks.listener.global-listener-retries 3 Retry count configured for the global listener.
user-tasks.listener.global-listener-after-non-global true Configures the global listener to run after BPMN-level listeners.
user-tasks.listener.global-listener-priority 0 Priority configured for the global listener.
user-tasks.listener.preload-existing-tasks true If true, LISTENER runs one startup search for already-created native user tasks before opening the listener worker.

Message Correlation#

Correlation API implementation supports the following restrictions:

Key Value Description
tenantId Camunda tenant id Passed to the Camunda publish-message command with tenantId(value). Empty values are ignored.

All other restriction keys are rejected before the message command is sent. Message correlation uses the command's messageName, the correlationKey from cmd.correlation.get().correlationKey, and the variables from cmd.payloadSupplier.get().

Task Subscription Restrictions#

Task subscription restrictions are evaluated by the delivery strategy when a task is considered for delivery. Unknown restriction keys are not ignored; they make the task fail matching for that subscription. The workerLockDurationInMilliseconds restriction is special: it is applied as a lock-duration override for service task workers and ignored during task matching.

The subscription taskDescriptionKey is matched outside the restriction map. For service tasks it matches the Camunda job type. For user tasks it matches the BPMN user task element id (elementId). A null taskDescriptionKey matches any task of the requested task type. Payload delivery follows the API contract: payloadDescription == null delivers all available variables, an empty set delivers no variables, and a non-empty set delivers only the named variables.

Task type and strategy Supported matching keys
Service tasks, SUBSCRIPTION activityId, executionId, tenantId, processInstanceId, processDefinitionId
User tasks, SCHEDULED tenantId, processInstanceId, processDefinitionId, processDefinitionKey
User tasks, SUBSCRIPTION_REFRESHING activityId, executionId, tenantId, processInstanceId, processDefinitionId, processDefinitionKey
User tasks, LISTENER activityId, executionId, tenantId, processInstanceId, processDefinitionId, processDefinitionKey

Task Information#

The TaskInformation.getMeta() provides meta information about the task as Map<String, String> for maximum compatibility. The Original Type column denotes the source value type before the adapter serializes it into the meta map. For typed access, TaskInformation provides getMetaValueAsOffsetDate, getMetaValueAsStringSet, and getMetaValueAsInt.

Meta entries with null values are usually omitted. One current exception is scheduled user task formId, which is created with toString() and can therefore contain the literal string null if no form key is available.

Every delivery can add reason to the meta map by calling TaskInformation.withReason(...). Known reason values are create, assign, update, complete, and delete.

User Tasks#

The following table combines the user task metadata from all built-in user task delivery strategies. Legend: ❎ = supported by the strategy, 0️⃣ = not provided by the strategy.

Key SCHEDULED SUBSCRIPTION_REFRESHING LISTENER Original Type Description Example
activityId String BPMN user task element id. approve-request
executionId 0️⃣ 0️⃣ Long Camunda element instance key. 2251799813685311
processDefinitionKey String BPMN process id. invoice-process
processDefinitionId Long Camunda process definition key. 2251799813685250
processInstanceId Long Camunda process instance key. 2251799813685301
tenantId String Camunda tenant id. tenant-a
assignee String Current assignee. For SUBSCRIPTION_REFRESHING, this comes from Camunda custom headers. alice
candidateUsers Collection<String> or String Candidate users, serialized as comma-separated values. For SUBSCRIPTION_REFRESHING, this is the raw custom header value. alice,bob
candidateGroups Collection<String> or String Candidate groups, serialized as comma-separated values. For SUBSCRIPTION_REFRESHING, this is the raw custom header value. accounting,ops
followUpDate OffsetDateTime or String Follow-up date. For SUBSCRIPTION_REFRESHING, this comes from Camunda custom headers. 2026-06-23T10:15:30Z
dueDate OffsetDateTime or String Due date. For SUBSCRIPTION_REFRESHING, this comes from Camunda custom headers. 2026-06-24T10:15:30Z
creationDate 0️⃣ 0️⃣ OffsetDateTime User task creation date. 2026-06-23T09:00:00Z
processName 0️⃣ 0️⃣ String Process display name returned by Camunda. Invoice Process
taskName 0️⃣ 0️⃣ String User task display name returned by Camunda. Approve request
formId 0️⃣ 0️⃣ String Value returned by Form.formKey. Can be the literal string null. camunda-forms:bpmn:approve
formKey String Form reference. SCHEDULED maps Form.formId; SUBSCRIPTION_REFRESHING maps the form key custom header; LISTENER maps the listener user task form key. approve-form
formVersion 0️⃣ 0️⃣ Long Form version returned by Camunda. 3
taskState 0️⃣ 0️⃣ UserTaskState Camunda user task state. CREATED
topicName 0️⃣ String Activated job type or listener job type. process-engine-user-tasks
retries 0️⃣ Int Activated job retry count. 3
eventType 0️⃣ 0️⃣ ListenerEventType Camunda listener event type. CREATING
action 0️⃣ 0️⃣ String User task action from the listener job. assign
changedAttributes 0️⃣ 0️⃣ Collection<String> Changed user task attributes, serialized as comma-separated values. assignee,priority
priority 0️⃣ 0️⃣ Int User task priority. 80
reason String Delivery or termination reason added by the adapter. create

Service Tasks#

These values are mapped from Camunda activated jobs in the SUBSCRIPTION strategy.

Key Original Type Description Example
activityId String BPMN service task element id. charge-card
processDefinitionKey String BPMN process id. payment-process
processDefinitionId Long Camunda process definition key. 2251799813685250
processInstanceId Long Camunda process instance key. 2251799813685301
tenantId String Camunda tenant id. tenant-a
formKey String Custom header using Camunda's user task form key header name, if present. camunda-forms:bpmn:approve
assignee String Custom header using Camunda's user task assignee header name, if present. alice
dueDate String Custom header using Camunda's user task due date header name, if present. 2026-06-24T10:15:30Z
candidateUsers String Custom header using Camunda's user task candidate users header name, if present. Use getMetaValueAsStringSet when the value is comma-separated. alice,bob
candidateGroups String Custom header using Camunda's user task candidate groups header name, if present. Use getMetaValueAsStringSet when the value is comma-separated. accounting,ops
followUpDate String Custom header using Camunda's user task follow-up date header name, if present. 2026-06-23T10:15:30Z
topicName String Activated job type. charge-card
retries Int Activated job retry count. 3
reason String Delivery or termination reason added by the adapter. create