Repository navigation
Migrating from version 1
An application which reported to the Business Cockpit with the version 1 adapters keeps almost everything. The business code is untouched, and so is the configuration. What changes is the dependency, and the reason it changes is that the whole application moves from VanillaBP 1 to VanillaBP 2.
So this is a step inside a bigger move rather than a migration of its own. What VanillaBP 2 asks of your application is in its own upgrade guide; this page is only about the cockpit's half.
-
What stays
The code and the keys you do not have to touch. -
The dependency
Which artifact replaces the version 1 one, and where it lives now. -
The keys which are gone
Nine of them, one reason each. -
What behaves differently
The six changes you will notice in the cockpit. -
Your own way to the cockpit
What becomes of a publishing bean of version 1. -
Where the version 1 documentation lives
For an application which stays on the old line for a while.
Your Java code. @UserTaskDetailsProvider, @WorkflowDetailsProvider, @DetailsEvent, the
prefilled details objects and BusinessCockpitService are what they were. A method which compiled
against version 1 compiles against version 2.
Your configuration. The keys are the ones version 1 read, in the places version 1 read them:
vanillabp.cockpit for the whole application, vanillabp.workflow-modules.<id>.cockpit for a
workflow module, and the workflow and user task levels below it. A list stays a list and the group
hierarchy stays a map of lists. An application upgrades by changing a dependency, and what the
cockpit adapter has become inside is nothing it has to know about. Two keys are the exception:
template-loader-path is read more strictly than before, and initiator-source is new and
mandatory. Both are described under what behaves differently.
Your cockpit server. The REST and Kafka interfaces a workflow module reports on keep their OpenAPI contracts, so a cockpit and a workflow module of different versions still understand each other.
Version 1 was an artifact of the cockpit repository, one per BPMS, together with the
adapters-commons it depended on. Those artifacts are maintained for the 0.8.x line. They are not
part of 0.9.0 any more.
Version 2 has a repository per BPMS, and one artifact per platform in each of them:
| BPMS | Where it lives |
|---|---|
| Camunda 7 | businesscockpit-camunda7-adapter |
| Camunda 8 | businesscockpit-camunda8-adapter |
| Process-Engine-API | businesscockpit-process-engine-api-adapter |
Connecting a workflow module names the artifacts. Each of those
wikis has a Migrating from Version 1 page of its own for what changes about that engine, and the
Camunda 8 one is worth reading before you deploy, because the first deployment produces a new
process version.
Two things follow from the move which have nothing to do with the cockpit as such. Version 1 ran on
Spring Boot only, because it depended on VanillaBP 1's spring-boot-support. Version 2 runs on
Spring Boot and on Quarkus. And version 2 needs an outbox store in your application, because a
report is written before it is sent.
Every key not named here is the key it was. These do nothing any more, and on Quarkus a leftover one ends the build with a message saying what became of it:
| Version 1 key | Why it is gone |
|---|---|
rest.log |
The client logs through SLF4J, so set the logger io.vanillabp.cockpit.bpms.api.v1_1.BpmsApi to DEBUG
|
rest.additional-get-parameters.<name> |
It appended query parameters to GET requests, and every report is a POST |
rest.retry.* |
A failed report waits in the outbox and is repeated from there, which vanillabp.outbox.* configures |
kafka.group-id-suffix |
It made a consumer group unique, and the adapter only produces |
jwt.hmacSHA256-base64, jwt.cookie.*
|
Version 1 bound them and read them nowhere, and the cockpit server configures its own tokens |
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 |
Three keys are not version 1's. kafka.bootstrap-servers and kafka.properties.* are what version
1 took from spring.kafka.bootstrap-servers and spring.kafka.producer.*: the adapter builds its
own producer now, and does so on both platforms. process-engine-api.remembered-user-tasks comes
with the Process-Engine-API integration and does nothing on another engine.
On Spring Boot a key which is gone is simply ignored, so check by hand rather than waiting for a message.
Every user task appears now. Version 1 reported a user task only when a @UserTaskDetailsProvider
matched it and dropped the event otherwise, without saying so. Now every user task of a deployed
process is reported, and a provider decides how much the cockpit shows about it rather than whether
it shows it. Expect tasks in the cockpit which were not there before, and give them a provider or a
template where the BPMN name is not the title you want.
Nothing is lost when the cockpit server is down. Version 1 sent its reports after the transaction committed and forgot them when the send failed. A report is now an outbox entry written in the same transaction as the work which caused it, and repeated until the server takes it. What you see of that is a report arriving a moment later than it used to, and a burst of changes to one task arriving as one report carrying the current state.
A task is read when the report is sent rather than when the event happened. The assignee, the
candidates, the dates and the variables a @TaskParam parameter is bound from are read at that
point, which is what makes the collapsing above possible.
Who sees a user task is decided once. Version 1 took the assignee, the candidate groups and the
excluded users from every update, and an update could give a task to somebody else. Now the report
which creates the task in the cockpit sets the assignee, the candidates and the excluded users, and
later reports do not change them. Only taking a task over and assigning it in the cockpit still
change who has it. admittedUsers is read from every report, as before. If your workflow module
handed tasks over by reporting them again, end the task and enter it again instead, for instance
with a boundary event. See
Organizing user tasks.
Everything is validated while the application starts. Version 1 found a broken setting when the first event arrived. Now the log of the first boot is what you work from, and every gap of the application is named in one boot.
The version attribute of @UserTaskDetailsProvider is read now. Version 1 documented it and never
read it, so a method which carried one served every version of your model. It picks the method now,
and @WorkflowDetailsProvider has the same attribute. A method which names no version keeps serving
every version, so an application which never wrote the attribute reports what it always reported.
What a version may name, and what happens where the BPMS reports none, is in
Which versions of your model a method serves.
template-loader-path says where its directory is. Version 1 read a path without a prefix as a
directory of the file system, and the cockpit server read the same kind of value as a classpath
location, so one text meant two things. Now the value carries classpath: or file: in front of it,
and one without either ends the boot. The message repeats your value with both prefixes, so an
application which wrote /opt/my-application/templates writes file:/opt/my-application/templates.
classpath: and classpath*: keep working as they did.
Every report names an initiator, and one new key says who answers it. In version 1 the field was
optional and most applications left it empty. Write
vanillabp.cockpit.initiator-source: by-application where your details providers set the initiator,
or system where a workflow module knows no action a user causes. The key has no default, so an
application without it does not start. Under by-application, a report which names nobody fails,
and the engine's work fails with it. Old cases keep what they have. Nobody can work out later who
started a case which ran without an initiator. That is why you are asked once, instead of the field
being switched on quietly. The entry Every report names an initiator, and one new key says who answers it in UPGRADE.md is
the short version, and Who caused it
is the long one.
Version 1 let an application replace the way reports travel. The publishing beans were declared with
@ConditionalOnMissingBean, so an application which declared a UserTaskPublishing bean of its own
got its own way instead of REST or Kafka.
Version 2 has the same seam, in one place instead of three. A bean of type
BusinessCockpitTransport replaces both shipped transports, and it has one method per kind of
report: the user task, the workflow and the registration of the workflow module. Version 1 spread
those over UserTaskPublishing, WorkflowPublishing and WorkflowModulePublishing, so three beans
of version 1 become one class here. A bean which served one of the three and left the others to the
shipped way is written by wrapping the shipped transport, which
Connecting a workflow module shows.
What such a transport is handed differs from version 1, and in your favour. It is called while an outbox entry is dispatched, so the report has been through the BPMS and through your details provider before you see it. A call which fails is repeated with a backoff instead of losing the report. Version 1 called the publishing bean straight from the engine's thread, and a failure there was yours to survive.
An application which reports its own way configures neither vanillabp.cockpit.rest.base-url nor
vanillabp.cockpit.kafka.bootstrap-servers. Both of version 1's keys can go.
In the history of the cockpit repository. The
version 1 adapters were documented in the README files below adapters/, and 0.9.0 removed that
directory from the main branch. Read those files at the
0.4.0 tag, the last release
which carried them, or on the branch of the 0.8.x line. They are not copied into this wiki,
because that would describe an integration which no longer ships.
Releases says which line is which.
