Repository navigation
Configuration
This page names every key the Business Cockpit reads in an application whose workflows run on Camunda 8, and what changed against version 1.
-
Where the keys live
The four sections the cockpit is configured in, and which of them wins. -
What the Camunda 8 half reads
The keys of the cluster it listens to, all of them the adapter's own. -
Where the reports go
The cockpit server's address, or the Kafka brokers, and the templates. -
What a workflow module tells the cockpit
Where the module answers, how its forms are served, in which languages it reports and who names the initiator of its reports. -
What changed against version 1
The keys which are gone, the keys which are new, the two settings which behave differently, and where the cockpit still waits for the cluster.
Every key the Business Cockpit reads is the key version 1 read, in the place version 1 read it:
vanillabp.cockpit.<key>
vanillabp.workflow-modules.<moduleId>.cockpit.<key>
vanillabp.workflow-modules.<moduleId>.workflows.<process>.cockpit.<key>
vanillabp.workflow-modules.<moduleId>.workflows.<process>.user-tasks.<task>.cockpit.<key>
The most specific value wins per key. What a user task says beats what its workflow says, and what a
workflow says beats what its workflow module says. Some settings hold for the whole application: the
transport, the templates and the two switches. Those are written once at the top and exist nowhere
else. initiator-source is the one exception: it stands at the top, and a workflow module or a single
workflow may still answer it for itself.
VanillaBP reads nothing below vanillabp.cockpit, so the cockpit binds that part of the tree itself on
both platforms. On Quarkus that binding is also what lets the application start at all, because a key
below vanillabp which nothing declares ends the startup there. A misspelled key ends the Quarkus build
with a message naming it and the key it was nearest to. A key of version 1 which is gone ends the build
with a message saying what became of that key. Spring Boot ignores both. A workflow module's own
defaults file (<moduleId>.yaml next to its BPMN files) carries these keys as well, below everything the
application itself writes.
The Camunda 8 half of the cockpit adds no key of its own. It has to know a few things about a cluster:
where that cluster is, which tenant a workflow module is deployed under, how long a listener job stays
locked for its worker, and how that worker polls. It reads all of that from
vanillabp.adapters.<id>.*, which the
VanillaBP Camunda 8 adapter owns.
Configure the cluster there, and the cockpit follows.
The lock of its workers is job-timeout. The cockpit asks for it at the workflow module, and at the
adapter where the module says nothing. One worker serves a job type across every process which uses it,
so a lock resolved per process would be several locks for one worker.
stream-enabled, poll-interval and request-timeout are never set on a worker of the cockpit. The
adapter puts them on the client it builds, every worker of that client inherits them, and an environment
variable can still overrule them there. stream-timeout has no such setting on the client, so the
cockpit's workers read it from the adapter's configuration themselves. Either way, an application which
tuned its adapter tuned the cockpit's workers with it.
job-lease decides for the cockpit's workers too. They lease their activations where the adapter leases
its own, and they have no switch of their own. Two components which lease one job type with different
answers starve each other. What the lease buys, and what it costs a rolling upgrade, is explained in
When a report takes longer than its lock.
The cockpit insists on one thing about your cluster, and the adapter insists on it too. The cluster has
to have secondary storage (camunda.data.secondary-storage.type). A report of an event is built from the
listener job and needs nothing else. But aggregateChanged and getUserTask search that storage for
the workflows and the tasks of a case, and the adapter asks it which case a called process belongs to.
Configure exactly one transport. Neither of them, or both of them, ends the boot with a message naming the keys of both.
These keys stand below vanillabp.cockpit.
| Key | What it is |
|---|---|
user-tasks-enabled |
false stops user tasks from being reported at all |
workflow-list-enabled |
false stops workflows from being reported at all |
rest.base-url |
The address of the cockpit server's BPMS API, and with it the choice of the REST transport |
rest.authentication.basic |
true sends a basic authentication with every report |
rest.authentication.username, rest.authentication.password
|
The user it is sent with |
rest.authentication.oauth.base-url |
Where tokens are issued, and with it the choice of the client-credentials flow |
rest.authentication.oauth.client-id, …client-secret
|
The client the token is asked for |
rest.authentication.oauth.basic |
true sends the client in an Authorization header instead of in the token request |
rest.connect-timeout, rest.read-timeout
|
How long connecting and answering may take, as the number of milliseconds version 1 expected or written with a unit (1500ms, PT20S); 1.5 and 10 seconds by default |
rest.proxy.host, rest.proxy.port
|
The HTTP proxy the cockpit server is reached through |
rest.proxy.username, rest.proxy.password
|
The user that proxy expects, where it expects one |
rest.verify-ssl |
false switches the certificate check off altogether |
rest.ssl-truststore-filename, rest.ssl-truststore-password
|
The PKCS12 file the server's certificate is checked against |
kafka.bootstrap-servers |
The brokers, and with them the choice of the Kafka transport |
kafka.topics.user-task |
The topic user-task reports go to |
kafka.topics.workflow |
The topic workflow reports go to |
kafka.topics.workflow-module |
The topic a workflow module registers itself on |
kafka.properties.<name> |
Any further producer setting, handed to the client unchanged |
template-loader-path |
The directory the title templates are loaded from |
The client-credentials flow configures its own connection, the way it did in version 1.
connect-timeout, read-timeout, verify-ssl, ssl-truststore-filename, ssl-truststore-password
and proxy.* below rest.authentication.oauth describe the way to the authorization server. They
inherit nothing from rest.*.
No key switches a request log on. The REST client logs through SLF4J, so set the logger
io.vanillabp.cockpit.bpms.api.v1_1.BpmsApi to DEBUG to see what is sent.
These stand below vanillabp.workflow-modules.<moduleId>.cockpit, because that is what they are about.
| Key | What it is |
|---|---|
workflow-module-uri |
Where the module answers the cockpit's provider APIs |
ui-uri-type |
A name agreed with your cockpit user interface; VanillaBP knows none |
ui-uri-path |
Where the module's forms are served from |
i18n-languages |
The languages titles are reported in, written as a list |
bpmn-description-language |
The language the names in the BPMN files are written in; mandatory without templates |
group-hierarchy.<group> |
Which groups a group stands for, written as a list |
template-path |
The segment this module contributes to the template lookup path |
initiator-source |
Who names the user who caused a report: by-application or system. No default |
A gap is reported at startup, and every gap of the application is reported in one boot, each line naming the key which fixes it. A workflow module which writes none of these keys reports nothing to the cockpit, and the log says so while the application starts.
initiator-source is the one key here which has no default. A module which reports to the cockpit and
answers it at no level ends the boot. Write by-application where a @WorkflowDetailsProvider or
@UserTaskDetailsProvider method of yours sets the initiator from what the workflow aggregate knows
about the user, and system where the module knows no action a user causes. Camunda 8 cannot answer
it for you. A listener job does not carry the user who started an instance, and the searchable storage
does not hold that user either. So this adapter prefills nothing here. An application which answers the
same way for all of its modules writes it once at vanillabp.cockpit.initiator-source.
Four of these mean something for a single workflow as well, and one of them for a single user task.
Both levels have a cockpit section of their own, and the most specific value wins per key:
vanillabp:
workflow-modules:
taxi-ride:
cockpit:
initiator-source: by-application
i18n-languages:
- en
- de
group-hierarchy:
TEAM_LEAD:
- TEAM_MEMBER
- ASSISTANT
workflows:
TaxiRide:
cockpit:
i18n-languages:
- fr
template-path: rides
user-tasks:
approve:
cockpit:
template-path: approval| Key | What it is |
|---|---|
workflows.<process>.cockpit.i18n-languages |
The languages this workflow's titles are reported in |
workflows.<process>.cockpit.bpmn-description-language |
The language this workflow's BPMN names are written in |
workflows.<process>.cockpit.template-path |
The segment this workflow contributes to the template lookup path |
workflows.<process>.user-tasks.<task>.cockpit.template-path |
The segment this user task contributes |
workflows.<process>.cockpit.initiator-source |
Who names the initiator of this one workflow's reports |
The module still says i18n-languages and bpmn-description-language itself. A workflow which
disagrees overrules it for its own reports. initiator-source works the same way, so a module whose
cases are started by users can still say system for the one workflow a nightly job starts.
Every key not named here is the key it was, in the place it was. These are gone, one reason each:
| Version 1 key | Why it is gone |
|---|---|
vanillabp.cockpit.rest.log |
the client logs through SLF4J, so set the logger io.vanillabp.cockpit.bpms.api.v1_1.BpmsApi to DEBUG
|
vanillabp.cockpit.rest.additional-get-parameters.<name> |
it appended query parameters to GET requests, and every report is a POST |
vanillabp.cockpit.rest.retry.enabled, .max-attempts, .period, .max-period
|
a failed report waits in the outbox and is repeated from there, which vanillabp.outbox.* configures |
vanillabp.cockpit.kafka.group-id-suffix |
it made a consumer group unique, and the adapter only produces |
vanillabp.cockpit.jwt.hmacSHA256-base64, vanillabp.cockpit.jwt.cookie.*
|
version 1 bound them and read them nowhere, and the cockpit server configures its own tokens |
vanillabp.workflow-modules.<id>.cockpit.group-hierarchy-bean-name |
the hierarchy is configuration, and which groups may see a module is answered by the WorkflowModuleDetailsProvider bean |
workerId |
it named the instance a report came from, and the adapter takes the host name for that |
spring.application.name |
only the Camunda 8 exporter path read it, and that path is gone |
spring.kafka.consumer.*, camunda.zeebe.kafka-exporter.topic-name
|
version 1 also consumed a topic a Camunda 8 exporter wrote, and version 2 learns the same from the listeners it puts into the models |
io.vanillabp.businesscockpit.tasklistener.prefixes, io.vanillabp.businesscockpit.executionlistener.prefixes, io.vanillabp.deployment.priority
|
entries of an in-memory map of version 1's deployment rather than keys of a configuration file; a job type of this adapter is recognized by its own prefix |
Three keys are not version 1's. vanillabp.cockpit.kafka.bootstrap-servers and
vanillabp.cockpit.kafka.properties.* are what version 1 took from spring.kafka.bootstrap-servers
and spring.kafka.producer.*. The cockpit now builds its own producer, on both platforms.
vanillabp.cockpit.process-engine-api.remembered-user-tasks belongs to the cockpit's
Process-Engine-API half and does nothing in an application running on Camunda 8.
The keys the cockpit had of its own below vanillabp.workflow-modules.<id>.adapters.camunda8 are the
Camunda 8 adapter's now:
| Version 1 key | What reads it now |
|---|---|
use-tenants |
vanillabp.adapters.<id>.name-clash-avoidance, whose default by-adapter is what use-tenants: true was |
tenant-id |
vanillabp.adapters.<id>.tenant-id; unset, the tenant is the workflow module id, as in version 1 |
task-timeout (per workflow module, per workflow, per task) |
vanillabp.adapters.<id>.job-timeout, resolved at the same levels; the cockpit's workers ask for it at the workflow module, because one worker serves a job type for every process which uses it |
poll-interval (same three levels) |
vanillabp.adapters.<id>.poll-interval, per adapter rather than per workflow or task |
poll-request-timeout (same three levels) |
vanillabp.adapters.<id>.request-timeout, per adapter |
stream-enabled (same three levels) |
vanillabp.adapters.<id>.stream-enabled, per adapter |
stream-timeout (same three levels) |
vanillabp.adapters.<id>.stream-timeout, per adapter |
workflow-visibility-timeout |
nothing of the cockpit's own; the waits which are left read the adapter's vanillabp.adapters.<id>.workflow-visibility-timeout, see below
|
Those five worker keys were the cockpit's own copy of what the Camunda 8 adapter already configured. A worker of the cockpit is a worker on the same cluster, so it is opened the way the adapter opens its own. The three finer levels the four poll and stream keys had are gone with them. Those settings describe a connection rather than a task, and the adapter keeps them per adapter id.
Two things behave differently although they are spelled the same. The timeouts accept the number of milliseconds version 1 expected, and they accept the spelling both platforms use; their defaults are version 1's, 1.5 and 10 seconds. And every setting is read and checked while the application starts, rather than when the first event arrives, so the log of the first boot is what you work from.
workflow-visibility-timeout said how long version 1 would keep asking the cluster for a workflow it had
just been told about, inside the transaction of the caller. That key is gone, and so is that waiting.
Version 2 does not ask in the caller's transaction. A change reported for a workflow the cluster does not
know yet is built when the outbox sends it. It is sent again a little later while the cluster still does
not know the workflow.
The cockpit still waits for the cluster in two places. Both wait for the cluster's secondary storage,
which runs a little behind the engine. Both read the Camunda 8 adapter's key of the same name,
vanillabp.adapters.<id>.workflow-visibility-timeout. It is ten seconds by default, and zero switches the
waiting off. The key belongs to the
VanillaBP Camunda 8 adapter,
which waits that long for the same storage. So you set it once, for both.
| Line | When it waits | What it waits for |
|---|---|---|
| 8.8 | in every listener job, and for every task read from the storage | the root of the call hierarchy, because the job does not name it |
| 8.8, 8.9, 8.10 | for a called process which shares its workflow aggregate with another process | the chain of calls above it, which says the case it belongs to |
On 8.8 a job does not say whether another process called its workflow. So the cockpit asks the cluster for the call hierarchy of the job's process instance. It asks once per instance and remembers the answer. It waits only while the storage does not know the instance at all. That can happen to any workflow which started a moment ago, called or not. If the time runs out, the cockpit treats the workflow as a case of its own, and the log says so. On 8.9 and 8.10 the job names its root, so nothing is asked here.
On every line, a called process which shares its workflow aggregate with another process needs the chain of calls above it. That chain says which case the process belongs to, see A called process. A workflow nobody called and a called process with an aggregate of its own cost no request. If the time runs out, the report goes to the top of the hierarchy, and the log says so. On 8.8 this wait is normally short, because the first one already waited for the same storage.
Both waits happen inside a listener job. The transition waits for them, and the time counts against the
lock of the job, see When a report takes longer than its lock.
They also happen when a report is built from the storage. That is when the outbox sends a change you
reported, and when getUserTask answers. They never happen in the transaction of aggregateChanged. Set
the key to zero where a transition must not wait. Then the cockpit asks once and takes the answer it
gets. Why line 8.8 pays more is
decision 7.
Why a called process may be a case of its own is
decision 3.
The lines are listed in the
README of the repository.
What else changes for an application coming from version 1 is on Migrating from Version 1.
