From 3289e132852cdef5a9304169b7c0a2b7c4ec8843 Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Sun, 11 Oct 2020 20:23:42 +0200 Subject: [PATCH 01/16] Update for next development version --- datapool/datapool-api/pom.xml | 2 +- datapool/datapool-core/pom.xml | 2 +- datapool/datapool-event/pom.xml | 2 +- datapool/pom.xml | 2 +- docs/pom.xml | 2 +- engine/camunda-engine-client/pom.xml | 2 +- engine/datapool-collector/pom.xml | 2 +- engine/pom.xml | 2 +- engine/property-taskurl-resolver/pom.xml | 2 +- engine/taskpool-collector/pom.xml | 2 +- engine/taskpool-engine-springboot-starter/pom.xml | 2 +- engine/variable-serializer/pom.xml | 2 +- examples/components/process-backend/pom.xml | 2 +- examples/components/process-forms/pom.xml | 2 +- examples/components/tasklist-angular/pom.xml | 2 +- examples/components/tasklist-api/pom.xml | 2 +- examples/components/tasklist-backend/pom.xml | 2 +- examples/components/tasklist-reactive-backend/pom.xml | 2 +- examples/components/users/pom.xml | 2 +- examples/pom.xml | 2 +- .../distributed-axon-server/camunda-webapp-application/pom.xml | 2 +- .../cockpit-application/application/pom.xml | 2 +- .../distributed-axon-server/cockpit-application/backend/pom.xml | 2 +- .../cockpit-application/frontend/pom.xml | 2 +- .../distributed-axon-server/cockpit-application/pom.xml | 2 +- examples/scenarios/distributed-axon-server/pom.xml | 2 +- .../distributed-axon-server/process-application/pom.xml | 2 +- .../distributed-axon-server/taskpool-application/pom.xml | 2 +- examples/scenarios/pom.xml | 2 +- examples/scenarios/single-node/pom.xml | 2 +- pom.xml | 2 +- taskpool/pom.xml | 2 +- taskpool/taskpool-api/pom.xml | 2 +- taskpool/taskpool-core/pom.xml | 2 +- taskpool/taskpool-event/pom.xml | 2 +- view/mongo/pom.xml | 2 +- view/pom.xml | 2 +- view/simple/pom.xml | 2 +- view/view-api/pom.xml | 2 +- 39 files changed, 39 insertions(+), 39 deletions(-) diff --git a/datapool/datapool-api/pom.xml b/datapool/datapool-api/pom.xml index a26efef2d..21844cbe6 100755 --- a/datapool/datapool-api/pom.xml +++ b/datapool/datapool-api/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-datapool-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-datapool-api diff --git a/datapool/datapool-core/pom.xml b/datapool/datapool-core/pom.xml index 9c4874d32..407b260a3 100755 --- a/datapool/datapool-core/pom.xml +++ b/datapool/datapool-core/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-datapool-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-datapool-core diff --git a/datapool/datapool-event/pom.xml b/datapool/datapool-event/pom.xml index a35412fb4..17d2dd600 100755 --- a/datapool/datapool-event/pom.xml +++ b/datapool/datapool-event/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-datapool-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-datapool-event diff --git a/datapool/pom.xml b/datapool/pom.xml index 64cc154cd..a91a1264f 100755 --- a/datapool/pom.xml +++ b/datapool/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-datapool-root diff --git a/docs/pom.xml b/docs/pom.xml index b1a7fcbe4..5613c8032 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-docs diff --git a/engine/camunda-engine-client/pom.xml b/engine/camunda-engine-client/pom.xml index 0a3ab634e..e8d6d9938 100644 --- a/engine/camunda-engine-client/pom.xml +++ b/engine/camunda-engine-client/pom.xml @@ -4,7 +4,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-engine-client diff --git a/engine/datapool-collector/pom.xml b/engine/datapool-collector/pom.xml index 7f7f97938..2b59c9ff4 100755 --- a/engine/datapool-collector/pom.xml +++ b/engine/datapool-collector/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-datapool-collector diff --git a/engine/pom.xml b/engine/pom.xml index 43a122085..15903d101 100755 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-engine-root diff --git a/engine/property-taskurl-resolver/pom.xml b/engine/property-taskurl-resolver/pom.xml index c1e2ef92b..f724c8365 100644 --- a/engine/property-taskurl-resolver/pom.xml +++ b/engine/property-taskurl-resolver/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.2 + 2.1.3-SNAPSHOT taskpool-property-taskurl-resolver diff --git a/engine/taskpool-collector/pom.xml b/engine/taskpool-collector/pom.xml index 66a42de4b..60ceb85d3 100755 --- a/engine/taskpool-collector/pom.xml +++ b/engine/taskpool-collector/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-collector diff --git a/engine/taskpool-engine-springboot-starter/pom.xml b/engine/taskpool-engine-springboot-starter/pom.xml index e83834daf..5db2f01e9 100755 --- a/engine/taskpool-engine-springboot-starter/pom.xml +++ b/engine/taskpool-engine-springboot-starter/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-engine-springboot-starter diff --git a/engine/variable-serializer/pom.xml b/engine/variable-serializer/pom.xml index 912e0b3ce..e18875cb7 100755 --- a/engine/variable-serializer/pom.xml +++ b/engine/variable-serializer/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-variable-serializer diff --git a/examples/components/process-backend/pom.xml b/examples/components/process-backend/pom.xml index a5e6b6205..4526f1c1a 100755 --- a/examples/components/process-backend/pom.xml +++ b/examples/components/process-backend/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.2 + 2.1.3-SNAPSHOT ../../pom.xml diff --git a/examples/components/process-forms/pom.xml b/examples/components/process-forms/pom.xml index f26175deb..c4e278cd5 100755 --- a/examples/components/process-forms/pom.xml +++ b/examples/components/process-forms/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.2 + 2.1.3-SNAPSHOT ../../pom.xml diff --git a/examples/components/tasklist-angular/pom.xml b/examples/components/tasklist-angular/pom.xml index c96d9bc43..230de72ab 100755 --- a/examples/components/tasklist-angular/pom.xml +++ b/examples/components/tasklist-angular/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.2 + 2.1.3-SNAPSHOT ../../pom.xml diff --git a/examples/components/tasklist-api/pom.xml b/examples/components/tasklist-api/pom.xml index c31943d8c..cef90848d 100755 --- a/examples/components/tasklist-api/pom.xml +++ b/examples/components/tasklist-api/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.2 + 2.1.3-SNAPSHOT ../../pom.xml diff --git a/examples/components/tasklist-backend/pom.xml b/examples/components/tasklist-backend/pom.xml index a0ac55adc..9b8f86c78 100755 --- a/examples/components/tasklist-backend/pom.xml +++ b/examples/components/tasklist-backend/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.2 + 2.1.3-SNAPSHOT ../../pom.xml diff --git a/examples/components/tasklist-reactive-backend/pom.xml b/examples/components/tasklist-reactive-backend/pom.xml index f01f21887..8575a83a4 100755 --- a/examples/components/tasklist-reactive-backend/pom.xml +++ b/examples/components/tasklist-reactive-backend/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.2 + 2.1.3-SNAPSHOT ../../pom.xml diff --git a/examples/components/users/pom.xml b/examples/components/users/pom.xml index 9a23df373..24bdc97d2 100644 --- a/examples/components/users/pom.xml +++ b/examples/components/users/pom.xml @@ -7,7 +7,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.2 + 2.1.3-SNAPSHOT ../../pom.xml diff --git a/examples/pom.xml b/examples/pom.xml index 5157816eb..ed2fb7fff 100755 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.2 + 2.1.3-SNAPSHOT taskpool-examples-root diff --git a/examples/scenarios/distributed-axon-server/camunda-webapp-application/pom.xml b/examples/scenarios/distributed-axon-server/camunda-webapp-application/pom.xml index ac4569b1a..042594b18 100755 --- a/examples/scenarios/distributed-axon-server/camunda-webapp-application/pom.xml +++ b/examples/scenarios/distributed-axon-server/camunda-webapp-application/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-distributed-axon-server - 2.1.2 + 2.1.3-SNAPSHOT example-distributed-axon-server-webapp-application diff --git a/examples/scenarios/distributed-axon-server/cockpit-application/application/pom.xml b/examples/scenarios/distributed-axon-server/cockpit-application/application/pom.xml index 2c0f5a827..00e51bff7 100755 --- a/examples/scenarios/distributed-axon-server/cockpit-application/application/pom.xml +++ b/examples/scenarios/distributed-axon-server/cockpit-application/application/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-cockpit-root - 2.1.2 + 2.1.3-SNAPSHOT taskpool-example-cockpit diff --git a/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml b/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml index ad2d9508a..2aceeb524 100755 --- a/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml +++ b/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-cockpit-root - 2.1.2 + 2.1.3-SNAPSHOT taskpool-example-cockpit-backend diff --git a/examples/scenarios/distributed-axon-server/cockpit-application/frontend/pom.xml b/examples/scenarios/distributed-axon-server/cockpit-application/frontend/pom.xml index 676e9f597..87a711906 100755 --- a/examples/scenarios/distributed-axon-server/cockpit-application/frontend/pom.xml +++ b/examples/scenarios/distributed-axon-server/cockpit-application/frontend/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-cockpit-root - 2.1.2 + 2.1.3-SNAPSHOT taskpool-example-cockpit-frontend diff --git a/examples/scenarios/distributed-axon-server/cockpit-application/pom.xml b/examples/scenarios/distributed-axon-server/cockpit-application/pom.xml index 0bc5b1a35..1dc152e67 100755 --- a/examples/scenarios/distributed-axon-server/cockpit-application/pom.xml +++ b/examples/scenarios/distributed-axon-server/cockpit-application/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-distributed-axon-server - 2.1.2 + 2.1.3-SNAPSHOT taskpool-example-cockpit-root diff --git a/examples/scenarios/distributed-axon-server/pom.xml b/examples/scenarios/distributed-axon-server/pom.xml index 3e96e49f6..d9320c526 100755 --- a/examples/scenarios/distributed-axon-server/pom.xml +++ b/examples/scenarios/distributed-axon-server/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-root - 2.1.2 + 2.1.3-SNAPSHOT taskpool-example-scenario-distributed-axon-server diff --git a/examples/scenarios/distributed-axon-server/process-application/pom.xml b/examples/scenarios/distributed-axon-server/process-application/pom.xml index d0f26b876..3d9b0ac62 100755 --- a/examples/scenarios/distributed-axon-server/process-application/pom.xml +++ b/examples/scenarios/distributed-axon-server/process-application/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-distributed-axon-server - 2.1.2 + 2.1.3-SNAPSHOT example-distributed-axon-server-process-application diff --git a/examples/scenarios/distributed-axon-server/taskpool-application/pom.xml b/examples/scenarios/distributed-axon-server/taskpool-application/pom.xml index 518b96e0e..bf9e96c07 100755 --- a/examples/scenarios/distributed-axon-server/taskpool-application/pom.xml +++ b/examples/scenarios/distributed-axon-server/taskpool-application/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-distributed-axon-server - 2.1.2 + 2.1.3-SNAPSHOT example-distributed-axon-server-taskpool-application diff --git a/examples/scenarios/pom.xml b/examples/scenarios/pom.xml index 7959d1c8c..b462253d7 100755 --- a/examples/scenarios/pom.xml +++ b/examples/scenarios/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.2 + 2.1.3-SNAPSHOT taskpool-example-scenario-root diff --git a/examples/scenarios/single-node/pom.xml b/examples/scenarios/single-node/pom.xml index d4312ba4a..9e2bdcebe 100755 --- a/examples/scenarios/single-node/pom.xml +++ b/examples/scenarios/single-node/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-root - 2.1.2 + 2.1.3-SNAPSHOT taskpool-example-scenario-single-node diff --git a/pom.xml b/pom.xml index 8c609633f..9cb15e360 100755 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.2 + 2.1.3-SNAPSHOT pom ${project.artifactId} diff --git a/taskpool/pom.xml b/taskpool/pom.xml index 11800744e..1fd2730a1 100755 --- a/taskpool/pom.xml +++ b/taskpool/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-root diff --git a/taskpool/taskpool-api/pom.xml b/taskpool/taskpool-api/pom.xml index 9d05941d7..50de9c474 100755 --- a/taskpool/taskpool-api/pom.xml +++ b/taskpool/taskpool-api/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-api diff --git a/taskpool/taskpool-core/pom.xml b/taskpool/taskpool-core/pom.xml index 1dfbd8a98..dab60ec09 100755 --- a/taskpool/taskpool-core/pom.xml +++ b/taskpool/taskpool-core/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-core diff --git a/taskpool/taskpool-event/pom.xml b/taskpool/taskpool-event/pom.xml index 3083ec584..12394ea9c 100755 --- a/taskpool/taskpool-event/pom.xml +++ b/taskpool/taskpool-event/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-event diff --git a/view/mongo/pom.xml b/view/mongo/pom.xml index 495a0ac61..bfe62a455 100755 --- a/view/mongo/pom.xml +++ b/view/mongo/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-view-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-view-mongo diff --git a/view/pom.xml b/view/pom.xml index 9720e76ed..bc20eb7cd 100755 --- a/view/pom.xml +++ b/view/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-view-root diff --git a/view/simple/pom.xml b/view/simple/pom.xml index d36c7c459..662367538 100755 --- a/view/simple/pom.xml +++ b/view/simple/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool-view-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-view-simple diff --git a/view/view-api/pom.xml b/view/view-api/pom.xml index 4590166aa..ea9834e5b 100755 --- a/view/view-api/pom.xml +++ b/view/view-api/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-view-root - 2.1.2 + 2.1.3-SNAPSHOT camunda-bpm-taskpool-view-api From da9402773cfbc07670fa946810ee1336f64f4ecb Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Sun, 11 Oct 2020 20:46:59 +0200 Subject: [PATCH 02/16] fixed more docs issues --- docs/src/orchid/resources/wiki/user-guide/example.ad | 2 +- docs/src/orchid/resources/wiki/user-guide/integration-guide.ad | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/orchid/resources/wiki/user-guide/example.ad b/docs/src/orchid/resources/wiki/user-guide/example.ad index c078dec86..2ff74c6fd 100644 --- a/docs/src/orchid/resources/wiki/user-guide/example.ad +++ b/docs/src/orchid/resources/wiki/user-guide/example.ad @@ -5,7 +5,7 @@ title: Example Application == {{ page.title }} Along with library modules several example modules and applications are provided, demonstrating the main features of the solution. -This includes a series of example applications for usage in different link:scenarios[Usage Scenarios]. They all share the same +This includes a series of example applications for usage in different link:../scenarios/[Usage Scenarios]. They all share the same business process described in the next section. diff --git a/docs/src/orchid/resources/wiki/user-guide/integration-guide.ad b/docs/src/orchid/resources/wiki/user-guide/integration-guide.ad index aba37b1c6..e7dfb3bfc 100644 --- a/docs/src/orchid/resources/wiki/user-guide/integration-guide.ad +++ b/docs/src/orchid/resources/wiki/user-guide/integration-guide.ad @@ -71,4 +71,4 @@ camunda: Now, start your process engine. If you run into a user task, you should see on the console how this is passed to task pool. -For more details on the configuration of different options, please consult the link:components[Taskpool Components] sections. +For more details on the configuration of different options, please consult the link:../components/[Taskpool Components] sections. From 98087ed35b3de0a4a75f6c1e9a33716b3cb64441 Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Mon, 12 Oct 2020 13:47:04 +0200 Subject: [PATCH 03/16] feature: implement process instance lifecycle tracking, fix #281 --- .../orchid/resources/changelog/2.1/2.1.3.ad | 11 ++ .../ProcessInstanceEventCollectorService.kt | 65 +++++++- .../process/service/SystemInfoPrinter.kt | 2 +- .../instance/ProcessInstanceCommand.kt | 43 +++++- .../core/process/ProcessInstanceAggregate.kt | 37 ++++- .../process/ProcessInstanceAggregateTest.kt | 140 +++++++++++++----- .../process/instance/ProcessInstanceEvents.kt | 31 +++- .../service/ProcessInstanceSimpleService.kt | 61 +++++++- 8 files changed, 332 insertions(+), 58 deletions(-) create mode 100644 docs/src/orchid/resources/changelog/2.1/2.1.3.ad diff --git a/docs/src/orchid/resources/changelog/2.1/2.1.3.ad b/docs/src/orchid/resources/changelog/2.1/2.1.3.ad new file mode 100644 index 000000000..e753812fe --- /dev/null +++ b/docs/src/orchid/resources/changelog/2.1/2.1.3.ad @@ -0,0 +1,11 @@ +--- +version: 2.1.3 +--- + +== Features + +* Respect process instance lifecycle, see #281 + +== Bugfixes + +* Fixed more documentation dead links, see #277 diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/instance/ProcessInstanceEventCollectorService.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/instance/ProcessInstanceEventCollectorService.kt index 90c71ac13..f7e9450c5 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/instance/ProcessInstanceEventCollectorService.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/instance/ProcessInstanceEventCollectorService.kt @@ -1,12 +1,11 @@ package io.holunda.camunda.taskpool.collector.process.instance import io.holunda.camunda.taskpool.TaskCollectorProperties -import io.holunda.camunda.taskpool.api.process.instance.EndProcessInstanceCommand -import io.holunda.camunda.taskpool.api.process.instance.StartProcessInstanceCommand +import io.holunda.camunda.taskpool.api.process.instance.* import io.holunda.camunda.taskpool.collector.sourceReference -import io.holunda.camunda.taskpool.collector.task.TaskEventCollectorService import mu.KLogging import org.camunda.bpm.engine.RepositoryService +import org.camunda.bpm.engine.history.HistoricProcessInstance import org.camunda.bpm.engine.impl.history.event.HistoricProcessInstanceEventEntity import org.springframework.context.event.EventListener import org.springframework.core.annotation.Order @@ -22,7 +21,7 @@ class ProcessInstanceEventCollectorService( private val repositoryService: RepositoryService ) { - companion object: KLogging() { + companion object : KLogging() { // high order to be later than all other listeners and work on changed entity const val ORDER = Integer.MAX_VALUE - 100 } @@ -37,14 +36,41 @@ class ProcessInstanceEventCollectorService( fun create(processInstance: HistoricProcessInstanceEventEntity): StartProcessInstanceCommand = processInstance .toStartProcessInstanceCommand(repositoryService, collectorProperties.enricher.applicationName) + /** + * Fires update process instance command. + * See [HistoryEventTypes.PROCESS_INSTANCE_UPDATE] + */ + @Order(ORDER) + @EventListener(condition = "#processInstance.eventType.equals('update')") + fun update(processInstance: HistoricProcessInstanceEventEntity): UpdateProcessInstanceCommand? = when (processInstance.state) { + // suspend + HistoricProcessInstance.STATE_SUSPENDED -> processInstance.toSuspendProcessInstanceCommand(repositoryService, collectorProperties.enricher.applicationName) + // resume + HistoricProcessInstance.STATE_ACTIVE -> processInstance.toResumeProcessInstanceCommand(repositoryService, collectorProperties.enricher.applicationName) + else -> { + logger.debug { "Unknown update process instance event received $processInstance" } + null + } + } + + /** * Fires end process instance command. * See [HistoryEventTypes.PROCESS_INSTANCE_END] */ @Order(ORDER) @EventListener(condition = "#processInstance.eventType.equals('end')") - fun end(processInstance: HistoricProcessInstanceEventEntity): EndProcessInstanceCommand = processInstance - .toEndProcessInstanceCommand(repositoryService, collectorProperties.enricher.applicationName) + fun end(processInstance: HistoricProcessInstanceEventEntity): EndProcessInstanceCommand? = when (processInstance.state) { + // cancel + HistoricProcessInstance.STATE_EXTERNALLY_TERMINATED -> processInstance.toCancelProcessInstanceCommand(repositoryService, collectorProperties.enricher.applicationName) + // finish + HistoricProcessInstance.STATE_INTERNALLY_TERMINATED -> processInstance.toFinishProcessInstanceCommand(repositoryService, collectorProperties.enricher.applicationName) + else -> { + logger.debug { "Unknown end process instance event received $processInstance" } + null + } + } + } private fun HistoricProcessInstanceEventEntity.toStartProcessInstanceCommand(repositoryService: RepositoryService, applicationName: String) = StartProcessInstanceCommand( @@ -60,12 +86,11 @@ private fun HistoricProcessInstanceEventEntity.toStartProcessInstanceCommand(rep } ) -private fun HistoricProcessInstanceEventEntity.toEndProcessInstanceCommand(repositoryService: RepositoryService, applicationName: String) = EndProcessInstanceCommand( +private fun HistoricProcessInstanceEventEntity.toFinishProcessInstanceCommand(repositoryService: RepositoryService, applicationName: String) = FinishProcessInstanceCommand( sourceReference = this.sourceReference(repositoryService, applicationName), processInstanceId = this.processInstanceId, businessKey = this.businessKey, endActivityId = this.endActivityId, - deleteReason = this.deleteReason, superInstanceId = when { this.superProcessInstanceId != null -> this.superProcessInstanceId this.superCaseInstanceId != null -> this.superCaseInstanceId @@ -73,3 +98,27 @@ private fun HistoricProcessInstanceEventEntity.toEndProcessInstanceCommand(repos } ) +private fun HistoricProcessInstanceEventEntity.toCancelProcessInstanceCommand(repositoryService: RepositoryService, applicationName: String) = CancelProcessInstanceCommand( + sourceReference = this.sourceReference(repositoryService, applicationName), + processInstanceId = this.processInstanceId, + businessKey = this.businessKey, + endActivityId = this.endActivityId, + superInstanceId = when { + this.superProcessInstanceId != null -> this.superProcessInstanceId + this.superCaseInstanceId != null -> this.superCaseInstanceId + else -> null + }, + deleteReason = this.deleteReason +) + + +private fun HistoricProcessInstanceEventEntity.toSuspendProcessInstanceCommand(repositoryService: RepositoryService, applicationName: String) = SuspendProcessInstanceCommand( + sourceReference = this.sourceReference(repositoryService, applicationName), + processInstanceId = this.processInstanceId, +) + + +private fun HistoricProcessInstanceEventEntity.toResumeProcessInstanceCommand(repositoryService: RepositoryService, applicationName: String) = ResumeProcessInstanceCommand( + sourceReference = this.sourceReference(repositoryService, applicationName), + processInstanceId = this.processInstanceId, +) diff --git a/examples/components/process-backend/src/main/kotlin/io/holunda/camunda/taskpool/example/process/service/SystemInfoPrinter.kt b/examples/components/process-backend/src/main/kotlin/io/holunda/camunda/taskpool/example/process/service/SystemInfoPrinter.kt index 024408f74..56442fbf3 100644 --- a/examples/components/process-backend/src/main/kotlin/io/holunda/camunda/taskpool/example/process/service/SystemInfoPrinter.kt +++ b/examples/components/process-backend/src/main/kotlin/io/holunda/camunda/taskpool/example/process/service/SystemInfoPrinter.kt @@ -47,7 +47,7 @@ class SystemInfoPrinter( fun processInstancePrinter(): ApplicationRunner { return ApplicationRunner { val subscription = queryGateway.subscriptionQuery( - ProcessInstancesByStateQuery(setOf(ProcessInstanceState.RUNNING, ProcessInstanceState.FINISHED)), + ProcessInstancesByStateQuery(setOf(ProcessInstanceState.RUNNING, ProcessInstanceState.SUSPENDED, ProcessInstanceState.FINISHED)), QueryResponseMessageResponseType.queryResponseMessageResponseType(), QueryResponseMessageResponseType.queryResponseMessageResponseType() ) diff --git a/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceCommand.kt b/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceCommand.kt index 2eb45abbf..37169f70e 100644 --- a/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceCommand.kt +++ b/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceCommand.kt @@ -2,7 +2,6 @@ package io.holunda.camunda.taskpool.api.process.instance import io.holunda.camunda.taskpool.api.task.SourceReference import org.axonframework.modelling.command.TargetAggregateIdentifier -import org.axonframework.serialization.Revision /** * Command related to process instance. @@ -38,8 +37,24 @@ data class StartProcessInstanceCommand( /** * Informs about a process instance ended in the engine. */ -data class EndProcessInstanceCommand( +abstract class EndProcessInstanceCommand : ProcessInstanceCommand +data class FinishProcessInstanceCommand( + @TargetAggregateIdentifier + override val processInstanceId: String, + override val sourceReference: SourceReference, + + /** the business key of the process instance */ + val businessKey: String? = null, + + /** the id of the super case instance */ + val superInstanceId: String? = null, + + /** id of the activity which ended the process instance */ + val endActivityId: String?, +): EndProcessInstanceCommand() + +data class CancelProcessInstanceCommand( @TargetAggregateIdentifier override val processInstanceId: String, override val sourceReference: SourceReference, @@ -55,5 +70,27 @@ data class EndProcessInstanceCommand( /** the reason why this process instance was cancelled (deleted) */ val deleteReason: String? +): EndProcessInstanceCommand() -) : ProcessInstanceCommand +/** + * Informs about a process instance updated in the engine. + */ +abstract class UpdateProcessInstanceCommand : ProcessInstanceCommand + +/** + * Informs about a process instance suspended in the engine. + */ +data class SuspendProcessInstanceCommand( + @TargetAggregateIdentifier + override val processInstanceId: String, + override val sourceReference: SourceReference, +) : UpdateProcessInstanceCommand() + +/** + * Informs about a process instance resumed in the engine. + */ +data class ResumeProcessInstanceCommand( + @TargetAggregateIdentifier + override val processInstanceId: String, + override val sourceReference: SourceReference, +) : UpdateProcessInstanceCommand() diff --git a/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregate.kt b/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregate.kt index 3d2f07e79..f5d3e25b2 100644 --- a/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregate.kt +++ b/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregate.kt @@ -1,9 +1,6 @@ package io.holunda.camunda.taskpool.core.process -import io.holunda.camunda.taskpool.api.process.instance.EndProcessInstanceCommand -import io.holunda.camunda.taskpool.api.process.instance.ProcessInstanceEndedEvent -import io.holunda.camunda.taskpool.api.process.instance.StartProcessInstanceCommand -import io.holunda.camunda.taskpool.api.process.instance.ProcessInstanceStartedEvent +import io.holunda.camunda.taskpool.api.process.instance.* import org.axonframework.commandhandling.CommandHandler import org.axonframework.eventsourcing.EventSourcingHandler import org.axonframework.modelling.command.AggregateIdentifier @@ -29,17 +26,45 @@ class ProcessInstanceAggregate() { } @CommandHandler - fun end(cmd: EndProcessInstanceCommand) { + fun end(cmd: FinishProcessInstanceCommand) { AggregateLifecycle.apply(ProcessInstanceEndedEvent( processInstanceId = cmd.processInstanceId, sourceReference = cmd.sourceReference, businessKey = cmd.businessKey, endActivityId = cmd.endActivityId, - deleteReason = cmd.deleteReason, superInstanceId = cmd.superInstanceId )) } + @CommandHandler + fun cancel(cmd: CancelProcessInstanceCommand) { + AggregateLifecycle.apply(ProcessInstanceCancelledEvent( + processInstanceId = cmd.processInstanceId, + sourceReference = cmd.sourceReference, + businessKey = cmd.businessKey, + endActivityId = cmd.endActivityId, + superInstanceId = cmd.superInstanceId, + deleteReason = cmd.deleteReason + )) + } + + @CommandHandler + fun suspend(cmd: SuspendProcessInstanceCommand) { + AggregateLifecycle.apply(ProcessInstanceSuspendedEvent( + processInstanceId = cmd.processInstanceId, + sourceReference = cmd.sourceReference, + )) + } + + @CommandHandler + fun resume(cmd: ResumeProcessInstanceCommand) { + AggregateLifecycle.apply(ProcessInstanceResumedEvent( + processInstanceId = cmd.processInstanceId, + sourceReference = cmd.sourceReference, + )) + } + + @EventSourcingHandler fun on(event: ProcessInstanceStartedEvent) { this.processInstanceId = event.processInstanceId diff --git a/taskpool/taskpool-core/src/test/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregateTest.kt b/taskpool/taskpool-core/src/test/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregateTest.kt index e7cd3ba32..c15130319 100644 --- a/taskpool/taskpool-core/src/test/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregateTest.kt +++ b/taskpool/taskpool-core/src/test/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregateTest.kt @@ -1,16 +1,22 @@ package io.holunda.camunda.taskpool.core.process -import io.holunda.camunda.taskpool.api.process.instance.EndProcessInstanceCommand -import io.holunda.camunda.taskpool.api.process.instance.ProcessInstanceEndedEvent -import io.holunda.camunda.taskpool.api.process.instance.ProcessInstanceStartedEvent -import io.holunda.camunda.taskpool.api.process.instance.StartProcessInstanceCommand +import io.holunda.camunda.taskpool.api.process.instance.* import io.holunda.camunda.taskpool.api.task.ProcessReference import org.axonframework.test.aggregate.AggregateTestFixture import org.junit.Test class ProcessInstanceAggregateTest { - val fixture = AggregateTestFixture(ProcessInstanceAggregate::class.java) + private val fixture = AggregateTestFixture(ProcessInstanceAggregate::class.java) + private val sourceReference = ProcessReference( + "id:1", + "id:1", + "process-definition-key:67", + "process-definition-key", + "My Process", + "My application", + null + ) @Test @@ -18,15 +24,7 @@ class ProcessInstanceAggregateTest { val command = StartProcessInstanceCommand( "id:1", - ProcessReference( - "id:1", - "id:1", - "process-definition-key:67", - "process-definition-key", - "My Process", - "My application", - null - ), + sourceReference, "businessKey-4711", "kermit", null, @@ -46,21 +44,101 @@ class ProcessInstanceAggregateTest { )) } + @Test + fun `should react on instance suspend`() { + + val command = SuspendProcessInstanceCommand( + "id:1", + sourceReference, + ) + + fixture + .given( + ProcessInstanceStartedEvent( + "id:1", + sourceReference, + "businessKey-4711", + "kermit", + null, + "start_event" + ) + ) + .`when`(command) + .expectEvents(ProcessInstanceSuspendedEvent( + command.processInstanceId, + command.sourceReference, + )) + } + @Test - fun `should react on instance end`() { + fun `should react on instance resume`() { - val command = EndProcessInstanceCommand( + val command = ResumeProcessInstanceCommand( "id:1", - ProcessReference( - "id:1", - "id:1", - "process-definition-key:67", - "process-definition-key", - "My Process", - "My application", - null - ), + sourceReference + ) + + fixture + .given( + ProcessInstanceStartedEvent( + "id:1", + sourceReference, + "businessKey-4711", + "kermit", + null, + "start_event" + ), + ProcessInstanceResumedEvent( + command.processInstanceId, + command.sourceReference, + ) + ) + .`when`(command) + .expectEvents(ProcessInstanceResumedEvent( + command.processInstanceId, + command.sourceReference, + )) + } + + + @Test + fun `should react on instance finish`() { + + val command = FinishProcessInstanceCommand( + "id:1", + sourceReference, + "businessKey-4711", + "kermit", + "end_event" + ) + + fixture + .given( + ProcessInstanceStartedEvent( + "id:1", + sourceReference, + "businessKey-4711", + "kermit", + null, + "start_event" + ) + ) + .`when`(command) + .expectEvents(ProcessInstanceEndedEvent( + command.processInstanceId, + command.sourceReference, + command.businessKey, + command.superInstanceId, + command.endActivityId + )) + } + @Test + fun `should react on instance cancel`() { + + val command = CancelProcessInstanceCommand( + "id:1", + sourceReference, "businessKey-4711", "kermit", "end_event", @@ -71,15 +149,7 @@ class ProcessInstanceAggregateTest { .given( ProcessInstanceStartedEvent( "id:1", - ProcessReference( - "id:1", - "id:1", - "process-definition-key:67", - "process-definition-key", - "My Process", - "My application", - null - ), + sourceReference, "businessKey-4711", "kermit", null, @@ -87,7 +157,7 @@ class ProcessInstanceAggregateTest { ) ) .`when`(command) - .expectEvents(ProcessInstanceEndedEvent( + .expectEvents(ProcessInstanceCancelledEvent( command.processInstanceId, command.sourceReference, command.businessKey, diff --git a/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceEvents.kt b/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceEvents.kt index 1bcb31dc2..be8d5fc34 100644 --- a/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceEvents.kt +++ b/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceEvents.kt @@ -22,7 +22,7 @@ data class ProcessInstanceStartedEvent( val startActivityId: String? = null ) -@Revision("1") +@Revision("2") data class ProcessInstanceEndedEvent( val processInstanceId: String, val sourceReference: SourceReference, @@ -33,9 +33,38 @@ data class ProcessInstanceEndedEvent( /** the id of the super case instance */ val superInstanceId: String? = null, + /** id of the activity which ended the process instance */ + val endActivityId: String? +) + + +@Revision("1") +data class ProcessInstanceCancelledEvent( + val processInstanceId: String, + val sourceReference: SourceReference, + + /** the business key of the process instance */ + val businessKey: String? = null, + + /** the id of the super case instance */ + val superInstanceId: String? = null, + /** id of the activity which ended the process instance */ val endActivityId: String?, /** the reason why this process instance was cancelled (deleted) */ val deleteReason: String? ) + + +@Revision("1") +data class ProcessInstanceSuspendedEvent( + val processInstanceId: String, + val sourceReference: SourceReference, +) + +@Revision("1") +data class ProcessInstanceResumedEvent( + val processInstanceId: String, + val sourceReference: SourceReference, +) diff --git a/view/simple/src/main/kotlin/io/holunda/camunda/taskpool/view/simple/service/ProcessInstanceSimpleService.kt b/view/simple/src/main/kotlin/io/holunda/camunda/taskpool/view/simple/service/ProcessInstanceSimpleService.kt index 04d0f4769..9d3a6efb8 100644 --- a/view/simple/src/main/kotlin/io/holunda/camunda/taskpool/view/simple/service/ProcessInstanceSimpleService.kt +++ b/view/simple/src/main/kotlin/io/holunda/camunda/taskpool/view/simple/service/ProcessInstanceSimpleService.kt @@ -2,8 +2,7 @@ package io.holunda.camunda.taskpool.view.simple.service import io.holixon.axon.gateway.query.QueryResponseMessageResponseType import io.holixon.axon.gateway.query.RevisionValue -import io.holunda.camunda.taskpool.api.process.instance.ProcessInstanceEndedEvent -import io.holunda.camunda.taskpool.api.process.instance.ProcessInstanceStartedEvent +import io.holunda.camunda.taskpool.api.process.instance.* import io.holunda.camunda.taskpool.view.ProcessInstance import io.holunda.camunda.taskpool.view.ProcessInstanceState import io.holunda.camunda.taskpool.view.query.process.ProcessInstanceApi @@ -67,10 +66,49 @@ class ProcessInstanceSimpleService( updateProcessInstanceQuery(event.processInstanceId) } + /** + * Handles suspend of process instance. + */ + @EventHandler + fun on(event: ProcessInstanceSuspendedEvent, metaData: MetaData) { + val processInstance = processInstances[event.processInstanceId] + if (processInstance != null) { + processInstances[event.processInstanceId] = processInstance.copy(state = ProcessInstanceState.SUSPENDED) + revisionSupport.updateRevision(event.processInstanceId, RevisionValue.fromMetaData(metaData)) + logger.debug { "SIMPLE-VIEW-43: Process instance suspended $event." } + updateProcessInstanceQuery(event.processInstanceId) + } + } + + /** + * Handles resume of process instance. + */ + @EventHandler + fun on(event: ProcessInstanceResumedEvent, metaData: MetaData) { + val processInstance = processInstances[event.processInstanceId] + if (processInstance != null) { + processInstances[event.processInstanceId] = processInstance.copy(state = ProcessInstanceState.RUNNING) + revisionSupport.updateRevision(event.processInstanceId, RevisionValue.fromMetaData(metaData)) + logger.debug { "SIMPLE-VIEW-44: Process instance resumed $event." } + updateProcessInstanceQuery(event.processInstanceId) + } + } + + /** + * Handles cancel of process instance. + */ + @EventHandler + fun on(event: ProcessInstanceCancelledEvent, metaData: MetaData) { + processInstances[event.processInstanceId] = event.toProcessInstance(processInstances[event.processInstanceId]) + revisionSupport.updateRevision(event.processInstanceId, RevisionValue.fromMetaData(metaData)) + logger.debug { "SIMPLE-VIEW-45: Process instance was cancelled $event." } + updateProcessInstanceQuery(event.processInstanceId) + } + private fun updateProcessInstanceQuery(processInstanceId: String) { val revisionValue = revisionSupport.getRevisionMax(setOf(processInstanceId)) - logger.debug { "SIMPLE-VIEW-43: Updating query with new element $processInstanceId with revision $revisionValue" } + logger.debug { "SIMPLE-VIEW-49: Updating query with new element $processInstanceId with revision $revisionValue" } val processInstance = processInstances.getValue(processInstanceId) queryUpdateEmitter.emit( ProcessInstancesByStateQuery::class.java, @@ -102,6 +140,21 @@ fun ProcessInstanceStartedEvent.toProcessInstance(): ProcessInstance = ProcessIn * @param processInstance an old version of the view model. */ fun ProcessInstanceEndedEvent.toProcessInstance(processInstance: ProcessInstance?): ProcessInstance = ProcessInstance( + processInstanceId = this.processInstanceId, + sourceReference = this.sourceReference, + businessKey = this.businessKey, + superInstanceId = this.superInstanceId, + endActivityId = this.endActivityId, + startActivityId = processInstance?.startActivityId, + startUserId = processInstance?.startUserId, + state = ProcessInstanceState.FINISHED +) + +/** + * Converts event to view model. + * @param processInstance an old version of the view model. + */ +fun ProcessInstanceCancelledEvent.toProcessInstance(processInstance: ProcessInstance?): ProcessInstance = ProcessInstance( processInstanceId = this.processInstanceId, sourceReference = this.sourceReference, businessKey = this.businessKey, @@ -110,5 +163,5 @@ fun ProcessInstanceEndedEvent.toProcessInstance(processInstance: ProcessInstance deleteReason = this.deleteReason, startActivityId = processInstance?.startActivityId, startUserId = processInstance?.startUserId, - state = if (this.deleteReason == null) ProcessInstanceState.FINISHED else ProcessInstanceState.CANCELLED + state = ProcessInstanceState.CANCELLED ) From a071f402341f9f16f7a20694d0f3435ada4a0f49 Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Mon, 12 Oct 2020 15:13:53 +0200 Subject: [PATCH 04/16] docs: KDocs --- .../instance/ProcessInstanceCommand.kt | 6 ++++++ .../core/process/ProcessInstanceAggregate.kt | 19 ++++++++++++++++++- .../process/instance/ProcessInstanceEvents.kt | 17 +++++++++++++++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceCommand.kt b/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceCommand.kt index 37169f70e..e606d4dcf 100644 --- a/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceCommand.kt +++ b/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceCommand.kt @@ -39,6 +39,9 @@ data class StartProcessInstanceCommand( */ abstract class EndProcessInstanceCommand : ProcessInstanceCommand +/** + * Informs about a process instance finished in the engine. + */ data class FinishProcessInstanceCommand( @TargetAggregateIdentifier override val processInstanceId: String, @@ -54,6 +57,9 @@ data class FinishProcessInstanceCommand( val endActivityId: String?, ): EndProcessInstanceCommand() +/** + * Informs about a process instance cancelled by the user in the engine. + */ data class CancelProcessInstanceCommand( @TargetAggregateIdentifier override val processInstanceId: String, diff --git a/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregate.kt b/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregate.kt index f5d3e25b2..245ef3818 100644 --- a/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregate.kt +++ b/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/process/ProcessInstanceAggregate.kt @@ -13,6 +13,9 @@ class ProcessInstanceAggregate() { @AggregateIdentifier lateinit var processInstanceId: String + /** + * Create instance handler. + */ @CommandHandler constructor(cmd: StartProcessInstanceCommand): this() { AggregateLifecycle.apply(ProcessInstanceStartedEvent( @@ -25,6 +28,9 @@ class ProcessInstanceAggregate() { )) } + /** + * Finish instance handler. + */ @CommandHandler fun end(cmd: FinishProcessInstanceCommand) { AggregateLifecycle.apply(ProcessInstanceEndedEvent( @@ -36,6 +42,9 @@ class ProcessInstanceAggregate() { )) } + /** + * Cancel instance handler (by user). + */ @CommandHandler fun cancel(cmd: CancelProcessInstanceCommand) { AggregateLifecycle.apply(ProcessInstanceCancelledEvent( @@ -48,6 +57,9 @@ class ProcessInstanceAggregate() { )) } + /** + * Suspend instance handler (by user). + */ @CommandHandler fun suspend(cmd: SuspendProcessInstanceCommand) { AggregateLifecycle.apply(ProcessInstanceSuspendedEvent( @@ -56,6 +68,9 @@ class ProcessInstanceAggregate() { )) } + /** + * Resume instance handler (by user). + */ @CommandHandler fun resume(cmd: ResumeProcessInstanceCommand) { AggregateLifecycle.apply(ProcessInstanceResumedEvent( @@ -64,7 +79,9 @@ class ProcessInstanceAggregate() { )) } - + /** + * Set process instance id.. + */ @EventSourcingHandler fun on(event: ProcessInstanceStartedEvent) { this.processInstanceId = event.processInstanceId diff --git a/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceEvents.kt b/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceEvents.kt index be8d5fc34..573868fe3 100644 --- a/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceEvents.kt +++ b/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/api/process/instance/ProcessInstanceEvents.kt @@ -3,6 +3,9 @@ package io.holunda.camunda.taskpool.api.process.instance import io.holunda.camunda.taskpool.api.task.SourceReference import org.axonframework.serialization.Revision +/** + * Process instance has started. + */ @Revision("1") data class ProcessInstanceStartedEvent( @@ -22,6 +25,9 @@ data class ProcessInstanceStartedEvent( val startActivityId: String? = null ) +/** + * Process instance has ended. + */ @Revision("2") data class ProcessInstanceEndedEvent( val processInstanceId: String, @@ -37,7 +43,9 @@ data class ProcessInstanceEndedEvent( val endActivityId: String? ) - +/** + * Process instance has been cancelled. + */ @Revision("1") data class ProcessInstanceCancelledEvent( val processInstanceId: String, @@ -56,13 +64,18 @@ data class ProcessInstanceCancelledEvent( val deleteReason: String? ) - +/** + * Process instance has been suspended. + */ @Revision("1") data class ProcessInstanceSuspendedEvent( val processInstanceId: String, val sourceReference: SourceReference, ) +/** + * Process instance has been resumed. + */ @Revision("1") data class ProcessInstanceResumedEvent( val processInstanceId: String, From e36fd74289c1874160085e2d670e756d76690fdf Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Mon, 12 Oct 2020 15:44:40 +0200 Subject: [PATCH 05/16] provide boms, fix #280 --- bom/datapool-dependencies/pom.xml | 41 +++++++++++++++ bom/taskpool-dependencies/pom.xml | 84 +++++++++++++++++++++++++++++++ pom.xml | 2 + 3 files changed, 127 insertions(+) create mode 100644 bom/datapool-dependencies/pom.xml create mode 100644 bom/taskpool-dependencies/pom.xml diff --git a/bom/datapool-dependencies/pom.xml b/bom/datapool-dependencies/pom.xml new file mode 100644 index 000000000..b9c8838de --- /dev/null +++ b/bom/datapool-dependencies/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + camunda-bpm-taskpool + io.holunda.taskpool + 2.1.3-SNAPSHOT + ../../pom.xml + + + datapool-dependencies + pom + + + + + io.holunda.taskpool + camunda-bpm-datapool-api + ${project.version} + + + io.holunda.taskpool + camunda-bpm-datapool-collector + ${project.version} + + + io.holunda.taskpool + camunda-bpm-datapool-event + ${project.version} + + + io.holunda.taskpool + camunda-bpm-datapool-core + ${project.version} + + + + + diff --git a/bom/taskpool-dependencies/pom.xml b/bom/taskpool-dependencies/pom.xml new file mode 100644 index 000000000..6282298d4 --- /dev/null +++ b/bom/taskpool-dependencies/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + + camunda-bpm-taskpool + io.holunda.taskpool + 2.1.3-SNAPSHOT + ../../pom.xml + + + taskpool-dependencies + pom + + + + + io.holunda.taskpool + datapool-dependencies + ${project.version} + import + pom + + + io.holunda.taskpool + camunda-bpm-taskpool-api + ${project.version} + + + io.holunda.taskpool + camunda-bpm-taskpool-collector + 2.1.3-SNAPSHOT + + + io.holunda.taskpool + camunda-bpm-taskpool-event + ${project.version} + + + io.holunda.taskpool + camunda-bpm-taskpool-core + ${project.version} + + + io.holunda.taskpool + camunda-bpm-taskpool-engine-springboot-starter + ${project.version} + + + io.holunda.taskpool + camunda-bpm-taskpool-view-api + ${project.version} + + + io.holunda.taskpool + camunda-bpm-taskpool-view-simple + ${project.version} + + + io.holunda.taskpool + camunda-bpm-taskpool-view-mongo + ${project.version} + + + io.holunda.taskpool + camunda-bpm-taskpool-variable-serializer + ${project.version} + + + io.holunda.taskpool + camunda-bpm-engine-client + ${project.version} + + + io.holunda.taskpool + taskpool-property-taskurl-resolver + ${project.version} + + + + + + diff --git a/pom.xml b/pom.xml index 9cb15e360..de5cac9ab 100755 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,8 @@ taskpool datapool view + bom/taskpool-dependencies + bom/datapool-dependencies From ff6ce121bebfda122bae46335e2ea92d31a0cf7b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 12 Oct 2020 19:16:50 +0000 Subject: [PATCH 06/16] Bump junit from 4.12 to 4.13.1 Bumps [junit](https://github.com/junit-team/junit4) from 4.12 to 4.13.1. - [Release notes](https://github.com/junit-team/junit4/releases) - [Changelog](https://github.com/junit-team/junit4/blob/main/doc/ReleaseNotes4.12.md) - [Commits](https://github.com/junit-team/junit4/compare/r4.12...r4.13.1) Signed-off-by: dependabot[bot] --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100755 => 100644 pom.xml diff --git a/pom.xml b/pom.xml old mode 100755 new mode 100644 index de5cac9ab..2a386e5ba --- a/pom.xml +++ b/pom.xml @@ -251,7 +251,7 @@ junit junit - 4.12 + 4.13.1 test From b8d979eb3bf1dbc083ae9f029daf65df13b8d53a Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Mon, 12 Oct 2020 21:20:19 +0200 Subject: [PATCH 07/16] chnage property names, implement prop test, fix #286, fix #285 --- .../components/engine-taskpool-collector.ad | 2 +- .../src/main/kotlin/task/TaskEventHandlers.kt | 2 +- .../test/kotlin/task/TaskEventHandlerTest.kt | 4 +- .../FallbackTaskCollectorConfiguration.kt | 2 +- .../taskpool/TaskCollectorConfiguration.kt | 59 +++++--- .../ProcessDefinitionEnginePlugin.kt | 4 +- .../definition/ProcessDefinitionService.kt | 4 +- .../ProcessInstanceEventCollectorService.kt | 105 ++++++------- .../task/TaskEventCollectorService.kt | 2 +- .../ProcessVariableEventCollectorService.kt | 85 +++++++++++ .../enricher/EmptyTaskCommandEnricher.kt | 2 +- ....kt => ProcessInstanceProcessorService.kt} | 0 .../enricher/TaskCommandEnricherService.kt | 24 ++- ...ndSender.kt => EngineTaskCommandSender.kt} | 4 +- ...wareAccumulatingEngineTaskCommandSender.kt | 22 +-- .../sender/accumulator/CommandAccumulator.kt | 2 +- .../accumulator/DirectCommandAccumulator.kt | 2 +- .../InvertingCommandAccumulator.kt | 2 +- .../ProjectingCommandAccumulator.kt | 18 +-- .../accumulator/SortingCommandAccumulator.kt | 2 +- .../sender/gateway/AxonCommandListGateway.kt | 8 +- .../TaskCollectorPropertiesExtendedTest.kt | 142 ++++++++++++++++++ .../TaskCollectorPropertiesITest.kt | 2 +- ...ication.kt => CollectorTestApplication.kt} | 2 +- .../itest/ProcessDefinitionServiceITest.kt | 2 +- .../taskpool/itest/TaskCollectorITest.kt | 2 +- .../sender/AxonCommandListGatewayTest.kt | 14 +- .../resources/application-collector-itest.yml | 7 +- .../application-properties-itest.yml | 17 +-- .../process/rest/EnvironmentController.kt | 2 +- .../src/main/resources/application.yml | 17 ++- .../src/main/resources/application.yml | 22 ++- .../taskpool/TaskCollectorProperties.kt | 76 +++++++--- 33 files changed, 465 insertions(+), 195 deletions(-) create mode 100644 engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/variable/ProcessVariableEventCollectorService.kt rename engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/{ProcessInstanceEnricherService.kt => ProcessInstanceProcessorService.kt} (100%) rename engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/{CommandSender.kt => EngineTaskCommandSender.kt} (73%) create mode 100644 engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/collector/properties/TaskCollectorPropertiesExtendedTest.kt rename engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/{TaskCollectorTestApplication.kt => CollectorTestApplication.kt} (90%) diff --git a/docs/src/orchid/resources/wiki/user-guide/components/engine-taskpool-collector.ad b/docs/src/orchid/resources/wiki/user-guide/components/engine-taskpool-collector.ad index e588b524a..1444973f9 100644 --- a/docs/src/orchid/resources/wiki/user-guide/components/engine-taskpool-collector.ad +++ b/docs/src/orchid/resources/wiki/user-guide/components/engine-taskpool-collector.ad @@ -259,7 +259,7 @@ The default provided command sender (type: `tx`) is collects all task commands d and accumulates by creating one command reflecting the intent of the task operation. It uses Axon Command Bus (encapsulated by the `AxonCommandListGateway`. -TIP: If you want to implement a custom command sending, please provide your own implementation of the interface `CommandSender` +TIP: If you want to implement a custom command sending, please provide your own implementation of the interface `EngineTaskCommandSender` (register a Spring Component of the type) and set the property `camunda.taskpool.collector.sender.type` to `custom`. The Spring event listeners receiving events from the Camunda Engine plugin are called before the engine commits the transaction. diff --git a/engine/camunda-engine-client/src/main/kotlin/task/TaskEventHandlers.kt b/engine/camunda-engine-client/src/main/kotlin/task/TaskEventHandlers.kt index f1d78c638..a748d017d 100644 --- a/engine/camunda-engine-client/src/main/kotlin/task/TaskEventHandlers.kt +++ b/engine/camunda-engine-client/src/main/kotlin/task/TaskEventHandlers.kt @@ -132,5 +132,5 @@ class TaskEventHandlers( } - private fun isAddressedToMe(event: TaskIdentity) = taskCollectorProperties.enricher.applicationName == event.sourceReference.applicationName + private fun isAddressedToMe(event: TaskIdentity) = taskCollectorProperties.applicationName == event.sourceReference.applicationName } diff --git a/engine/camunda-engine-client/src/test/kotlin/task/TaskEventHandlerTest.kt b/engine/camunda-engine-client/src/test/kotlin/task/TaskEventHandlerTest.kt index b22fcfe30..3405fb099 100644 --- a/engine/camunda-engine-client/src/test/kotlin/task/TaskEventHandlerTest.kt +++ b/engine/camunda-engine-client/src/test/kotlin/task/TaskEventHandlerTest.kt @@ -21,11 +21,11 @@ class TaskEventHandlerTest { @get: Rule val mockitoRule: MockitoRule = MockitoJUnit.rule() - private val taskCollectorProperties = TaskCollectorProperties("myApplication") + private val taskCollectorProperties = TaskCollectorProperties(applicationName = "myApplication") private val processReference = ProcessReference( instanceId = UUID.randomUUID().toString(), name = "My Process", - applicationName = taskCollectorProperties.enricher.applicationName, + applicationName = taskCollectorProperties.applicationName, definitionId = "PROCESS:001", definitionKey = "PROCESS", executionId = UUID.randomUUID().toString() diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/FallbackTaskCollectorConfiguration.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/FallbackTaskCollectorConfiguration.kt index 63d46fc89..e38c93c4c 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/FallbackTaskCollectorConfiguration.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/FallbackTaskCollectorConfiguration.kt @@ -29,7 +29,7 @@ open class FallbackProcessVariablesFilterConfiguration { @ConditionalOnMissingBean(ProcessVariablesCorrelator::class) open class FallbackProcessVariablesCorrelatorConfiguration { /** - * Empty correlator. + * Empty corellator. */ @Bean open fun processVariablesCorrelatorFallback(): ProcessVariablesCorrelator = ProcessVariablesCorrelator() diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/TaskCollectorConfiguration.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/TaskCollectorConfiguration.kt index cfe02ed82..b1feb0572 100755 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/TaskCollectorConfiguration.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/TaskCollectorConfiguration.kt @@ -3,9 +3,9 @@ package io.holunda.camunda.taskpool import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import io.holunda.camunda.taskpool.enricher.* -import io.holunda.camunda.taskpool.sender.CommandSender +import io.holunda.camunda.taskpool.sender.EngineTaskCommandSender import io.holunda.camunda.taskpool.sender.TxAwareAccumulatingEngineTaskCommandSender -import io.holunda.camunda.taskpool.sender.accumulator.CommandAccumulator +import io.holunda.camunda.taskpool.sender.accumulator.EngineTaskCommandAccumulator import io.holunda.camunda.taskpool.sender.accumulator.ProjectingCommandAccumulator import io.holunda.camunda.taskpool.sender.gateway.* import org.camunda.bpm.engine.RuntimeService @@ -43,30 +43,30 @@ class TaskCollectorConfiguration( * Create accumulator. */ @Bean - fun commandAccumulator(objectMapper: ObjectMapper): CommandAccumulator = ProjectingCommandAccumulator(objectMapper = objectMapper) + fun commandAccumulator(objectMapper: ObjectMapper): EngineTaskCommandAccumulator = ProjectingCommandAccumulator(objectMapper = objectMapper) /** * Create enricher. */ @Bean - @ConditionalOnExpression("'\${camunda.taskpool.collector.enricher.type}' != 'custom'") + @ConditionalOnExpression("'\${camunda.taskpool.collector.task.enricher.type}' != 'custom'") fun processVariablesEnricher(runtimeService: RuntimeService, filter: ProcessVariablesFilter, correlator: ProcessVariablesCorrelator): VariablesEnricher = - when (properties.enricher.type) { + when (properties.task.enricher.type) { TaskCollectorEnricherType.processVariables -> ProcessVariablesTaskCommandEnricher(runtimeService, filter, correlator) TaskCollectorEnricherType.no -> EmptyTaskCommandEnricher() - else -> throw IllegalStateException("Could not initialize enricher, used ${properties.enricher.type} type.") + else -> throw IllegalStateException("Could not initialize task enricher, used unknown ${properties.task.enricher.type} type.") } /** * Create command sender. */ @Bean - @ConditionalOnExpression("'\${camunda.taskpool.collector.sender.type}' != 'custom'") - fun txCommandSender(commandListGateway: CommandListGateway, accumulator: CommandAccumulator): CommandSender = - when (properties.sender.type) { - TaskSenderType.tx -> TxAwareAccumulatingEngineTaskCommandSender(commandListGateway, accumulator, properties.sender.sendWithinTransaction) - else -> throw IllegalStateException("Could not initialize sender, used ${properties.sender.type} type.") + @ConditionalOnExpression("'\${camunda.taskpool.collector.task.sender.type}' != 'custom'") + fun txCommandSender(commandListGateway: CommandListGateway, accumulator: EngineTaskCommandAccumulator): EngineTaskCommandSender = + when (properties.task.sender.type) { + TaskSenderType.tx -> TxAwareAccumulatingEngineTaskCommandSender(commandListGateway, accumulator, properties.task.sender.sendWithinTransaction) + else -> throw IllegalStateException("Could not initialize sender, used unknown ${properties.task.sender.type} type.") } /** @@ -74,35 +74,48 @@ class TaskCollectorConfiguration( */ @PostConstruct fun printSenderConfiguration() { - if (properties.sender.enabled) { - logger.info("SENDER-001: Camunda Taskpool commands will be distributed over command bus.") + + if (properties.sendCommandsEnabled) { + logger.info("SENDER-001: Taskpool commands will be distributed over command bus.") } else { - logger.info("SENDER-002: Camunda Taskpool command distribution is disabled by property.") + logger.info("SENDER-002: Taskpool command distribution is disabled by property.") } } + /** - * Prints enricher config. + * Prints sender config. */ @PostConstruct - fun printEnricherConfiguration() { - when (properties.enricher.type) { - TaskCollectorEnricherType.processVariables -> logger.info("ENRICHER-001: Camunda Taskpool commands will be enriched with process variables.") - TaskCollectorEnricherType.no -> logger.info("ENRICHER-002: Camunda Taskpool commands will not be enriched.") - else -> logger.info("ENRICHER-003: Camunda Taskpool commands will not be enriched by a custom enricher.") + fun printTaskEnricherConfiguration() { + require(properties.enricher == null) { + "'camunda.taskpool.collector.enricher' property has been deprecated, please use 'camunda.taskpool.collector.task.enricher' instead." + } + + if (properties.task.enabled) { + logger.info ("COLLECTOR-001: Task commands will be collected.") + when (properties.task.enricher.type) { + TaskCollectorEnricherType.processVariables -> logger.info("ENRICHER-001: Task commands will be enriched with process variables.") + TaskCollectorEnricherType.no -> logger.info("ENRICHER-002: Task commands will not be enriched.") + else -> logger.info("ENRICHER-003: Task commands will be enriched by a custom enricher.") + } + } else { + logger.info ("COLLECTOR-002: Task commands not be collected.") } } - /** + + /** * Default logging handler. */ @Bean - fun loggingTaskCommandSuccessHandler(): CommandSuccessHandler = LoggingTaskCommandSuccessHandler(LoggerFactory.getLogger(CommandSender::class.java)) + fun loggingTaskCommandSuccessHandler(): CommandSuccessHandler = LoggingTaskCommandSuccessHandler(LoggerFactory.getLogger(EngineTaskCommandSender::class.java)) /** * Default logging handler. */ @Bean - fun loggingTaskCommandErrorHandler(): CommandErrorHandler = LoggingTaskCommandErrorHandler(LoggerFactory.getLogger(CommandSender::class.java)) + fun loggingTaskCommandErrorHandler(): CommandErrorHandler = LoggingTaskCommandErrorHandler(LoggerFactory.getLogger(EngineTaskCommandSender::class.java)) + } diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/definition/ProcessDefinitionEnginePlugin.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/definition/ProcessDefinitionEnginePlugin.kt index 018fbe6ce..400c87f16 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/definition/ProcessDefinitionEnginePlugin.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/definition/ProcessDefinitionEnginePlugin.kt @@ -16,12 +16,12 @@ class ProcessDefinitionEnginePlugin( override fun preInit(springConfiguration: SpringProcessEngineConfiguration) { if (properties.processDefinition.enabled) { - logger.info("EVENTING-010: Process definition registration plugin registered.") + logger.info("EVENTING-010: Process definition registration plugin activated.") springConfiguration.customPostBPMNParseListeners.add( RegisterProcessDefinitionParseListener(springConfiguration) ) } else { - logger.info("EVENTING-011: Process definition disabled by property.") + logger.info("EVENTING-011: Process definition registration disabled by property.") } } } diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/definition/ProcessDefinitionService.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/definition/ProcessDefinitionService.kt index 34f3c97cf..663c84529 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/definition/ProcessDefinitionService.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/definition/ProcessDefinitionService.kt @@ -19,7 +19,7 @@ import org.springframework.stereotype.Component */ @Component class ProcessDefinitionService( - private val properties: TaskCollectorProperties + private val collectorProperties: TaskCollectorProperties ) { private val processDefinitions: MutableSet = mutableSetOf() @@ -55,7 +55,7 @@ class ProcessDefinitionService( } this.processDefinitions.addAll(newDefinitions) - return newDefinitions.map { it.asCommand(applicationName = properties.enricher.applicationName, formKey = formService.getStartFormKey(it.id)) } + return newDefinitions.map { it.asCommand(applicationName = collectorProperties.applicationName, formKey = formService.getStartFormKey(it.id)) } } /** diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/instance/ProcessInstanceEventCollectorService.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/instance/ProcessInstanceEventCollectorService.kt index f7e9450c5..dbd814eba 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/instance/ProcessInstanceEventCollectorService.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/process/instance/ProcessInstanceEventCollectorService.kt @@ -33,8 +33,19 @@ class ProcessInstanceEventCollectorService( */ @Order(ORDER) @EventListener(condition = "#processInstance.eventType.equals('start')") - fun create(processInstance: HistoricProcessInstanceEventEntity): StartProcessInstanceCommand = processInstance - .toStartProcessInstanceCommand(repositoryService, collectorProperties.enricher.applicationName) + fun create(processInstance: HistoricProcessInstanceEventEntity): StartProcessInstanceCommand = + StartProcessInstanceCommand( + sourceReference = processInstance.sourceReference(repositoryService, collectorProperties.applicationName), + processInstanceId = processInstance.processInstanceId, + businessKey = processInstance.businessKey, + startActivityId = processInstance.startActivityId, + startUserId = processInstance.startUserId, + superInstanceId = when { + processInstance.superProcessInstanceId != null -> processInstance.superProcessInstanceId + processInstance.superCaseInstanceId != null -> processInstance.superCaseInstanceId + else -> null + } + ) /** * Fires update process instance command. @@ -44,9 +55,17 @@ class ProcessInstanceEventCollectorService( @EventListener(condition = "#processInstance.eventType.equals('update')") fun update(processInstance: HistoricProcessInstanceEventEntity): UpdateProcessInstanceCommand? = when (processInstance.state) { // suspend - HistoricProcessInstance.STATE_SUSPENDED -> processInstance.toSuspendProcessInstanceCommand(repositoryService, collectorProperties.enricher.applicationName) + HistoricProcessInstance.STATE_SUSPENDED -> + SuspendProcessInstanceCommand( + sourceReference = processInstance.sourceReference(repositoryService, collectorProperties.applicationName), + processInstanceId = processInstance.processInstanceId, + ) // resume - HistoricProcessInstance.STATE_ACTIVE -> processInstance.toResumeProcessInstanceCommand(repositoryService, collectorProperties.enricher.applicationName) + HistoricProcessInstance.STATE_ACTIVE -> + ResumeProcessInstanceCommand( + sourceReference = processInstance.sourceReference(repositoryService, collectorProperties.applicationName), + processInstanceId = processInstance.processInstanceId, + ) else -> { logger.debug { "Unknown update process instance event received $processInstance" } null @@ -62,63 +81,35 @@ class ProcessInstanceEventCollectorService( @EventListener(condition = "#processInstance.eventType.equals('end')") fun end(processInstance: HistoricProcessInstanceEventEntity): EndProcessInstanceCommand? = when (processInstance.state) { // cancel - HistoricProcessInstance.STATE_EXTERNALLY_TERMINATED -> processInstance.toCancelProcessInstanceCommand(repositoryService, collectorProperties.enricher.applicationName) + HistoricProcessInstance.STATE_EXTERNALLY_TERMINATED -> + CancelProcessInstanceCommand( + sourceReference = processInstance.sourceReference(repositoryService, collectorProperties.applicationName), + processInstanceId = processInstance.processInstanceId, + businessKey = processInstance.businessKey, + endActivityId = processInstance.endActivityId, + superInstanceId = when { + processInstance.superProcessInstanceId != null -> processInstance.superProcessInstanceId + processInstance.superCaseInstanceId != null -> processInstance.superCaseInstanceId + else -> null + }, + deleteReason = processInstance.deleteReason + ) // finish - HistoricProcessInstance.STATE_INTERNALLY_TERMINATED -> processInstance.toFinishProcessInstanceCommand(repositoryService, collectorProperties.enricher.applicationName) + HistoricProcessInstance.STATE_INTERNALLY_TERMINATED -> + FinishProcessInstanceCommand( + sourceReference = processInstance.sourceReference(repositoryService, collectorProperties.applicationName), + processInstanceId = processInstance.processInstanceId, + businessKey = processInstance.businessKey, + endActivityId = processInstance.endActivityId, + superInstanceId = when { + processInstance.superProcessInstanceId != null -> processInstance.superProcessInstanceId + processInstance.superCaseInstanceId != null -> processInstance.superCaseInstanceId + else -> null + } + ) else -> { logger.debug { "Unknown end process instance event received $processInstance" } null } } - } - -private fun HistoricProcessInstanceEventEntity.toStartProcessInstanceCommand(repositoryService: RepositoryService, applicationName: String) = StartProcessInstanceCommand( - sourceReference = this.sourceReference(repositoryService, applicationName), - processInstanceId = this.processInstanceId, - businessKey = this.businessKey, - startActivityId = this.startActivityId, - startUserId = this.startUserId, - superInstanceId = when { - this.superProcessInstanceId != null -> this.superProcessInstanceId - this.superCaseInstanceId != null -> this.superCaseInstanceId - else -> null - } -) - -private fun HistoricProcessInstanceEventEntity.toFinishProcessInstanceCommand(repositoryService: RepositoryService, applicationName: String) = FinishProcessInstanceCommand( - sourceReference = this.sourceReference(repositoryService, applicationName), - processInstanceId = this.processInstanceId, - businessKey = this.businessKey, - endActivityId = this.endActivityId, - superInstanceId = when { - this.superProcessInstanceId != null -> this.superProcessInstanceId - this.superCaseInstanceId != null -> this.superCaseInstanceId - else -> null - } -) - -private fun HistoricProcessInstanceEventEntity.toCancelProcessInstanceCommand(repositoryService: RepositoryService, applicationName: String) = CancelProcessInstanceCommand( - sourceReference = this.sourceReference(repositoryService, applicationName), - processInstanceId = this.processInstanceId, - businessKey = this.businessKey, - endActivityId = this.endActivityId, - superInstanceId = when { - this.superProcessInstanceId != null -> this.superProcessInstanceId - this.superCaseInstanceId != null -> this.superCaseInstanceId - else -> null - }, - deleteReason = this.deleteReason -) - - -private fun HistoricProcessInstanceEventEntity.toSuspendProcessInstanceCommand(repositoryService: RepositoryService, applicationName: String) = SuspendProcessInstanceCommand( - sourceReference = this.sourceReference(repositoryService, applicationName), - processInstanceId = this.processInstanceId, -) - - -private fun HistoricProcessInstanceEventEntity.toResumeProcessInstanceCommand(repositoryService: RepositoryService, applicationName: String) = ResumeProcessInstanceCommand( - sourceReference = this.sourceReference(repositoryService, applicationName), - processInstanceId = this.processInstanceId, -) diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/task/TaskEventCollectorService.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/task/TaskEventCollectorService.kt index 964684195..478c36f19 100755 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/task/TaskEventCollectorService.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/task/TaskEventCollectorService.kt @@ -49,7 +49,7 @@ class TaskEventCollectorService( formKey = task.formKey(), taskDefinitionKey = task.taskDefinitionKey, businessKey = task.execution.businessKey, - sourceReference = task.sourceReference(collectorProperties.enricher.applicationName) + sourceReference = task.sourceReference(collectorProperties.applicationName) ) /** diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/variable/ProcessVariableEventCollectorService.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/variable/ProcessVariableEventCollectorService.kt new file mode 100644 index 000000000..ca03609e4 --- /dev/null +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/variable/ProcessVariableEventCollectorService.kt @@ -0,0 +1,85 @@ +package io.holunda.camunda.taskpool.collector.variable + +import io.holunda.camunda.taskpool.TaskCollectorProperties +import mu.KLogging +import org.camunda.bpm.engine.RepositoryService +import org.camunda.bpm.engine.impl.history.event.HistoricVariableUpdateEventEntity +import org.camunda.bpm.engine.impl.history.event.HistoryEventTypes +import org.camunda.bpm.engine.impl.persistence.entity.HistoricDetailVariableInstanceUpdateEntity +import org.springframework.context.event.EventListener +import org.springframework.core.annotation.Order +import org.springframework.stereotype.Component + +/** + * + * + * + * VARIABLE_INSTANCE_CREATE("variable-instance", "create"), + * VARIABLE_INSTANCE_UPDATE("variable-instance", "update"), + * VARIABLE_INSTANCE_MIGRATE("variable-instance", "migrate"), + * VARIABLE_INSTANCE_UPDATE_DETAIL("variable-instance", "update-detail"), + * VARIABLE_INSTANCE_DELETE("variable-instance", "delete"), + * + */ +@Component +class ProcessVariableEventCollectorService( + private val collectorProperties: TaskCollectorProperties, + private val repositoryService: RepositoryService +) { + + companion object : KLogging() { + // high order to be later than all other listeners and work on changed entity + const val ORDER = Integer.MAX_VALUE - 100 + } + + /** + * Fires create process variable command. + * See [HistoryEventTypes.VARIABLE_INSTANCE_CREATE] + */ + @Order(ORDER) + @EventListener(condition = "#variableEvent.eventType.equals('create')") + fun create(variableEvent: HistoricVariableUpdateEventEntity) { + logger.debug { "Created variable $variableEvent" } + } + + /** + * Fires update detail process variable command. + * See [HistoryEventTypes.VARIABLE_INSTANCE_UPDATE] + */ + @Order(ORDER) + @EventListener(condition = "#variableEvent.eventType.equals('update-detail')") + fun updateDetail(variableEvent: HistoricDetailVariableInstanceUpdateEntity) { + logger.debug { "Created variable $variableEvent" } + } + + /** + * Fires delete process variable command. + * See [HistoryEventTypes.VARIABLE_INSTANCE_DELETE] + */ + @Order(ORDER) + @EventListener(condition = "#variableEvent.eventType.equals('delete')") + fun delete(variableEvent: HistoricVariableUpdateEventEntity) { + logger.debug { "Created variable $variableEvent" } + } + + /** + * Fires update process variable command. + * See [HistoryEventTypes.VARIABLE_INSTANCE_UPDATE] + */ + @Order(ORDER) + @EventListener(condition = "#variableEvent.eventType.equals('update')") + fun update(variableEvent: HistoricVariableUpdateEventEntity) { + logger.debug { "Update variable $variableEvent" } + } + + /** + * Fires migrate process variable command. + * See [HistoryEventTypes.VARIABLE_INSTANCE_MIGRATE] + */ + @Order(ORDER) + @EventListener(condition = "#variableEvent.eventType.equals('migrate')") + fun migrate(variableEvent: HistoricVariableUpdateEventEntity) { + logger.debug { "Update variable $variableEvent" } + } + +} diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/EmptyTaskCommandEnricher.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/EmptyTaskCommandEnricher.kt index 0a5528ebf..17cbadb2d 100755 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/EmptyTaskCommandEnricher.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/EmptyTaskCommandEnricher.kt @@ -4,7 +4,7 @@ import io.holunda.camunda.taskpool.api.task.TaskIdentityWithPayloadAndCorrelatio /** - * Empty implementation without eny enrichment. Used for compliance of the commands. + * Empty implementation without any enrichment. Used for compliance of the commands. */ class EmptyTaskCommandEnricher : VariablesEnricher { override fun enrich(command: T): T = command.apply { enriched = true } diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/ProcessInstanceEnricherService.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/ProcessInstanceProcessorService.kt similarity index 100% rename from engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/ProcessInstanceEnricherService.kt rename to engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/ProcessInstanceProcessorService.kt diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/TaskCommandEnricherService.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/TaskCommandEnricherService.kt index a0b9213c5..d10ef70e6 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/TaskCommandEnricherService.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/enricher/TaskCommandEnricherService.kt @@ -1,25 +1,37 @@ package io.holunda.camunda.taskpool.enricher +import io.holunda.camunda.taskpool.TaskCollectorProperties import io.holunda.camunda.taskpool.api.task.EngineTaskCommand import io.holunda.camunda.taskpool.api.task.TaskIdentityWithPayloadAndCorrelations -import io.holunda.camunda.taskpool.sender.CommandSender +import io.holunda.camunda.taskpool.sender.EngineTaskCommandSender +import mu.KLogging +import org.slf4j.Logger +import org.slf4j.LoggerFactory import org.springframework.context.event.EventListener import org.springframework.stereotype.Component /** * Default enricher. + * This component is a sink of all engine task commands collected by the [TaskEventCollectorService] + * and will enrich all commands which are implementing [TaskIdentityWithPayloadAndCorrelations] interface + * and pass it over to sender, responsible for accumulation (reducing the amount of commands) and sending. */ @Component class TaskCommandEnricherService( - private val commandSender: CommandSender, - private val enricher: VariablesEnricher + private val engineTaskCommandSender: EngineTaskCommandSender, + private val enricher: VariablesEnricher, + private val collectorProperties: TaskCollectorProperties ) { - + private val logger: Logger = LoggerFactory.getLogger(TaskCommandEnricherService::class.java) @EventListener fun send(command: EngineTaskCommand) { - // enrich before collect - commandSender.send(enrich(command)) + if (collectorProperties.task.enabled) { + // enrich and send + engineTaskCommandSender.send(enrich(command)) + } else { + logger.debug("Task command collecting is disabled by property, would have enriched and sent command $command.") + } } /** diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/CommandSender.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/EngineTaskCommandSender.kt similarity index 73% rename from engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/CommandSender.kt rename to engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/EngineTaskCommandSender.kt index 446fd37c6..f7719326a 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/CommandSender.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/EngineTaskCommandSender.kt @@ -3,9 +3,9 @@ package io.holunda.camunda.taskpool.sender import io.holunda.camunda.taskpool.api.task.EngineTaskCommand /** - * Interface for beans sending commands. + * Interface for beans sending task commands. */ -interface CommandSender { +interface EngineTaskCommandSender { /** * Sends the command to core and enriches it, if possible. */ diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/TxAwareAccumulatingEngineTaskCommandSender.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/TxAwareAccumulatingEngineTaskCommandSender.kt index d374df896..b2f512a64 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/TxAwareAccumulatingEngineTaskCommandSender.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/TxAwareAccumulatingEngineTaskCommandSender.kt @@ -1,7 +1,7 @@ package io.holunda.camunda.taskpool.sender import io.holunda.camunda.taskpool.api.task.EngineTaskCommand -import io.holunda.camunda.taskpool.sender.accumulator.CommandAccumulator +import io.holunda.camunda.taskpool.sender.accumulator.EngineTaskCommandAccumulator import io.holunda.camunda.taskpool.sender.gateway.CommandListGateway import org.slf4j.Logger import org.slf4j.LoggerFactory @@ -13,22 +13,22 @@ import org.springframework.transaction.support.TransactionSynchronizationManager */ open class TxAwareAccumulatingEngineTaskCommandSender( private val commandListGateway: CommandListGateway, - private val commandAccumulator: CommandAccumulator, + private val engineTaskCommandAccumulator: EngineTaskCommandAccumulator, private val sendTasksWithinTransaction: Boolean -) : CommandSender { - private val logger: Logger = LoggerFactory.getLogger(CommandSender::class.java) +) : EngineTaskCommandSender { + private val logger: Logger = LoggerFactory.getLogger(EngineTaskCommandSender::class.java) private val registered: ThreadLocal = ThreadLocal.withInitial { false } @Suppress("RemoveExplicitTypeArguments") - private val commands: ThreadLocal>> = ThreadLocal.withInitial { mutableMapOf>() } + private val taskCommands: ThreadLocal>> = ThreadLocal.withInitial { mutableMapOf>() } /** - * Sends an engine command.send + * Sends an engine task command (after commit). */ override fun send(command: EngineTaskCommand) { // add command to list - commands.get().getOrPut(command.id) { mutableListOf() }.add(command) + taskCommands.get().getOrPut(command.id) { mutableListOf() }.add(command) // register synchronization only once if (!registered.get()) { @@ -58,7 +58,7 @@ open class TxAwareAccumulatingEngineTaskCommandSender( * Clean-up the thread on completion. */ override fun afterCompletion(status: Int) { - commands.remove() + taskCommands.remove() registered.remove() } }) @@ -70,11 +70,11 @@ open class TxAwareAccumulatingEngineTaskCommandSender( private fun send() { // iterate over messages and send them - commands.get().forEach { (taskId: String, taskCommands: MutableList) -> - val accumulatorName = commandAccumulator::class.simpleName + taskCommands.get().forEach { (taskId: String, taskCommands: MutableList) -> + val accumulatorName = engineTaskCommandAccumulator::class.simpleName logger.debug("SENDER-005: Handling ${taskCommands.size} commands for task $taskId using command accumulator $accumulatorName") - val commands = commandAccumulator.invoke(taskCommands) + val commands = engineTaskCommandAccumulator.invoke(taskCommands) // handle messages for every task commandListGateway.sendToGateway(commands) diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/CommandAccumulator.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/CommandAccumulator.kt index ebf143978..6576171b4 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/CommandAccumulator.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/CommandAccumulator.kt @@ -6,4 +6,4 @@ import io.holunda.camunda.taskpool.api.task.EngineTaskCommand * Accumulator is responsible for transforming (and evtl. reducing) the number of commands being sent, * by accumulating information from several commands into one. */ -typealias CommandAccumulator = (List) -> List +typealias EngineTaskCommandAccumulator = (List) -> List diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/DirectCommandAccumulator.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/DirectCommandAccumulator.kt index f03e08236..85fcf0da2 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/DirectCommandAccumulator.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/DirectCommandAccumulator.kt @@ -5,6 +5,6 @@ import io.holunda.camunda.taskpool.api.task.EngineTaskCommand /** * Just passing the commands straight through. */ -class DirectCommandAccumulator : CommandAccumulator { +class DirectCommandAccumulator : EngineTaskCommandAccumulator { override fun invoke(taskCommands: List) = taskCommands } diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/InvertingCommandAccumulator.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/InvertingCommandAccumulator.kt index 4a70b5c84..1f5a7ef65 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/InvertingCommandAccumulator.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/InvertingCommandAccumulator.kt @@ -5,6 +5,6 @@ import io.holunda.camunda.taskpool.api.task.EngineTaskCommand /** * invert the order of commands, because Camunda sends them in reversed order. */ -class InvertingCommandAccumulator : CommandAccumulator { +class InvertingCommandAccumulator : EngineTaskCommandAccumulator { override fun invoke(taskCommands: List) = taskCommands.reversed() } diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/ProjectingCommandAccumulator.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/ProjectingCommandAccumulator.kt index b1188a560..cda5deb10 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/ProjectingCommandAccumulator.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/ProjectingCommandAccumulator.kt @@ -1,7 +1,6 @@ package io.holunda.camunda.taskpool.sender.accumulator import com.fasterxml.jackson.databind.ObjectMapper -import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper import io.holunda.camunda.taskpool.api.business.WithCorrelations import io.holunda.camunda.taskpool.api.task.* import io.holunda.camunda.variable.serializer.serialize @@ -13,10 +12,10 @@ import kotlin.reflect.KClass * @param objectMapper optional object mapper used for serialization, defaults to jacksonObjectMapper with Kotlin module. */ class ProjectingCommandAccumulator( - val objectMapper: ObjectMapper = jacksonObjectMapper() -) : CommandAccumulator { + val objectMapper: ObjectMapper +) : EngineTaskCommandAccumulator { - private val sorter: CommandAccumulator = SortingCommandAccumulator() + private val sorter: EngineTaskCommandAccumulator = SortingCommandAccumulator() override fun invoke(taskCommands: List): List = if (taskCommands.size > 1) { @@ -30,7 +29,7 @@ class ProjectingCommandAccumulator( @Suppress("UNCHECKED_CAST") - private fun collectCommandProperties(command: T, details: List): T = projectProperties( + private fun collectCommandProperties(command: T, details: List): T = projectProperties( original = command, details = details, /** @@ -75,14 +74,14 @@ class ProjectingCommandAccumulator( WithPayload::payload.name, WithCorrelations::correlations.name ), - projectionErrorDetector = EngineCommandProjectionErrorDetector + projectionErrorDetector = EngineTaskCommandProjectionErrorDetector ) /** * Handle payload and correlations and serialize using provided object mapper (e.g. to JSON) */ @Suppress("UNCHECKED_CAST") - fun handlePayloadAndCorrelations(command: T): T = + fun handlePayloadAndCorrelations(command: T): T = // handle payload and correlations if (command is CreateTaskCommand) command.copy(payload = serialize(payload = command.payload, mapper = objectMapper)) as T @@ -93,12 +92,11 @@ class ProjectingCommandAccumulator( /** * If detail is AddCandidateUsersCommand or UpdateAttributeTaskCommand, no error reporting should be done. => False will be returned. */ -object EngineCommandProjectionErrorDetector : ProjectionErrorDetector { +object EngineTaskCommandProjectionErrorDetector : ProjectionErrorDetector { override fun shouldReportError(original: Any, detail: Any): Boolean { return when (detail) { - is AddCandidateUsersCommand, - is UpdateAttributeTaskCommand -> false + is AddCandidateUsersCommand, is UpdateAttributeTaskCommand -> false else -> true } } diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/SortingCommandAccumulator.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/SortingCommandAccumulator.kt index 30be64fe6..266fb3e81 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/SortingCommandAccumulator.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/accumulator/SortingCommandAccumulator.kt @@ -6,6 +6,6 @@ import io.holunda.camunda.taskpool.api.task.EngineTaskCommandSorter /** * Sorts commands by their order id */ -class SortingCommandAccumulator : CommandAccumulator { +class SortingCommandAccumulator : EngineTaskCommandAccumulator { override fun invoke(taskCommands: List) = taskCommands.sortedWith(EngineTaskCommandSorter()) } diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/gateway/AxonCommandListGateway.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/gateway/AxonCommandListGateway.kt index 3a7adc07d..46f4397ad 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/gateway/AxonCommandListGateway.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/sender/gateway/AxonCommandListGateway.kt @@ -1,7 +1,7 @@ package io.holunda.camunda.taskpool.sender.gateway import io.holunda.camunda.taskpool.TaskCollectorProperties -import io.holunda.camunda.taskpool.sender.CommandSender +import io.holunda.camunda.taskpool.sender.EngineTaskCommandSender import org.axonframework.commandhandling.CommandResultMessage import org.axonframework.commandhandling.gateway.CommandGateway import org.slf4j.Logger @@ -19,7 +19,7 @@ class AxonCommandListGateway( private val commandErrorHandler: CommandErrorHandler ) : CommandListGateway { - private val logger: Logger = LoggerFactory.getLogger(CommandSender::class.java) + private val logger: Logger = LoggerFactory.getLogger(EngineTaskCommandSender::class.java) /** * Sends data to gateway. Ignores any errors, but logs. @@ -30,7 +30,7 @@ class AxonCommandListGateway( val nextCommand = commands.first() val remainingCommands = commands.subList(1, commands.size) - if (properties.sender.enabled) { + if (properties.sendCommandsEnabled) { commandGateway.send(nextCommand) { commandMessage, commandResultMessage -> if (commandResultMessage.isExceptional) { commandErrorHandler.apply(commandMessage, commandResultMessage) @@ -40,7 +40,7 @@ class AxonCommandListGateway( sendToGateway(remainingCommands) } } else { - logger.debug("SENDER-003: Would have sent command $nextCommand") + logger.debug("SENDER-003: Seding command over gateway disabled by property. Would have sent command $nextCommand") sendToGateway(remainingCommands) } } diff --git a/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/collector/properties/TaskCollectorPropertiesExtendedTest.kt b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/collector/properties/TaskCollectorPropertiesExtendedTest.kt new file mode 100644 index 000000000..83bffff74 --- /dev/null +++ b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/collector/properties/TaskCollectorPropertiesExtendedTest.kt @@ -0,0 +1,142 @@ +package io.holunda.camunda.taskpool.collector.properties + +import io.holunda.camunda.taskpool.TaskCollectorConfiguration +import io.holunda.camunda.taskpool.TaskCollectorEnricherType +import io.holunda.camunda.taskpool.TaskCollectorProperties +import io.holunda.camunda.taskpool.TaskSenderType +import io.holunda.camunda.taskpool.enricher.VariablesEnricher +import io.holunda.camunda.taskpool.sender.EngineTaskCommandSender +import junit.framework.Assert.assertNotNull +import junit.framework.Assert.fail +import org.assertj.core.api.Assertions.assertThat +import org.assertj.core.api.Assertions.assertThatExceptionOfType +import org.axonframework.commandhandling.gateway.CommandGateway +import org.axonframework.eventhandling.EventBus +import org.axonframework.serialization.Serializer +import org.axonframework.serialization.xml.XStreamSerializer +import org.junit.Test +import org.mockito.Mockito.mock +import org.springframework.boot.context.annotation.UserConfigurations +import org.springframework.boot.test.context.runner.ApplicationContextRunner +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +class TaskCollectorPropertiesExtendedTest { + + private val contextRunner = ApplicationContextRunner() + .withConfiguration(UserConfigurations.of(TaskCollectorConfiguration::class.java)) + + @Test + fun testMinimal() { + contextRunner + .withUserConfiguration(TestMockConfiguration::class.java) + .withPropertyValues( + "spring.application.name=my-test-application", + "camunda.taskpool.collector.tasklist-url=http://some" + ).run { + + assertNotNull(it.getBean(TaskCollectorProperties::class.java)) + val props: TaskCollectorProperties = it.getBean(TaskCollectorProperties::class.java) + + // deprecated should not be used. + assertThat(props.enricher).isNull() + + assertThat(props.sendCommandsEnabled).isFalse + assertThat(props.applicationName).isEqualTo("my-test-application") + + assertThat(props.processDefinition.enabled).isFalse + + assertThat(props.processInstance.enabled).isFalse + + assertThat(props.task.enabled).isTrue + assertThat(props.task.sender.type).isEqualTo(TaskSenderType.tx) + assertThat(props.task.sender.sendWithinTransaction).isFalse + + assertThat(props.task.enricher.type).isEqualTo(TaskCollectorEnricherType.processVariables) + } + } + + @Test + fun testAllChanged() { + contextRunner + .withUserConfiguration(TestMockConfiguration::class.java) + .withUserConfiguration(AdditionalMockConfiguration::class.java) + .withPropertyValues( + "spring.application.name=my-test-application", + "camunda.taskpool.collector.tasklist-url=http://some", + "camunda.taskpool.collector.applicationName=another-than-spring", + "camunda.taskpool.collector.send-commands-enabled=true", + "camunda.taskpool.collector.process-definition.enabled=true", + "camunda.taskpool.collector.process-instance.enabled=true", + "camunda.taskpool.collector.task.sender.enabled=false", + "camunda.taskpool.collector.task.sender.type=custom", + "camunda.taskpool.collector.task.sender.send-within-transaction=true", + "camunda.taskpool.collector.task.enricher.type=custom", + ).run { + + assertNotNull(it.getBean(TaskCollectorProperties::class.java)) + val props: TaskCollectorProperties = it.getBean(TaskCollectorProperties::class.java) + + // deprecated should not be used. + assertThat(props.enricher).isNull() + + assertThat(props.applicationName).isEqualTo("another-than-spring") + assertThat(props.sendCommandsEnabled).isTrue + + assertThat(props.processDefinition.enabled).isTrue + + assertThat(props.processInstance.enabled).isTrue + + assertThat(props.task.sender.type).isEqualTo(TaskSenderType.custom) + assertThat(props.task.sender.sendWithinTransaction).isTrue + + assertThat(props.task.enricher.type).isEqualTo(TaskCollectorEnricherType.custom) + } + } + + + @Test + fun testDeprecation() { + // spring context exception is always an IllegalStateException + assertThatExceptionOfType(IllegalStateException::class.java).isThrownBy { + contextRunner + .withUserConfiguration(TestMockConfiguration::class.java) + .withPropertyValues( + "spring.application.name=my-test-application", + "camunda.taskpool.collector.tasklist-url=http://some", + "camunda.taskpool.collector.enricher.type=no" // deprecated property. + ).run { + assertNotNull(it.getBean(TaskCollectorProperties::class.java)) + fail("Spring context is initialized, but it should not since the config is invalid.") + } + } + } + /** + * Config class without configuration annotation not to confuse others. + */ + private class AdditionalMockConfiguration { + @Bean + fun engineTaskCommandSender(): EngineTaskCommandSender = mock(EngineTaskCommandSender::class.java) + + @Bean + fun variablesEnricher(): VariablesEnricher = mock(VariablesEnricher::class.java) + } + + /** + * Config class without configuration annotation not to confuse others. + */ + private class TestMockConfiguration { + + @Bean + fun eventSerializer(): Serializer = XStreamSerializer.builder().build() + + + @Bean + fun eventBus(): EventBus = mock(EventBus::class.java) + + @Bean + fun commandGateway(): CommandGateway = mock(CommandGateway::class.java) + + } + +} diff --git a/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/collector/properties/TaskCollectorPropertiesITest.kt b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/collector/properties/TaskCollectorPropertiesITest.kt index dbe953ec9..48d683bde 100644 --- a/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/collector/properties/TaskCollectorPropertiesITest.kt +++ b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/collector/properties/TaskCollectorPropertiesITest.kt @@ -21,7 +21,7 @@ class TaskCollectorPropertiesITest { @Test fun test_properties() { - assertThat(props.enricher.applicationName).isEqualTo("Foo") + assertThat(props.applicationName).isEqualTo("Foo") } } diff --git a/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/TaskCollectorTestApplication.kt b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/CollectorTestApplication.kt similarity index 90% rename from engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/TaskCollectorTestApplication.kt rename to engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/CollectorTestApplication.kt index b0ca33b56..0c060d6d2 100644 --- a/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/TaskCollectorTestApplication.kt +++ b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/CollectorTestApplication.kt @@ -8,4 +8,4 @@ import org.springframework.boot.autoconfigure.SpringBootApplication @SpringBootApplication @EnableProcessApplication @EnableTaskCollector -class TaskCollectorTestApplication +class CollectorTestApplication diff --git a/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/ProcessDefinitionServiceITest.kt b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/ProcessDefinitionServiceITest.kt index 5fbfa8630..e289587e4 100644 --- a/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/ProcessDefinitionServiceITest.kt +++ b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/ProcessDefinitionServiceITest.kt @@ -24,7 +24,7 @@ import org.springframework.test.context.junit4.SpringRunner * This ITests simulates work of Camunda process definition collector. */ @RunWith(SpringRunner::class) -@SpringBootTest(classes = [TaskCollectorTestApplication::class], webEnvironment = SpringBootTest.WebEnvironment.MOCK) +@SpringBootTest(classes = [CollectorTestApplication::class], webEnvironment = SpringBootTest.WebEnvironment.MOCK) @ActiveProfiles("collector-itest") @DirtiesContext class ProcessDefinitionServiceITest { diff --git a/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/TaskCollectorITest.kt b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/TaskCollectorITest.kt index 7cc91cf80..79fee7555 100644 --- a/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/TaskCollectorITest.kt +++ b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/itest/TaskCollectorITest.kt @@ -37,7 +37,7 @@ import java.util.concurrent.TimeUnit * This ITests simulates work of Camunda collector including variable enrichment. */ @RunWith(SpringRunner::class) -@SpringBootTest(classes = [TaskCollectorTestApplication::class], webEnvironment = SpringBootTest.WebEnvironment.MOCK) +@SpringBootTest(classes = [CollectorTestApplication::class], webEnvironment = SpringBootTest.WebEnvironment.MOCK) @ActiveProfiles("collector-itest") @DirtiesContext class TaskCollectorITest { diff --git a/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/sender/AxonCommandListGatewayTest.kt b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/sender/AxonCommandListGatewayTest.kt index ab1f02b4e..1fe56318a 100644 --- a/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/sender/AxonCommandListGatewayTest.kt +++ b/engine/taskpool-collector/src/test/kotlin/io/holunda/camunda/taskpool/sender/AxonCommandListGatewayTest.kt @@ -1,7 +1,6 @@ package io.holunda.camunda.taskpool.sender import io.holunda.camunda.taskpool.TaskCollectorProperties -import io.holunda.camunda.taskpool.TaskSenderProperties import io.holunda.camunda.taskpool.api.task.AssignTaskCommand import io.holunda.camunda.taskpool.api.task.CreateTaskCommand import io.holunda.camunda.taskpool.api.task.ProcessReference @@ -39,10 +38,8 @@ class AxonCommandListGatewayTest { val wrapper = AxonCommandListGateway( commandGateway = commandGateway, properties = TaskCollectorProperties( - springApplicationName = "some-name", - sender = TaskSenderProperties( - enabled = false - ) + applicationName = "some-name", + sendCommandsEnabled = false ), commandErrorHandler = LoggingTaskCommandErrorHandler(logger), commandSuccessHandler = LoggingTaskCommandSuccessHandler(logger) @@ -58,10 +55,8 @@ class AxonCommandListGatewayTest { val wrapper = AxonCommandListGateway( commandGateway = commandGateway, properties = TaskCollectorProperties( - springApplicationName = "some-name", - sender = TaskSenderProperties( - enabled = true - ) + applicationName = "some-name", + sendCommandsEnabled = true ), commandErrorHandler = LoggingTaskCommandErrorHandler(logger), commandSuccessHandler = LoggingTaskCommandSuccessHandler(logger) @@ -72,6 +67,7 @@ class AxonCommandListGatewayTest { id = "some-id", assignee = "kermit" ) + @Suppress("UNCHECKED_CAST") val callbackMatcher: ArgumentCaptor> = ArgumentCaptor.forClass(CommandCallback::class.java) as ArgumentCaptor> diff --git a/engine/taskpool-collector/src/test/resources/application-collector-itest.yml b/engine/taskpool-collector/src/test/resources/application-collector-itest.yml index 7c73270a1..a82845c27 100644 --- a/engine/taskpool-collector/src/test/resources/application-collector-itest.yml +++ b/engine/taskpool-collector/src/test/resources/application-collector-itest.yml @@ -13,12 +13,9 @@ camunda: taskpool: collector: tasklist-url: http://localhost/test-tasklist/ - enricher: -# application-name: collector-test - type: processVariables - sender: + send-commands-enabled: true + task: enabled: true - type: tx logging.level.io.holunda.camunda.taskpool: sender: DEBUG diff --git a/engine/taskpool-collector/src/test/resources/application-properties-itest.yml b/engine/taskpool-collector/src/test/resources/application-properties-itest.yml index 68e20834b..0e3a098c8 100644 --- a/engine/taskpool-collector/src/test/resources/application-properties-itest.yml +++ b/engine/taskpool-collector/src/test/resources/application-properties-itest.yml @@ -4,17 +4,16 @@ spring: camunda: taskpool: + # + # application-name property is disabled, to make sure that the defaulting to spring application name works. + # collector: tasklist-url: http://localhost/test-tasklist/ -# -# Enricher properties are disabled, to make sure that the defaulting to spring application name works. -# -# enricher: -# application-name: ${spring.application.name} # default -# type: processVariables - sender: - enabled: true - type: tx + task: + sender: + type: tx + enricher: + type: processVariables dataentry: sender: enabled: true diff --git a/examples/components/process-backend/src/main/kotlin/io/holunda/camunda/taskpool/example/process/rest/EnvironmentController.kt b/examples/components/process-backend/src/main/kotlin/io/holunda/camunda/taskpool/example/process/rest/EnvironmentController.kt index db3d29781..051192e28 100644 --- a/examples/components/process-backend/src/main/kotlin/io/holunda/camunda/taskpool/example/process/rest/EnvironmentController.kt +++ b/examples/components/process-backend/src/main/kotlin/io/holunda/camunda/taskpool/example/process/rest/EnvironmentController.kt @@ -21,7 +21,7 @@ class EnvironmentController( override fun getEnvironment(): ResponseEntity = ok( EnvironmentDto() - .applicationName(properties.enricher.applicationName) + .applicationName(properties.applicationName) .tasklistUrl(tasklistUrlResolver.getTasklistUrl()) ) } diff --git a/examples/scenarios/distributed-axon-server/process-application/src/main/resources/application.yml b/examples/scenarios/distributed-axon-server/process-application/src/main/resources/application.yml index 65147d2d6..97f2ab588 100644 --- a/examples/scenarios/distributed-axon-server/process-application/src/main/resources/application.yml +++ b/examples/scenarios/distributed-axon-server/process-application/src/main/resources/application.yml @@ -37,27 +37,28 @@ camunda: webapp: index-redirect-enabled: false taskpool: - gateway: type: revision-aware revision-aware: default-query-timeout: 3 collector: tasklist-url: http://localhost:8081/taskpool/ + application-name: ${spring.application.name} # default + send-commands-enabled: true + task: + enabled: true + enricher: + type: processVariablesSimpleDataEntryCommandSenderTest + sender: + type: tx process-definition: enabled: true process-instance: enabled: true - enricher: - application-name: ${spring.application.name} # default - type: processVariables - sender: - enabled: true - type: tx dataentry: sender: enabled: true - type: simple + type: simpleSimpleDataEntryCommandSenderTest applicationName: ${spring.application.name} # default form-url-resolver: defaultTaskTemplate: "/tasks/${formKey}/${id}?userId=%userId%" diff --git a/examples/scenarios/single-node/src/main/resources/application.yml b/examples/scenarios/single-node/src/main/resources/application.yml index b3bd1e3c7..cee53fb91 100755 --- a/examples/scenarios/single-node/src/main/resources/application.yml +++ b/examples/scenarios/single-node/src/main/resources/application.yml @@ -39,17 +39,19 @@ camunda: taskpool: collector: tasklist-url: http://localhost:${server.port}/taskpool/tasks + application-name: ${spring.application.name} # default + send-commands-enabled: true process-instance: enabled: true process-definition: enabled: true - enricher: - application-name: ${spring.application.name} # default - type: processVariables - sender: + task: enabled: true - type: tx - send-within-transaction: true # Must be set to true in single node scenario. + enricher: + type: processVariables + sender: + type: tx + send-within-transaction: true # Must be set to true in single node scenario. dataentry: sender: enabled: true @@ -71,12 +73,16 @@ camunda: logging.level: io.holunda.camunda: taskpool: + collector: + variable: DEBUG sender: WARN core: WARN view.simple: WARN datapool: - sender: DEBUG - org.springframework.web: DEBUG + sender: INFO + # To log REST controllers # org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping: TRACE +# To log web access +# org.springframework.web: DEBUG diff --git a/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/TaskCollectorProperties.kt b/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/TaskCollectorProperties.kt index d4e0f244d..a1d536ca0 100755 --- a/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/TaskCollectorProperties.kt +++ b/taskpool/taskpool-api/src/main/kotlin/io/holunda/camunda/taskpool/TaskCollectorProperties.kt @@ -4,57 +4,87 @@ import org.springframework.beans.factory.annotation.Value import org.springframework.boot.context.properties.ConfigurationProperties import org.springframework.boot.context.properties.ConstructorBinding import org.springframework.boot.context.properties.NestedConfigurationProperty -import java.lang.IllegalStateException /** * Configuration properties of task collector. + * Not using constructor binding here, because we need the springApplicationName. */ @ConfigurationProperties(prefix = "camunda.taskpool.collector") class TaskCollectorProperties( + + /** + * Denotes the (logical) name of the process application. + */ @Value("\${spring.application.name:unset-application-name}") - springApplicationName: String, + var applicationName: String, /** * Optional tasklist url, if no explicit resolver is provided. */ var tasklistUrl: String? = null, + /** - * Sender properties. + * Global value to control the command gateway. */ - @NestedConfigurationProperty - var sender: TaskSenderProperties = TaskSenderProperties(), + var sendCommandsEnabled: Boolean = false, /** - * Enricher properties. + * Deprecated task enricher properties -> moved to task.enricher. */ @NestedConfigurationProperty - var enricher: TaskCollectorEnricherProperties = TaskCollectorEnricherProperties(applicationName = springApplicationName), + @Deprecated("Please use camunda.taskpool.collector.task.enricher instead") + var enricher: TaskCollectorEnricherProperties? = null, /** - * Process definition collection properties. + * Task collector properties. + */ + @NestedConfigurationProperty + var task: TaskProperties = TaskProperties(), + /** + * Process definition collector properties. */ @NestedConfigurationProperty var processDefinition: ProcessDefinitionProperties = ProcessDefinitionProperties(), /** - * Process instance collection properties. + * Process instance collector properties. */ @NestedConfigurationProperty var processInstance: ProcessInstanceProperties = ProcessInstanceProperties() ) +/** + * Task collector properties. + * No constructor binding because of application name. + */ +@ConstructorBinding +data class TaskProperties( + /** + * Enable by default (since it was enabled before). + */ + val enabled: Boolean = true, + /** + * Task enricher properties. + */ + @NestedConfigurationProperty + val enricher: TaskCollectorEnricherProperties = TaskCollectorEnricherProperties(), + + /** + * Task sender properties. + */ + @NestedConfigurationProperty + val sender: TaskSenderProperties = TaskSenderProperties() +) + /** * Task command enricher properties. */ +@ConstructorBinding data class TaskCollectorEnricherProperties( /** * Type of enricher, see TaskCollectorEnricherType values. */ - var type: TaskCollectorEnricherType = TaskCollectorEnricherType.processVariables, - /** - * Denotes the (logical) name of the process application. - */ - var applicationName: String + val type: TaskCollectorEnricherType = TaskCollectorEnricherType.processVariables, ) /** @@ -65,35 +95,34 @@ enum class TaskCollectorEnricherType { * No enrichment. */ no, + /** * Enrich with process variables. */ processVariables, + /** * Custom enricher. */ custom } + /** - * Task command sender properties. + * Command sender properties. */ @ConstructorBinding data class TaskSenderProperties( - /** - * Task sender enabled. Defaults to false. - */ - var enabled: Boolean = false, /** * Sender type, defaults to tx */ - var type: TaskSenderType = TaskSenderType.tx, + val type: TaskSenderType = TaskSenderType.tx, /** * This flag controls if the tasks are sent within an open transaction (value true, before commit) * or not (value false, default, after commit). This setting is required if you move the command bus * and the command handling on the engine side. */ - var sendWithinTransaction: Boolean = false + val sendWithinTransaction: Boolean = false ) /** @@ -104,6 +133,7 @@ enum class TaskSenderType { * Sending after transaction commit. */ tx, + /** * Custom sending. */ @@ -119,7 +149,7 @@ data class ProcessDefinitionProperties( /** * Disable by default. */ - var enabled: Boolean = false + val enabled: Boolean = false ) @@ -132,5 +162,5 @@ data class ProcessInstanceProperties( /** * Disable by default. */ - var enabled: Boolean = false + val enabled: Boolean = false ) From 80a275c619ba184883a904afa75852ee9a511c21 Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Tue, 13 Oct 2020 16:35:17 +0200 Subject: [PATCH 08/16] more docs, fix 289# --- .../media/collector-building-blocks.graphml | 519 ++++++++++++++++++ .../media/collector-building-blocks.png | Bin 0 -> 43296 bytes .../orchid/resources/changelog/2.1/2.1.3.ad | 7 + .../components/engine-taskpool-collector.ad | 147 +++-- 4 files changed, 599 insertions(+), 74 deletions(-) create mode 100644 docs/src/orchid/resources/assets/media/collector-building-blocks.graphml create mode 100644 docs/src/orchid/resources/assets/media/collector-building-blocks.png diff --git a/docs/src/orchid/resources/assets/media/collector-building-blocks.graphml b/docs/src/orchid/resources/assets/media/collector-building-blocks.graphml new file mode 100644 index 000000000..45c8b711d --- /dev/null +++ b/docs/src/orchid/resources/assets/media/collector-building-blocks.graphml @@ -0,0 +1,519 @@ + + + + + + + + + + + + + + + + + + + + + + + + TaskEventCollector + + + + + + + + + + + + + + Spring Event Bus + + + + + + + + + + + Task Event + + + + + + + + + + + + + + + + + + ProcessInstanceEventCollector + + + + + + + + + + + + + + Process Instance Event + + + + + + + + + + + + + + + + + + ProcessVariableEventCollector + + + + + + + + + + + + + + Process Instance Event + + + + + + + + + + + + + + + + + + ProcessDefinitionEventCollector + + + + + + + + + + + + + + Process Definition Change + + + + + + + + + + + + + + + + + + TaskEventEnricher + + + + + + + + + + + + + + + TaskEventSender + + + + + + + + + + + + + + Engine Task Command + + + + + + + + + + + + + + + + + + Axon Command List Gateway + + + + + + + + + + + + + + Axon Command Bus + + + + + + + + + + + Process Instance Command + + + + + + + + + + + + + + + + + Process Variable Command + + + + + + + + + + + + + + + + + Process Definition Command + + + + + + + + + + + + + + + + + + Process definition job handler + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/src/orchid/resources/assets/media/collector-building-blocks.png b/docs/src/orchid/resources/assets/media/collector-building-blocks.png new file mode 100644 index 0000000000000000000000000000000000000000..cf543f1aa650c7b0a1e30534f83090aa931b1984 GIT binary patch literal 43296 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 literal 0 HcmV?d00001 diff --git a/docs/src/orchid/resources/changelog/2.1/2.1.3.ad b/docs/src/orchid/resources/changelog/2.1/2.1.3.ad index e753812fe..e136ffe7a 100644 --- a/docs/src/orchid/resources/changelog/2.1/2.1.3.ad +++ b/docs/src/orchid/resources/changelog/2.1/2.1.3.ad @@ -5,7 +5,14 @@ version: 2.1.3 == Features * Respect process instance lifecycle, see #281 +* Provide BOM for taskpool, see #280 + + +== Breaking changes + +* Chnaged taskpoool collector configuration properties (engine side), #286 == Bugfixes * Fixed more documentation dead links, see #277 +* Implemented test for collector properties, #285 diff --git a/docs/src/orchid/resources/wiki/user-guide/components/engine-taskpool-collector.ad b/docs/src/orchid/resources/wiki/user-guide/components/engine-taskpool-collector.ad index 1444973f9..dffbaf06f 100644 --- a/docs/src/orchid/resources/wiki/user-guide/components/engine-taskpool-collector.ad +++ b/docs/src/orchid/resources/wiki/user-guide/components/engine-taskpool-collector.ad @@ -8,53 +8,41 @@ pageId: engine-datapool-collector === Purpose -Taskpool Collector is a component usually deployed as a part of the process application -(aside with Camunda BPM Engine) that is responsible for collecting Spring events fired by -the Camunda Engine Eventing Plugin and creating the corresponding commands for the taskpool. -In doing so, it collects and enriches data and transmits it to Taskpool Core. +Taskpool Collector is a component deployed as a part of the process application +(aside with Camunda BPM Engine) that is responsible for collecting information from +the Camunda BPM Engine. It detects the _intent_ of the operations executed inside the engine +and creates the corresponding commands for the taskpool. The commands are enriched with data and transmitted to +other taskpool components (via Axon Command Bus). -In the following description, we use the term _event_ and _command_. Event denotes a data entity +In the following description, we use the terms _event_ and _command_. Event denotes an entity received from Camunda BPM Engine (from delegate event listener or from history event listener) -which is passed over to the Task Collector using internal Spring eventing mechanism. The Task Collector -converts the series of such events into an Taskpool Engine Command - an entity carrying an intent -of change inside of the taskpool core. +which is passed over to the Taskpool Collector using internal Spring eventing mechanism. The Taskpool +Collector converts the series of such events into a Taskpool Command - an entity carrying an intent +of change inside of the taskpool core. Please note that _event_ has another meaning in CQRS/ES systems +and other components of the taskpool, but in the context of Taskpool collector an event alway originates from +Spring eventing. === Features +- Collection of process definitions +- Collection of process instance events +- Collection of process variable change events - Collection of task events and history events -- Creation of corresponding task engine commands +- Creation of task engine commands - Enrichment of task engine commands with process variables - Attachment of correlation information to task engine commands -- Transmission of task engine commands +- Transmission of commands to Axon command bus - Provision of properties for process application === Architecture -[ditaa] ----- - - +---------+ +-------------+ +---------+ +--------------+ +-----------+ - | | | | | | | Task | | | - | Camunda +-=--->+ Event +-=---| Task +-=-->+ Command +---->+ Command | - | Event | | Collector | | Command | | Enricher | | Sender | - | {d} | | | | {d} | | Service | | | - +---------+ +-------------+ +---------+ +--+-------+---+ +-----------+ - : ^ - | : - V | - +--+-------+--+ - | | - | Enricher | - | | - +-------------+ - ----- +image::{{baseUrl('assets/media/collector-building-blocks.png')}}["Taskpool collector building blocks"] -The Taskpool Collector consists of several components: +The Taskpool Collector consists of several components which can be devided into the following groups: -- Event collector receives Spring Events from `camunda-eventing-engine-plugin` and forms commands -- Enricher performs the command enrichment with payload and data correlation -- Command sender is responsible for accumulating commands and sending them to Command Gateway +- Event collectors receive are responsible for gathering information and form commands +- Processors performs the command enrichment with payload and data correlation +- Command senders are responsible for accumulating commands and sending them to Command Gateway === Usage and configuration @@ -79,8 +67,8 @@ Then activate the taskpool collector by providing the annotation on any Spring C ---- @Configuration -@EnableDataEntryCollector -class MyDataCollectorConfiguration { +@EnableTaskpoolCollector +class MyProcessApplicationConfiguration { } @@ -90,7 +78,7 @@ class MyDataCollectorConfiguration { === Event collection -Taskpool collector registers Spring Event Listener to the following events, fired by Camunda Eventing Engine Plugin: +Taskpool Collector registers Spring Event Listener to the following events, fired by Camunda Eventing Engine Plugin: * `DelegateTask` events: ** create @@ -100,35 +88,39 @@ Taskpool collector registers Spring Event Listener to the following events, fire * `HistoryEvent` events: ** HistoricTaskInstanceEvent ** HistoricIdentityLinkLogEvent +** HistoricProcessInstanceEventEntity +** HistoricVariableUpdateEventEntity +** HistoricDetailVariableInstanceUpdateEntity + +The events are transformed into corresponding commands and passed over to the processor layer. === Task commands enrichment -Alongside with data attributes received from the Camunda BPM engine, the task engine commands -can be enriched with additional business data. There are three enrichment modes available controlled -by the `camunda.taskpool.collector.enricher.type` property: +Alongside with attributes received from the Camunda BPM engine, the engine task commands +can be enriched with additional attributes. + +There are three enrichment modes available controlled by the `camunda.taskpool.task.collector.enricher.type` property: * `no`: No enrichment takes place -* `process-variables`: Enrichment with process variables +* `process-variables`: Enrichment of engine task commands with process variables * `custom`: User provides own implementation ==== Process variable enrichment -In particular cases, the task related data is not sufficient for the information required in task list or -other user-related components. The information may be available as process variables and need to be attached -to the task in the taskpool. This is where _Process Variable Task Enricher_ can be used. For this purpose, -set the property `camunda.taskpool.collector.enricher.type` to `process-variables` and the enricher will -put all process variables into the task payload (defaults to an empty `EXCLUDE` filter). +In particular cases, the data enclosed into task attibutes is not sufficient for the task list or other user-related components. The information may be available as process variables and need to be attached to the task in the taskpool. This is where _Process Variable Task Enricher_ can be used. For this purpose, active it setting the property `camunda.taskpool.collector.task.enricher.type` to `process-variables` and the enricher will +put process variables into the task payload. You can control what variables will be put into task command payload by providing the Process Variables Filter. The `ProcessVariablesFilter` is a Spring bean holding a list of individual `VariableFilter` - at most one per -process definition key and optionally one without process definition key (a global filter). +process definition key and optionally one without process definition key (a global filter). If the filter is not provded, +a default filter is used which is an empty `EXCLUDE` filter, resulting in all process variables being attached to the user task. A `VariableFilter` can be of the following type: * `TaskVariableFilter`: -** `INCLUDE`: task-level include filter, denoting a list of variables to be added for the task. -** `EXCLUDE`: task-level exclude filter, denoting a list of variables to be ignored. All other variables are included. +** `INCLUDE`: task-level include filter, denoting a list of variables to be added for the task defined in the filter. +** `EXCLUDE`: task-level exclude filter, denoting a list of variables to be ignored for the task defined in the filter. All other variables are included. * `ProcessVariableFilter` with process definition key: ** `INCLUDE`: process-level include filter, denoting a list of variables to be added for all tasks of the process. ** `EXCLUDE`: process-level exclude filter, denoting a list of variables to be ignored for all tasks of the process. @@ -180,23 +172,23 @@ Here is an example, how the process variable filter can configure the enrichment ---- TIP: If you want to implement a custom enrichment, please provide your own implementation of the interface `VariablesEnricher` -(register a Spring Component of the type) and set the property `camunda.taskpool.collector.enricher.type` to `custom`. +(register a Spring Component of the type) and set the property `camunda.taskpool.collector.task.enricher.type` to `custom`. === Data Correlation Apart from task payload attached by the enricher, the so-called _Correlation_ with data entries can -be configured. The idea is to attach one or several references (that is `entryType` and `entryId`) to -business data entry(ies) to a task. In a view projection this correlations can be resolved and the +be configured. The data correlation allows to attach one or several references (that is a pair of values `entryType` and `entryId`) of +business data entry(ies) to a task. In the projection (which is used for querying of tasks) this correlations is be resolved and the information from business data events can be shown together with task information. -The correlation to data events can be configured by providing a `ProcessVariablesCorrelator`. Here is +The correlation to data events can be configured by providing a `ProcessVariablesCorrelator` bean. Here is an example how this can be done: [source, kotlin] ---- @Bean -open fun processVariablesCorrelator() = ProcessVariablesCorrelator( +fun processVariablesCorrelator() = ProcessVariablesCorrelator( ProcessVariableCorrelation(ProcessApproveRequest.KEY, <1> mapOf( @@ -213,25 +205,24 @@ open fun processVariablesCorrelator() = ProcessVariablesCorrelator( <3> define a correlation globally (for the whole process) The process variable correlator holds a list of process variable correlations - one for every process -definition key. Every `ProcessVariableCorrelation` configures global (that is for every task) or task correlation -(for particular task definition key) by providing a correlation map. A correlation map is keyed by the -Camunda Process Variable Name and holds business data Entry Type as value. +definition key. Every `ProcessVariableCorrelation` configures for all tasks or for an individual taskby providing a so-called correlation +map. A correlation map is keyed by the name of a process variable inside Camunda Process Engine and holds the type of business data entry as value. Here is an example. Imagine the process instance is storing the id of an approval request in a process variable called `varRequestId`. The system responsible for storing approval requests fires data entry events supplying the -data and using the entry type `approvalRequest` and the id of the request as `entryId`. In order to +data and using the entry type `io.my.approvalRequest` and the id of the request as `entryId`. In order to create a correlation in task `task_approve_request` of the `process_approval_process` we would provide the following configuration of the correlator: [source,kotlin] ---- @Bean -open fun processVariablesCorrelator() = ProcessVariablesCorrelator( +fun processVariablesCorrelator() = ProcessVariablesCorrelator( ProcessVariableCorrelation("process_approval_process", mapOf( "task_approve_request" to mapOf( - "varRequestId" to "approvalRequest" + "varRequestId" to "io.my.approvalRequest" // process variable 'varRequestId' holds the id of a data entry of type 'io.my.approvalRequest' ) ) ) @@ -248,27 +239,27 @@ and the process reaches the task `task_approve_request`, the task will get the f ] ---- -=== Command transmission +=== Command aggregation -In order to control sending of commands to command gateway, the command sender activation property -`camunda.taskpool.collector.sender.enabled` (default is `true`) is available. If disabled, the command sender -will log any command instead of sending it to the command gateway. +In order to control sending of commands to command sender, the command sender activation property +`camunda.taskpool.collector.task.enabled` is available. If disabled, the command sender +will log any command instead of aggregating sending it to the command gateway. -In addition you can control by the property `camunda.taskpool.collector.sender.type` if you want to use the default command sender or provide your own implementation. +In addition you can control by the property `camunda.taskpool.collector.task.sender.type` if you want to use the default command sender or provide your own implementation. The default provided command sender (type: `tx`) is collects all task commands during one transaction, group them by task id and accumulates by creating one command reflecting the intent of the task operation. It uses Axon Command Bus (encapsulated -by the `AxonCommandListGateway`. +by the `AxonCommandListGateway` for sending the result over to the Axon command gateway. TIP: If you want to implement a custom command sending, please provide your own implementation of the interface `EngineTaskCommandSender` -(register a Spring Component of the type) and set the property `camunda.taskpool.collector.sender.type` to `custom`. +(register a Spring Component of the type) and set the property `camunda.taskpool.collector.task.sender.type` to `custom`. The Spring event listeners receiving events from the Camunda Engine plugin are called before the engine commits the transaction. -Since all processing inside collector and enricher is performed synchronous, the sender must waits until transaction to +Since all processing inside collector component and enricher is performed synchronously, the sender must waits until transaction to be successfully committed before sending any commands to the Command Gateway. Otherwise, on any error the transaction would be rolled back and the command would create an inconsistency between the taskpool and the engine. -Depending on your deployment scenario, you may want to control the exact point in time when the commands are send to Command Bus. -The property `camunda.taskpool.collector.sender.send-within-transaction` is designed to influence this. If set to `true`, the commands +Depending on your deployment scenario, you may want to control the exact point in time when the commands are send to command gateway. +The property `camunda.taskpool.collector.task.sender.send-within-transaction` is designed to influence this. If set to `true`, the commands are sent _before_ the process engine transaction is committed, otherwise commands are sent _after_ the process engine transaction is committed. WARNING: Never send commands over remote messaging before the transaction is committed, since you may produce unexpected results if Camunda fails @@ -280,12 +271,9 @@ The commands sent via gateway (e.g. `AxonCommandListGateway`) are received by Co on the state of the aggregate and other components. The `AxonCommandListGateway` is informed about the command outcome. By default, it will log the outcome to console (success is logged in `DEBUG` log level, errors are using `ERROR` log level). -In some situations it is required to take care of command outcome. A prominent example is to include a metric for command dispatching errors into monitoring. For doing so, -it is possible to provide own handlers for success and error command outcome. - -For the Task Command Sender (as a part of `Taskpool Collector`) please provide a Spring Bean implementing the `CommandSuccessHandler` -and `CommandErrorHandler` accordingly. +In some situations it is required to take care of command outcome. A prominent example is to include a metric for command dispatching errors into monitoring. For doing so, it is possible to provide own handlers for success and error command outcome. For this purpose, please provide a Spring Bean implementing the `CommandSuccessHandler`and `CommandErrorHandler` accordingly. +Here is an example, how such a handler may look like: [source, kotlin] ---- @@ -301,6 +289,17 @@ and `CommandErrorHandler` accordingly. ---- +=== Configuration properties overview +.Title +|=== +|Name |Purpose |Default +|Cell in column 1, row 1 +|Cell in column 2, row 1 +|Cell in column 3, row 1 +|Cell in column 1, row 2 +|Cell in column 2, row 2 +|Cell in column 3, row 2 +|=== \ No newline at end of file From 52bbeff5a73da44472ce05bdf1124d30fa66f38c Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Tue, 13 Oct 2020 16:35:26 +0200 Subject: [PATCH 09/16] use lenient serializer in tests --- .../holunda/camunda/taskpool/upcast/TaskEventUpcasterTest.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/taskpool/taskpool-event/src/test/kotlin/io/holunda/camunda/taskpool/upcast/TaskEventUpcasterTest.kt b/taskpool/taskpool-event/src/test/kotlin/io/holunda/camunda/taskpool/upcast/TaskEventUpcasterTest.kt index 5122b08e3..8eb772625 100644 --- a/taskpool/taskpool-event/src/test/kotlin/io/holunda/camunda/taskpool/upcast/TaskEventUpcasterTest.kt +++ b/taskpool/taskpool-event/src/test/kotlin/io/holunda/camunda/taskpool/upcast/TaskEventUpcasterTest.kt @@ -45,7 +45,7 @@ class TaskEventUpcasterTest { val xml = generateFakeOldEventXML(clazz) val document = SAXReader().read(StringReader(xml)) val clazz = org.dom4j.Document::class.java - val serializer = XStreamSerializer.defaultSerializer() + val serializer = XStreamSerializer.builder().lenientDeserialization().build() val entry: EventData = SimpleEventData( metaData = SimpleSerializedObject(DocumentHelper.createDocument(), clazz, SimpleSerializedType(MetaData::class.java.name, null)), @@ -73,6 +73,7 @@ class TaskEventUpcasterTest { TaskToBeCompletedEvent2To4Upcaster(), TaskDeferredEvent2To4Upcaster(), TaskUndeferredEvent2To4Upcaster(), + ) val result = upcaster.upcast(eventStream).toList() val event: T = serializer.deserialize(result[0].data) From 7d7d89891163aea7c8927e3f1ceea4c24d2dbf32 Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Wed, 14 Oct 2020 11:44:02 +0200 Subject: [PATCH 10/16] more docs --- .../HistoricVariableInstanceExtensions.kt | 2 ++ .../SingleNodeExampleProcessApplication.kt | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/HistoricVariableInstanceExtensions.kt diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/HistoricVariableInstanceExtensions.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/HistoricVariableInstanceExtensions.kt new file mode 100644 index 000000000..42a1eaa54 --- /dev/null +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/HistoricVariableInstanceExtensions.kt @@ -0,0 +1,2 @@ +package io.holunda.camunda.taskpool.collector + diff --git a/examples/scenarios/single-node/src/main/kotlin/io/holunda/camunda/taskpool/example/process/SingleNodeExampleProcessApplication.kt b/examples/scenarios/single-node/src/main/kotlin/io/holunda/camunda/taskpool/example/process/SingleNodeExampleProcessApplication.kt index e3c1c975b..6dc8ef2a9 100755 --- a/examples/scenarios/single-node/src/main/kotlin/io/holunda/camunda/taskpool/example/process/SingleNodeExampleProcessApplication.kt +++ b/examples/scenarios/single-node/src/main/kotlin/io/holunda/camunda/taskpool/example/process/SingleNodeExampleProcessApplication.kt @@ -12,15 +12,28 @@ import org.axonframework.messaging.correlation.CorrelationDataProvider import org.axonframework.messaging.correlation.MessageOriginProvider import org.axonframework.messaging.correlation.MultiCorrelationDataProvider import org.axonframework.messaging.correlation.SimpleCorrelationDataProvider +import org.axonframework.serialization.Serializer +import org.axonframework.serialization.xml.XStreamSerializer import org.springframework.boot.SpringApplication import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.boot.runApplication import org.springframework.context.annotation.Bean - +/** + * Starts the single node application. + */ fun main(args: Array) { - SpringApplication.run(SingleNodeExampleProcessApplication::class.java, *args) + runApplication().let { Unit } } +/** + * Application being everything in one node: + * - process application + * - task pool core + * - data pool core + * - in-memory view + * - task list + */ @SpringBootApplication @EnableExampleUsers @EnableTaskPoolSimpleView @@ -43,5 +56,4 @@ class SingleNodeExampleProcessApplication { ) ) } - } From bbcfc3dfe417b9911db1dff4fb230d5848139d85 Mon Sep 17 00:00:00 2001 From: Lars Bilger Date: Thu, 15 Oct 2020 09:59:33 +0200 Subject: [PATCH 11/16] feat: refactor TaskChangeTracker and make it more robust --- view/mongo/pom.xml | 6 + .../view/mongo/service/TaskChangeTracker.kt | 95 +++++----- .../mongo/service/TaskChangeTrackerTest.kt | 175 ++++++++++++++++++ 3 files changed, 227 insertions(+), 49 deletions(-) create mode 100644 view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskChangeTrackerTest.kt diff --git a/view/mongo/pom.xml b/view/mongo/pom.xml index bfe62a455..13fef9b76 100755 --- a/view/mongo/pom.xml +++ b/view/mongo/pom.xml @@ -87,6 +87,12 @@ awaitility test
+ + io.projectreactor + reactor-test + ${project-reactor.version} + test + diff --git a/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskChangeTracker.kt b/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskChangeTracker.kt index 9fe568b77..341432f0c 100644 --- a/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskChangeTracker.kt +++ b/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskChangeTracker.kt @@ -1,5 +1,6 @@ package io.holunda.camunda.taskpool.view.mongo.service +import com.mongodb.MongoCommandException import com.mongodb.client.model.changestream.OperationType import io.holunda.camunda.taskpool.api.business.dataIdentityString import io.holunda.camunda.taskpool.view.Task @@ -9,14 +10,14 @@ import io.holunda.camunda.taskpool.view.query.task.ApplicationWithTaskCount import mu.KLogging import org.bson.BsonValue import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty -import org.springframework.data.mongodb.core.ChangeStreamEvent import org.springframework.stereotype.Component import reactor.core.Disposable import reactor.core.publisher.Flux import reactor.core.publisher.Mono +import reactor.core.publisher.SignalType +import reactor.util.retry.Retry import java.time.Duration -import java.util.function.Function.identity -import javax.annotation.PostConstruct +import java.util.logging.Level import javax.annotation.PreDestroy /** @@ -32,46 +33,47 @@ class TaskChangeTracker( ) { companion object : KLogging() - private lateinit var changeStream: Flux> - private lateinit var trulyDeleteChangeStreamSubscription: Disposable + private var lastSeenResumeToken: BsonValue? = null - /** - * Create subscription. - */ - @PostConstruct - fun createSubscription() { - var lastSeenResumeToken: BsonValue? = null - changeStream = Mono.fromSupplier { taskRepository.getTaskUpdates(lastSeenResumeToken) } - .flatMapMany(identity()) - .doOnNext { event -> - val resumeToken = event.resumeToken - if (resumeToken != null) lastSeenResumeToken = resumeToken - } - .filter { event -> - when (event.operationType) { - OperationType.INSERT, OperationType.UPDATE, OperationType.REPLACE -> { - logger.debug { "Got ${event.operationType?.value} event: $event" } - true - } - else -> { - logger.trace { "Ignoring ${event.operationType?.value} event: $event" } - false - } + private val changeStream: Flux = Flux.defer { taskRepository.getTaskUpdates(lastSeenResumeToken) } + // When there are no more subscribers to the change stream, the flux is cancelled. When a new subscriber appears, they should not get any past updates. + // This shouldn't happen at all because the `trulyDeleteChangeStream` subscription should always stay active, but we keep it as a last resort. + .doOnCancel { lastSeenResumeToken = null } + // Remember the last seen resume token if one is present + .doOnNext { event -> lastSeenResumeToken = event.resumeToken ?: lastSeenResumeToken } + // When the resume token is out of date, Mongo will throw an error 'resume of change stream was not possible, as the resume token was not found.' + // Unfortunately, there is no way to identify exactly this error because error codes and messages vary by Mongo server version. + // The closest we can get is reacting on any MongoCommandException and resetting the token so that upon the next retry, we start without a token. + .doOnError(MongoCommandException::class.java) { lastSeenResumeToken = null } + .filter { event -> + when (event.operationType) { + OperationType.INSERT, OperationType.UPDATE, OperationType.REPLACE -> { + logger.debug { "Got ${event.operationType?.value} event: $event" } + true + } + else -> { + logger.trace { "Ignoring ${event.operationType?.value} event: $event" } + false } } - .retryBackoff(Long.MAX_VALUE, Duration.ofMillis(100), Duration.ofSeconds(10)) - .share() + } + .log(TaskChangeTracker::class.qualifiedName, Level.WARNING, SignalType.ON_ERROR) + .retryWhen(Retry.backoff(Long.MAX_VALUE, Duration.ofMillis(100)).maxBackoff(Duration.ofSeconds(10))) + .concatMap { event -> Mono.justOrEmpty(event.body) } + .share() - // Truly delete documents that have been marked deleted - trulyDeleteChangeStreamSubscription = changeStream - .filter { event -> event.body?.deleted == true } - .concatMap { event -> - @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") - taskRepository.deleteById(event.body.id) - .doOnSuccess { logger.trace { "Deleted task ${event.body.id} from database." } } - } - .subscribe() - } + // Truly delete documents that have been marked deleted + private val trulyDeleteChangeStreamSubscription: Disposable = changeStream + .filter { it.deleted } + .flatMap( { task -> + taskRepository.deleteById(task.id) + .doOnSuccess { logger.trace { "Deleted task ${task.id} from database." } } + .doOnError { e -> logger.debug(e) { "Deleting task ${task.id} from database failed." } } + .retryWhen(Retry.backoff(5, Duration.ofMillis(50))) + .doOnError { e -> logger.warn(e) { "Deleting task ${task.id} from database failed and retries are exhausted." } } + .onErrorResume { Mono.empty() } + }, 10 ) + .subscribe() /** * Clear subscription. @@ -87,9 +89,8 @@ class TaskChangeTracker( fun trackTaskCountsByApplication(): Flux = changeStream .window(Duration.ofSeconds(1)) .concatMap { - it.reduce(setOf()) { applicationNames, event -> - @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") - applicationNames + event.body.sourceReference.applicationName + it.reduce(setOf()) { applicationNames, task -> + applicationNames + task.sourceReference.applicationName } } .concatMap { Flux.fromIterable(it) } @@ -99,18 +100,14 @@ class TaskChangeTracker( * Adopt changes to task update stream. */ fun trackTaskUpdates(): Flux = changeStream - .map { event -> - @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") - event.body.task() - } + .map { it.task() } /** * Adopt changes to task with data entries update stream. */ fun trackTaskWithDataEntriesUpdates(): Flux = changeStream - .concatMap { event -> - @Suppress("RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") - val task = event.body.task() + .concatMap { taskDocument -> + val task = taskDocument.task() this.dataEntryRepository.findAllById(task.correlations.map { dataIdentityString(entryType = it.key, entryId = it.value.toString()) }) .map { it.dataEntry() } .collectList() diff --git a/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskChangeTrackerTest.kt b/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskChangeTrackerTest.kt new file mode 100644 index 000000000..aa5201ffa --- /dev/null +++ b/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskChangeTrackerTest.kt @@ -0,0 +1,175 @@ +package io.holunda.camunda.taskpool.view.mongo.service + +import com.mongodb.MongoCommandException +import com.mongodb.ServerAddress +import com.mongodb.client.model.changestream.ChangeStreamDocument +import com.mongodb.client.model.changestream.OperationType +import com.nhaarman.mockitokotlin2.any +import com.nhaarman.mockitokotlin2.eq +import com.nhaarman.mockitokotlin2.mock +import com.nhaarman.mockitokotlin2.whenever +import io.holunda.camunda.taskpool.api.task.ProcessReference +import io.holunda.camunda.taskpool.view.Task +import io.holunda.camunda.taskpool.view.mongo.repository.DataEntryRepository +import io.holunda.camunda.taskpool.view.mongo.repository.ProcessReferenceDocument +import io.holunda.camunda.taskpool.view.mongo.repository.TaskDocument +import io.holunda.camunda.taskpool.view.mongo.repository.TaskRepository +import org.bson.BsonDocument +import org.bson.BsonString +import org.bson.Document +import org.junit.Test +import org.springframework.data.mongodb.core.ChangeStreamEvent +import org.springframework.data.mongodb.core.convert.MongoConverter +import reactor.core.Disposable +import reactor.core.publisher.Mono +import reactor.test.StepVerifier +import reactor.test.publisher.TestPublisher +import java.time.Duration + +internal class TaskChangeTrackerTest { + private val taskRepository: TaskRepository = mock() + private val dataEntryRepository: DataEntryRepository = mock() + + // Lazy initialization is needed for StepVerifier.withVirtualTime to work properly + private val taskChangeTracker by lazy { TaskChangeTracker(taskRepository, dataEntryRepository) } + + @Test + fun `subscribes only once to mongo change stream`() { + val changeStreamPublisher = publisherForResumeToken() + + var secondSubscription: Disposable? = null + StepVerifier.withVirtualTime { taskChangeTracker.trackTaskUpdates() } + .expectSubscription() + .then { secondSubscription = taskChangeTracker.trackTaskUpdates().subscribe() } + .then { changeStreamPublisher.assertSubscribers(1) } + .thenCancel() + .verify() + + changeStreamPublisher.assertSubscribers(1) + secondSubscription!!.dispose() + changeStreamPublisher.assertSubscribers(1) + } + + @Test + fun `resumes change stream at last known position after errors`() { + val initialPublisher = publisherForResumeToken(null) + val nextPublisher = publisherForResumeToken(1) + + StepVerifier.withVirtualTime { taskChangeTracker.trackTaskUpdates() } + .expectSubscription() + .then { initialPublisher.next(changeStreamEvent(1, "123")) } + .expectNext(task("123")) + .then { initialPublisher.error(RuntimeException("Connection down")) } + .expectNoEvent(1.seconds) + .then { nextPublisher.next(changeStreamEvent(2, "456")) } + .expectNext(task("456")) + .verifyTimeout(10.seconds) + } + + @Test + fun `resumes change stream at end after last subscriber cancels`() { + val initialPublisher = publisherForResumeToken(null) + + // We're trying to test a state that should never normally happen, but we can simulate it by unsubscribing the task change tracker. + StepVerifier.withVirtualTime { taskChangeTracker.apply { clearSubscription() }.trackTaskUpdates() } + .expectSubscription() + .then { initialPublisher.next(changeStreamEvent(1, "123")) } + .expectNext(task("123")) + .verifyTimeout(10.seconds) + + val nextPublisher = publisherForResumeToken(null) + StepVerifier.withVirtualTime { taskChangeTracker.trackTaskUpdates() } + .expectSubscription() + .then { nextPublisher.next(changeStreamEvent(2, "456")) } + .expectNext(task("456")) + .verifyTimeout(10.seconds) + } + + @Test + fun `resumes change stream at end if resume token is invalid`() { + val initialPublisher = publisherForResumeToken(null) + val nextPublisher = publisherForResumeToken(1) + val lastPublisher = publisher() + + StepVerifier.withVirtualTime { taskChangeTracker.trackTaskUpdates() } + .expectSubscription() + .then { initialPublisher.next(changeStreamEvent(1, "123")) } + .expectNext(task("123")) + .then { initialPublisher.error(RuntimeException("Connection down")) } + .expectNoEvent(1.seconds) + .then { nextPublisher.assertSubscribers() } + .then { lastPublisher.returnForResumeToken(null) } + .then { nextPublisher.error(MongoCommandException(BsonDocument(), ServerAddress())) } + .expectNoEvent(1.seconds) + .then { lastPublisher.assertSubscribers() } + .then { lastPublisher.next(changeStreamEvent(2, "456")) } + .expectNext(task("456")) + .verifyTimeout(10.seconds) + } + + @Test + fun `deletes tasks that were marked as deleted`() { + val initialPublisher = publisherForResumeToken(null) + val deleteResult = TestPublisher.createCold().complete() + whenever(taskRepository.deleteById("123")).thenReturn(deleteResult.mono()) + + StepVerifier.withVirtualTime { taskChangeTracker.trackTaskUpdates() } + .expectSubscription() + .then { initialPublisher.next(changeStreamEvent(1, "123", deleted = true)) } + .expectNext(task("123", deleted = true)) + .then { deleteResult.assertWasSubscribed() } + .verifyTimeout(10.seconds) + } + + @Test + fun `deletes tasks also if previous delete failed`() { + val initialPublisher = publisherForResumeToken(null) + val deleteResult = TestPublisher.createCold().complete() + whenever(taskRepository.deleteById("123")).thenReturn(Mono.error(RuntimeException("Delete failed"))) + whenever(taskRepository.deleteById("456")).thenReturn(deleteResult.mono()) + + StepVerifier.withVirtualTime { taskChangeTracker.trackTaskUpdates() } + .expectSubscription() + .then { initialPublisher.next(changeStreamEvent(1, "123", deleted = true)) } + .expectNext(task("123", deleted = true)) + .then { initialPublisher.next(changeStreamEvent(1, "456", deleted = true)) } + .expectNext(task("456", deleted = true)) + .then { deleteResult.assertWasSubscribed() } + .verifyTimeout(10.seconds) + } + + private fun publisherForResumeToken(resumeToken: Int? = null): TestPublisher> = + publisher().returnForResumeToken(resumeToken) + + private fun publisher() = TestPublisher.create>() + + private fun TestPublisher>.returnForResumeToken(resumeToken: Int?) = apply { + whenever(taskRepository.getTaskUpdates(resumeToken?.let { resumeToken(it) })).thenReturn(this.flux()) + } + + private fun changeStreamEvent(resumeToken: Int, taskId: String, deleted: Boolean = false): ChangeStreamEvent { + val converter: MongoConverter = mock() + whenever(converter.read(eq(TaskDocument::class.java), any())).thenAnswer { (it.arguments[1] as Document)["body"] } + return ChangeStreamEvent(ChangeStreamDocument(OperationType.INSERT, resumeToken(resumeToken), null, null, Document("body", taskDocument(taskId, deleted)), null, null, null, null, null), TaskDocument::class.java, converter) + } + + private fun taskDocument(id: String, deleted: Boolean = false) = + TaskDocument( + id, + sourceReference = ProcessReferenceDocument("", "", "", "", "", ""), + taskDefinitionKey = "", + deleted = deleted + ) + + private fun task(id: String, deleted: Boolean = false) = + Task( + id, + sourceReference = ProcessReference("", "", "", "", "", ""), + taskDefinitionKey = "", + deleted = deleted + ) + + private fun resumeToken(counter: Int) = BsonDocument("token", BsonString("token$counter")) +} + +internal val Int.seconds get() = Duration.ofSeconds(this.toLong()) From da86d6555fd0dc5291c1f223d40c573e08ff6728 Mon Sep 17 00:00:00 2001 From: Lars Bilger Date: Thu, 15 Oct 2020 10:13:56 +0200 Subject: [PATCH 12/16] fix: fix flaky test fixes #288 --- .../src/test/kotlin/VariableSerializerTest.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/engine/variable-serializer/src/test/kotlin/VariableSerializerTest.kt b/engine/variable-serializer/src/test/kotlin/VariableSerializerTest.kt index d3fad37f6..051d4c624 100755 --- a/engine/variable-serializer/src/test/kotlin/VariableSerializerTest.kt +++ b/engine/variable-serializer/src/test/kotlin/VariableSerializerTest.kt @@ -7,7 +7,6 @@ import org.camunda.bpm.engine.variable.Variables import org.junit.Test import java.text.SimpleDateFormat import java.time.Instant -import java.time.Instant.now import java.time.OffsetDateTime import java.time.ZoneOffset @@ -51,7 +50,7 @@ class SimpleDataEntryCommandSenderTest { mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false) mapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false) - val now = now() + val now = Instant.parse("2020-10-15T07:20:05.871641Z") val pojo = Pojo5(key = "value", ts = now, date = now.atOffset(ZoneOffset.UTC)) val result = serialize(pojo, mapper) From 14d5434f517c4b6bb01a1bbf1182d6d22349ecde Mon Sep 17 00:00:00 2001 From: Patrick Schalk Date: Tue, 20 Oct 2020 18:47:11 +0200 Subject: [PATCH 13/16] Move logging from event sourcing handler to command handler. #292 --- .../taskpool/core/task/TaskAggregate.kt | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/task/TaskAggregate.kt b/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/task/TaskAggregate.kt index 1da0207db..99ad27bd7 100755 --- a/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/task/TaskAggregate.kt +++ b/taskpool/taskpool-core/src/main/kotlin/io/holunda/camunda/taskpool/core/task/TaskAggregate.kt @@ -208,7 +208,6 @@ class TaskAggregate() { } } - @EventSourcingHandler fun on(event: TaskCreatedEngineEvent) { this.id = event.id @@ -229,26 +228,21 @@ class TaskAggregate() { this.owner = event.owner this.payload = event.payload this.priority = event.priority - - logger.debug { "Created task $event" } } @EventSourcingHandler fun on(event: TaskAssignedEngineEvent) { this.assignee = event.assignee - logger.debug { "Assigned task $this.id to $assignee" } } @EventSourcingHandler fun on(event: TaskCompletedEngineEvent) { this.completed = true - logger.debug { "Completed task $this.id by $assignee" } } @EventSourcingHandler fun on(event: TaskDeletedEngineEvent) { this.deleted = true - logger.debug { "Deleted task $this.id with reason ${event.deleteReason}" } } private fun assign(command: AssignTaskCommand) = @@ -271,7 +265,8 @@ class TaskAggregate() { correlations = this.correlations, businessKey = this.businessKey, followUpDate = this.followUpDate - )) + ).also { logger.debug { "Assigned task ${it.id} to ${it.assignee}" } } + ) private fun create(command: CreateTaskCommand) = AggregateLifecycle.apply( @@ -293,7 +288,8 @@ class TaskAggregate() { correlations = command.correlations, businessKey = command.businessKey, followUpDate = command.followUpDate - )) + ).also { logger.debug { "Created task $it" } } + ) private fun complete(assignee: String?) { if (assignee != null) { @@ -316,7 +312,8 @@ class TaskAggregate() { correlations = this.correlations, businessKey = this.businessKey, followUpDate = this.followUpDate - )) + ) + ) } AggregateLifecycle.apply( TaskCompletedEngineEvent( @@ -337,7 +334,8 @@ class TaskAggregate() { correlations = this.correlations, businessKey = this.businessKey, followUpDate = this.followUpDate - )) + ).also { logger.debug { "Completed task ${it.id} by $it.assignee" } } + ) } private fun delete(command: DeleteTaskCommand) = @@ -362,7 +360,8 @@ class TaskAggregate() { followUpDate = this.followUpDate, deleteReason = command.deleteReason - )) + ).also { logger.debug { "Deleted task ${it.id} with reason ${it.deleteReason}" } } + ) private fun updateAttributes(command: UpdateAttributeTaskCommand) { AggregateLifecycle.apply( From 9f91d6baf30c072f3a9918441cb34916d00786de Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Thu, 18 Mar 2021 11:17:52 +0100 Subject: [PATCH 14/16] update dependencies, fix mongodb problems --- engine/camunda-engine-client/pom.xml | 1 - .../test/kotlin/process/ProcessStarterTest.kt | 15 +- .../test/kotlin/task/TaskEventHandlerTest.kt | 15 +- engine/taskpool-collector/pom.xml | 12 +- .../HistoricVariableInstanceExtensions.kt | 78 ++++++ .../ProcessVariableEventCollectorService.kt | 24 +- engine/variable-serializer/pom.xml | 12 +- .../src/test/kotlin/VariableSerializerTest.kt | 2 +- .../cockpit-application/backend/pom.xml | 5 + .../backend/src/main/api/swagger.yml | 5 +- .../rest/mapper/TaskEventMapperTest.kt | 9 +- .../src/main/resources/application.yml | 4 +- .../src/main/resources/application-mongo.yml | 2 +- pom.xml | 235 +++++++++--------- .../definition/TaskEventEventUpcasters.kt | 2 +- view/mongo/pom.xml | 19 +- .../view/mongo/EnableTaskPoolMongoView.kt | 5 - .../mongo/TaskPoolMongoViewConfiguration.kt | 27 +- .../mongo/service/TaskPoolMongoService.kt | 8 +- .../service/TaskPoolMongoServiceITest.kt | 11 +- .../service/TaskPoolMongoServiceRetryTest.kt | 15 +- .../view/mongo/utils/MongoLauncher.kt | 17 +- view/simple/pom.xml | 13 +- 23 files changed, 299 insertions(+), 237 deletions(-) diff --git a/engine/camunda-engine-client/pom.xml b/engine/camunda-engine-client/pom.xml index e8d6d9938..8b3947cf4 100644 --- a/engine/camunda-engine-client/pom.xml +++ b/engine/camunda-engine-client/pom.xml @@ -43,6 +43,5 @@ camunda-bpm-mockito - diff --git a/engine/camunda-engine-client/src/test/kotlin/process/ProcessStarterTest.kt b/engine/camunda-engine-client/src/test/kotlin/process/ProcessStarterTest.kt index 91608f70d..25069ab34 100644 --- a/engine/camunda-engine-client/src/test/kotlin/process/ProcessStarterTest.kt +++ b/engine/camunda-engine-client/src/test/kotlin/process/ProcessStarterTest.kt @@ -9,25 +9,22 @@ import org.camunda.bpm.engine.RuntimeService import org.camunda.bpm.engine.variable.Variables import org.camunda.bpm.engine.variable.Variables.stringValue import org.camunda.bpm.extension.mockito.process.ProcessInstanceFake -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith import org.mockito.Mock -import org.mockito.junit.MockitoJUnit -import org.mockito.junit.MockitoRule +import org.mockito.junit.jupiter.MockitoExtension +@ExtendWith(MockitoExtension::class) class ProcessStarterTest { - @get: Rule - val mockitoRule: MockitoRule = MockitoJUnit.rule() - @Mock private lateinit var runtimeService: RuntimeService private lateinit var processStarter: ProcessStarter - @Before + @BeforeEach fun init() { processStarter = ProcessStarter(runtimeService) } diff --git a/engine/camunda-engine-client/src/test/kotlin/task/TaskEventHandlerTest.kt b/engine/camunda-engine-client/src/test/kotlin/task/TaskEventHandlerTest.kt index 3405fb099..42f815cd3 100644 --- a/engine/camunda-engine-client/src/test/kotlin/task/TaskEventHandlerTest.kt +++ b/engine/camunda-engine-client/src/test/kotlin/task/TaskEventHandlerTest.kt @@ -8,19 +8,16 @@ import io.holunda.camunda.taskpool.api.task.* import org.camunda.bpm.engine.TaskService import org.camunda.bpm.extension.mockito.QueryMocks import org.camunda.bpm.extension.mockito.task.TaskFake -import org.junit.Before -import org.junit.Rule -import org.junit.Test +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.extension.ExtendWith import org.mockito.Mock -import org.mockito.junit.MockitoJUnit -import org.mockito.junit.MockitoRule +import org.mockito.junit.jupiter.MockitoExtension import java.util.* +@ExtendWith(MockitoExtension::class) class TaskEventHandlerTest { - @get: Rule - val mockitoRule: MockitoRule = MockitoJUnit.rule() - private val taskCollectorProperties = TaskCollectorProperties(applicationName = "myApplication") private val processReference = ProcessReference( instanceId = UUID.randomUUID().toString(), @@ -37,7 +34,7 @@ class TaskEventHandlerTest { private lateinit var taskEventHandlers: TaskEventHandlers private lateinit var now: Date - @Before + @BeforeEach fun init() { taskEventHandlers = TaskEventHandlers(taskService, taskCollectorProperties) now = Date() diff --git a/engine/taskpool-collector/pom.xml b/engine/taskpool-collector/pom.xml index 60ceb85d3..fb9a5d518 100755 --- a/engine/taskpool-collector/pom.xml +++ b/engine/taskpool-collector/pom.xml @@ -54,26 +54,21 @@ org.springframework spring-tx - ${spring-framework.version} - org.slf4j slf4j-api + org.springframework.boot spring-boot-starter-test test - - - junit - junit - org.camunda.bpm.extension.mockito camunda-bpm-mockito + test org.camunda.bpm.springboot @@ -96,14 +91,17 @@ org.camunda.bpm.assert camunda-bpm-assert + test org.assertj assertj-core + test org.awaitility awaitility + test diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/HistoricVariableInstanceExtensions.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/HistoricVariableInstanceExtensions.kt index 42a1eaa54..03c108d31 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/HistoricVariableInstanceExtensions.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/HistoricVariableInstanceExtensions.kt @@ -1,2 +1,80 @@ package io.holunda.camunda.taskpool.collector +import io.holunda.camunda.taskpool.api.task.CaseReference +import io.holunda.camunda.taskpool.api.task.ProcessReference +import io.holunda.camunda.taskpool.api.task.SourceReference +import org.camunda.bpm.engine.RepositoryService +import org.camunda.bpm.engine.impl.history.event.HistoricVariableUpdateEventEntity +import org.camunda.bpm.engine.repository.CaseDefinition +import org.camunda.bpm.engine.repository.ProcessDefinition + +/** + * Extracts source reference out of historic variable event. + */ +fun HistoricVariableUpdateEventEntity.sourceReference(repositoryService: RepositoryService, applicationName: String): SourceReference = + when { + this.processDefinitionId != null -> ProcessReference( + definitionId = this.processDefinitionId, + instanceId = this.processInstanceId, + executionId = this.executionId, + definitionKey = this.processDefinitionKey, + name = this.processName(repositoryService), + applicationName = applicationName, + tenantId = this.tenantId + ) + this.caseDefinitionId != null -> CaseReference( + definitionId = this.caseDefinitionId, + instanceId = this.caseInstanceId, + executionId = this.caseExecutionId, + definitionKey = this.caseDefinitionKey, + name = this.caseName(repositoryService), + applicationName = applicationName, + tenantId = this.tenantId + ) + else -> throw IllegalArgumentException("No source reference found.") + } + +/** + * Retrieves case definition key from event. + * @param repositoryService to resolve definition + */ +fun HistoricVariableUpdateEventEntity.caseDefinitionKey(repositoryService: RepositoryService): String = caseDefinition(repositoryService).key + +/** + * Retrieves case name from event. If the case name is not set, fall back to key. + * @param repositoryService to resolve definition. + */ +fun HistoricVariableUpdateEventEntity.caseName(repositoryService: RepositoryService): String = caseDefinition(repositoryService).name + ?: caseDefinitionKey(repositoryService) + +/** + * Retrieves process definition key from event. + * @param repositoryService to resolve definition + */ +fun HistoricVariableUpdateEventEntity.processDefinitionKey(repositoryService: RepositoryService): String = processDefinition(repositoryService).key + +/** + * Retrieves process name from event. If the process name is not set, fall back to key. + * @param repositoryService to resolve definition + */ +fun HistoricVariableUpdateEventEntity.processName(repositoryService: RepositoryService): String = processDefinition(repositoryService).name + ?: processDefinitionKey(repositoryService) + +/** + * Retrieves case definition from event. + * @param repositoryService to resolve definition + */ +fun HistoricVariableUpdateEventEntity.caseDefinition(repositoryService: RepositoryService): CaseDefinition = repositoryService + .createCaseDefinitionQuery().caseDefinitionId(caseDefinitionId) + .singleResult() + ?: throw IllegalArgumentException("Case definition could not be resolved for id $caseDefinitionId") + +/** + * Retrieves process definition from event. + * @param repositoryService to resolve definition + */ +fun HistoricVariableUpdateEventEntity.processDefinition(repositoryService: RepositoryService): ProcessDefinition = repositoryService + .createProcessDefinitionQuery().processDefinitionId(processDefinitionId) + .singleResult() + ?: throw IllegalArgumentException("Process definition could not be resolved for id $processDefinitionId") + diff --git a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/variable/ProcessVariableEventCollectorService.kt b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/variable/ProcessVariableEventCollectorService.kt index ca03609e4..e0f04ad56 100644 --- a/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/variable/ProcessVariableEventCollectorService.kt +++ b/engine/taskpool-collector/src/main/kotlin/io/holunda/camunda/taskpool/collector/variable/ProcessVariableEventCollectorService.kt @@ -1,6 +1,7 @@ package io.holunda.camunda.taskpool.collector.variable import io.holunda.camunda.taskpool.TaskCollectorProperties +import io.holunda.camunda.taskpool.collector.sourceReference import mu.KLogging import org.camunda.bpm.engine.RepositoryService import org.camunda.bpm.engine.impl.history.event.HistoricVariableUpdateEventEntity @@ -39,7 +40,18 @@ class ProcessVariableEventCollectorService( @Order(ORDER) @EventListener(condition = "#variableEvent.eventType.equals('create')") fun create(variableEvent: HistoricVariableUpdateEventEntity) { - logger.debug { "Created variable $variableEvent" } + val sourceReference = variableEvent.sourceReference(repositoryService, collectorProperties.applicationName) + logger.debug { "Created variable ${variableEvent.variableName} for source ref: $sourceReference" } + } + + /** + * Fires update process variable command. + * See [HistoryEventTypes.VARIABLE_INSTANCE_UPDATE] + */ + @Order(ORDER) + @EventListener(condition = "#variableEvent.eventType.equals('update')") + fun update(variableEvent: HistoricVariableUpdateEventEntity) { + logger.debug { "Update variable $variableEvent" } } /** @@ -62,16 +74,6 @@ class ProcessVariableEventCollectorService( logger.debug { "Created variable $variableEvent" } } - /** - * Fires update process variable command. - * See [HistoryEventTypes.VARIABLE_INSTANCE_UPDATE] - */ - @Order(ORDER) - @EventListener(condition = "#variableEvent.eventType.equals('update')") - fun update(variableEvent: HistoricVariableUpdateEventEntity) { - logger.debug { "Update variable $variableEvent" } - } - /** * Fires migrate process variable command. * See [HistoryEventTypes.VARIABLE_INSTANCE_MIGRATE] diff --git a/engine/variable-serializer/pom.xml b/engine/variable-serializer/pom.xml index e18875cb7..c0efbad6b 100755 --- a/engine/variable-serializer/pom.xml +++ b/engine/variable-serializer/pom.xml @@ -33,18 +33,20 @@ org.slf4j slf4j-api + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + test + junit junit + test - org.assertj assertj-core - - - com.fasterxml.jackson.datatype - jackson-datatype-jsr310 test diff --git a/engine/variable-serializer/src/test/kotlin/VariableSerializerTest.kt b/engine/variable-serializer/src/test/kotlin/VariableSerializerTest.kt index 051d4c624..e33cee18d 100755 --- a/engine/variable-serializer/src/test/kotlin/VariableSerializerTest.kt +++ b/engine/variable-serializer/src/test/kotlin/VariableSerializerTest.kt @@ -68,7 +68,7 @@ class SimpleDataEntryCommandSenderTest { val result = serialize(pojo, mapper) assertThat(result[Pojo4::key.name]).isEqualTo(pojo.key) - assertThat(result[Pojo4::anotherKey.name] as List<*>).containsOnlyElementsOf(pojo.anotherKey) + assertThat(result[Pojo4::anotherKey.name] as List<*>).containsExactlyElementsOf(pojo.anotherKey) } @Test diff --git a/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml b/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml index 2aceeb524..8f21bf09c 100755 --- a/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml +++ b/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml @@ -47,6 +47,11 @@ swagger-annotations 1.5.20 + + + org.springframework.boot + spring-boot-starter-validation + com.fasterxml.jackson.datatype diff --git a/examples/scenarios/distributed-axon-server/cockpit-application/backend/src/main/api/swagger.yml b/examples/scenarios/distributed-axon-server/cockpit-application/backend/src/main/api/swagger.yml index de6847837..26e4f11f2 100644 --- a/examples/scenarios/distributed-axon-server/cockpit-application/backend/src/main/api/swagger.yml +++ b/examples/scenarios/distributed-axon-server/cockpit-application/backend/src/main/api/swagger.yml @@ -4,6 +4,7 @@ info: version: 0.0.1 description: API for the cockpit. basePath: '/taskpool-cockpit/rest' +host: localhost tags: - name: Task Event description: Operations on tasks and task events. @@ -30,6 +31,9 @@ paths: type: string description: Command, currently only delete is supported. required: true + responses: + '204': + description: Sucessful operation. '/task-events': get: tags: @@ -38,7 +42,6 @@ paths: produces: - application/json operationId: getTaskEvents - parameters: responses: '200': description: Successful operation. diff --git a/examples/scenarios/distributed-axon-server/cockpit-application/backend/src/test/kotlin/io/holunda/camunda/taskpool/cockpit/rest/mapper/TaskEventMapperTest.kt b/examples/scenarios/distributed-axon-server/cockpit-application/backend/src/test/kotlin/io/holunda/camunda/taskpool/cockpit/rest/mapper/TaskEventMapperTest.kt index 12fac66d8..80cff296a 100644 --- a/examples/scenarios/distributed-axon-server/cockpit-application/backend/src/test/kotlin/io/holunda/camunda/taskpool/cockpit/rest/mapper/TaskEventMapperTest.kt +++ b/examples/scenarios/distributed-axon-server/cockpit-application/backend/src/test/kotlin/io/holunda/camunda/taskpool/cockpit/rest/mapper/TaskEventMapperTest.kt @@ -5,24 +5,21 @@ import io.holunda.camunda.taskpool.api.task.TaskCreatedEngineEvent import io.holunda.camunda.taskpool.cockpit.service.TaskEventWithMetaData import org.assertj.core.api.Assertions.assertThat import org.axonframework.messaging.MetaData -import org.junit.Before -import org.junit.Test -import org.mockito.Mockito.spy +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test import java.time.Instant class TaskEventMapperTest { private lateinit var taskEventMapper: TaskEventMapper - @Before + @BeforeEach fun init() { taskEventMapper = TaskEventMapperImpl() } @Test fun `should map the instant`() { - taskEventMapper = spy(TaskEventMapperImpl::class.java) - val now = Instant.now() val event = TaskCreatedEngineEvent( id = "4711", diff --git a/examples/scenarios/distributed-axon-server/process-application/src/main/resources/application.yml b/examples/scenarios/distributed-axon-server/process-application/src/main/resources/application.yml index 97f2ab588..23f4bdedb 100644 --- a/examples/scenarios/distributed-axon-server/process-application/src/main/resources/application.yml +++ b/examples/scenarios/distributed-axon-server/process-application/src/main/resources/application.yml @@ -48,7 +48,7 @@ camunda: task: enabled: true enricher: - type: processVariablesSimpleDataEntryCommandSenderTest + type: processVariables sender: type: tx process-definition: @@ -58,7 +58,7 @@ camunda: dataentry: sender: enabled: true - type: simpleSimpleDataEntryCommandSenderTest + type: simple applicationName: ${spring.application.name} # default form-url-resolver: defaultTaskTemplate: "/tasks/${formKey}/${id}?userId=%userId%" diff --git a/examples/scenarios/distributed-axon-server/taskpool-application/src/main/resources/application-mongo.yml b/examples/scenarios/distributed-axon-server/taskpool-application/src/main/resources/application-mongo.yml index c0d1d8314..70938b9f4 100644 --- a/examples/scenarios/distributed-axon-server/taskpool-application/src/main/resources/application-mongo.yml +++ b/examples/scenarios/distributed-axon-server/taskpool-application/src/main/resources/application-mongo.yml @@ -1,9 +1,9 @@ spring: data: mongodb: - database: tasks-payload host: localhost port: 27017 + database: tasks-payload logging.level.io.holunda.camunda.taskpool: view.mongo: INFO diff --git a/pom.xml b/pom.xml index 2a386e5ba..d465bd303 100644 --- a/pom.xml +++ b/pom.xml @@ -28,33 +28,34 @@ false Use the system property: -Dcamunda-ee to enable EE --> - 7.13.0 - 7.13.0-ee + 7.14.0 + 7.14.1-ee ${camunda-ce.version} - 6.0.0 + 8.0.0 4.13.0 - 1.0.2 - 1.9.0 + 1.2.0 + 1.10.0 - 2.2.9.RELEASE - 5.2.8.RELEASE - 3.3.8.RELEASE + 2.4.3 + 1.1.3 - 4.4.3 + 4.4.7 0.1.0 0.0.4 - 1.4.10 + + 1.4.20 ${java.version} true 2.0.3 0.3.0 - 1.4.0.Final + 1.4.2.Final - 2.23.4 2.2.0 3.1.5 + + 0.18.0 @@ -164,12 +165,7 @@ pom - - org.camunda.bpm.springboot - camunda-bpm-spring-boot-starter - ${camunda-springboot.version} - - + io.holunda.data camunda-bpm-data @@ -183,26 +179,28 @@ ${org.mapstruct.version} + + + io.projectreactor.kotlin + reactor-kotlin-extensions + ${reactor-kotlin-extensions.version} + + + - org.axonframework axon-messaging ${axon.version} - - org.axonframework.extensions.kotlin - axon-kotlin - ${axon-kotlin.version} - org.axonframework - axon-spring + axon-eventsourcing ${axon.version} org.axonframework - axon-eventsourcing + axon-modelling ${axon.version} @@ -210,7 +208,6 @@ axon-configuration ${axon.version} - org.axonframework axon-spring-boot-starter @@ -218,10 +215,15 @@ org.axonframework - axon-modelling + axon-spring ${axon.version} + + org.axonframework.extensions.kotlin + axon-kotlin + ${axon-kotlin.version} + io.holixon axon-gateway-extension @@ -248,30 +250,6 @@ - - junit - junit - 4.13.1 - test - - - org.mockito - mockito-core - ${mockito.version} - test - - - org.mockito - mockito-inline - ${mockito.version} - test - - - org.axonframework - axon-test - ${axon.version} - test - org.jetbrains.kotlin kotlin-test @@ -302,6 +280,11 @@ ${springboot.version} test + + org.axonframework + axon-test + ${axon.version} + org.camunda.bpm.extension.mockito camunda-bpm-mockito @@ -320,6 +303,25 @@ ${awaitability.version} test + + com.tngtech.jgiven + jgiven-junit + ${jgiven.version} + test + + + com.tngtech.jgiven + jgiven-spring + ${jgiven.version} + test + + + com.tngtech.jgiven + jgiven-html5-report + ${jgiven.version} + test + +
@@ -343,6 +345,11 @@ kotlin-test test + + org.junit.vintage + junit-vintage-engine + test + @@ -682,11 +689,15 @@ maven-surefire-plugin - 2.22.2 + 3.0.0-M5 + + + org.junit.vintage + junit-vintage-engine + 5.7.1 + + - false random @@ -695,11 +706,7 @@ - - -Djava.awt.headless=true - ${surefireArgLine} - -XX:+StartAttachListener - + -Djava.awt.headless=true ${surefireArgLine} -XX:+StartAttachListener ${project.build.directory}/jgiven-reports @@ -709,11 +716,23 @@ org.apache.maven.plugins maven-failsafe-plugin - 2.22.2 + 3.0.0-M4 + + + + integration-test + + + - + false + + ${pattern.class.itest} + ${pattern.package.itest} + + + + -Djava.awt.headless=true ${failsafeArgLine} -XX:+StartAttachListener @@ -743,7 +762,7 @@ org.jetbrains.dokka dokka-maven-plugin - 1.4.10 + 1.4.20 test @@ -859,7 +878,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 1.4.2.jenkins-1 + 3.0.0-M3 enforce-maven @@ -871,6 +890,9 @@ 3.6.0 + + 11 + @@ -924,24 +946,6 @@ org.apache.maven.plugins maven-failsafe-plugin - - - - integration-test - - - - - - ${pattern.class.itest} - ${pattern.package.itest} - - - - - -Djava.awt.headless=true ${failsafeArgLine} - - @@ -1075,6 +1079,16 @@ docs + + + jcenter + JCenter + https://jcenter.bintray.com/ + + true + + + @@ -1121,31 +1135,6 @@ - - - - jcenter - JCenter - https://jcenter.bintray.com/ - - true - - - - - - - jfrog-snapshots - JFrog - - false - - - true - - http://oss.jfrog.org/artifactory/oss-snapshot-local/ - - zambrovski @@ -1161,19 +1150,6 @@ Holisticon AG http://www.holisticon.de - - dthuesen - Detlef von Thuesen - dthuesen@gmx.de - Holisticon AG - http://www.holisticon.de - - - bignesta - Christoph Wolff - Holisticon AG - http://www.holisticon.de - lbilger Lars Bilger @@ -1185,5 +1161,18 @@ HBT GmbH https://www.hbt.de/ + + bignesta + Christoph Wolff + Holisticon AG + http://www.holisticon.de + + + dthuesen + Detlef von Thuesen + dthuesen@gmx.de + Holisticon AG + http://www.holisticon.de + diff --git a/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/upcast/definition/TaskEventEventUpcasters.kt b/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/upcast/definition/TaskEventEventUpcasters.kt index f8cfae67e..bcbd55d5e 100644 --- a/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/upcast/definition/TaskEventEventUpcasters.kt +++ b/taskpool/taskpool-event/src/main/kotlin/io/holunda/camunda/taskpool/upcast/definition/TaskEventEventUpcasters.kt @@ -180,7 +180,7 @@ abstract class AbstractSourceReferenceElementRemovingUpcaster : AnnotationBasedS abstract fun getType(): String private fun removeWrongElement(document: Document, tagName: String) { - val nodes = document.selectNodes("//" + tagName + "[@defined-in='io.holunda.camunda.taskpool.api.task.SourceReference']") + val nodes = document.selectNodes("//${tagName}[@defined-in='io.holunda.camunda.taskpool.api.task.SourceReference']") nodes.forEach { it.parent.remove(it) } diff --git a/view/mongo/pom.xml b/view/mongo/pom.xml index 13fef9b76..324bef147 100755 --- a/view/mongo/pom.xml +++ b/view/mongo/pom.xml @@ -13,8 +13,7 @@ view/${project.artifactId} - 0.17.0 - 4.2 + 4.4 @@ -31,7 +30,6 @@ axon-mongo ${axon-mongo.version} - org.axonframework axon-messaging @@ -40,41 +38,39 @@ org.axonframework axon-configuration - io.projectreactor reactor-core - ${project-reactor.version} + + + io.projectreactor.kotlin + reactor-kotlin-extensions + org.springframework.boot spring-boot-starter-test + test - de.flapdoodle.embed de.flapdoodle.embed.mongo - 2.2.0 test - com.tngtech.jgiven jgiven-junit - ${jgiven.version} test com.tngtech.jgiven jgiven-spring - ${jgiven.version} test com.tngtech.jgiven jgiven-html5-report - ${jgiven.version} test @@ -90,7 +86,6 @@ io.projectreactor reactor-test - ${project-reactor.version} test diff --git a/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/EnableTaskPoolMongoView.kt b/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/EnableTaskPoolMongoView.kt index ab2ae8b5d..41ff81273 100755 --- a/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/EnableTaskPoolMongoView.kt +++ b/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/EnableTaskPoolMongoView.kt @@ -1,10 +1,5 @@ package io.holunda.camunda.taskpool.view.mongo -import org.springframework.boot.autoconfigure.ImportAutoConfiguration -import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration -import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration -import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration -import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration import org.springframework.context.annotation.Import /** diff --git a/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/TaskPoolMongoViewConfiguration.kt b/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/TaskPoolMongoViewConfiguration.kt index 595a23f5f..773b57d68 100644 --- a/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/TaskPoolMongoViewConfiguration.kt +++ b/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/TaskPoolMongoViewConfiguration.kt @@ -1,6 +1,6 @@ package io.holunda.camunda.taskpool.view.mongo -import com.mongodb.MongoClient +import com.mongodb.client.MongoClient import io.holunda.camunda.taskpool.view.mongo.repository.CaseReferenceDocument import io.holunda.camunda.taskpool.view.mongo.repository.ProcessReferenceDocument import io.holunda.camunda.taskpool.view.mongo.repository.ReferenceDocument @@ -16,20 +16,22 @@ import org.springframework.context.annotation.Bean import org.springframework.context.annotation.ComponentScan import org.springframework.context.annotation.Configuration import org.springframework.data.convert.ConfigurableTypeInformationMapper -import org.springframework.data.mongodb.MongoDbFactory -import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver +import org.springframework.data.mongodb.MongoDatabaseFactory +import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper import org.springframework.data.mongodb.core.convert.DefaultMongoTypeMapper.DEFAULT_TYPE_KEY import org.springframework.data.mongodb.core.convert.MappingMongoConverter +import org.springframework.data.mongodb.core.convert.MongoCustomConversions import org.springframework.data.mongodb.core.mapping.MongoMappingContext import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories import javax.annotation.PostConstruct + @Configuration @ComponentScan @EnableReactiveMongoRepositories @EnableConfigurationProperties(TaskPoolMongoViewProperties::class) -class TaskPoolMongoViewConfiguration { +class TaskPoolMongoViewConfiguration : AbstractMongoClientConfiguration() { companion object : KLogging() @@ -42,10 +44,10 @@ class TaskPoolMongoViewConfiguration { } @Bean - fun configureAxonMongoTemplate(mongoClient: MongoClient): MongoTemplate = + fun configureAxonMongoTemplate(): MongoTemplate = DefaultMongoTemplate .builder() - .mongoDatabase(mongoClient, mongoDatabaseName) + .mongoDatabase(mongoClient(), mongoDatabaseName) .trackingTokensCollectionName("tracking-tokens") // these collections are configured, but not used on the client side. .domainEventsCollectionName("domain-events") @@ -54,7 +56,7 @@ class TaskPoolMongoViewConfiguration { .build() @Bean - fun configure(mongoTemplate: MongoTemplate): TokenStore = + fun configureAxonMongoTokenStore(mongoTemplate: MongoTemplate): TokenStore = MongoTokenStore .builder() .mongoTemplate(mongoTemplate) @@ -62,11 +64,9 @@ class TaskPoolMongoViewConfiguration { .build() @Bean - fun mongoConverter(mongoFactory: MongoDbFactory) = MappingMongoConverter( - DefaultDbRefResolver(mongoFactory), - MongoMappingContext() - ) - .apply { + override fun mappingMongoConverter(mongoDatabaseFactory: MongoDatabaseFactory, customConversions: MongoCustomConversions, mappingContext: MongoMappingContext): MappingMongoConverter { + val mmc = super.mappingMongoConverter(mongoDatabaseFactory, customConversions, mappingContext) + mmc.apply { this.typeMapper = DefaultMongoTypeMapper(DEFAULT_TYPE_KEY, listOf( // register type aliases for source references. ConfigurableTypeInformationMapper( @@ -79,5 +79,8 @@ class TaskPoolMongoViewConfiguration { // replace "." with ":" (relevant for correlation) this.setMapKeyDotReplacement(":") } + return mmc + } + override fun getDatabaseName(): String = this.mongoDatabaseName } diff --git a/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoService.kt b/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoService.kt index fa5688c85..e114b0aee 100755 --- a/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoService.kt +++ b/view/mongo/src/main/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoService.kt @@ -11,8 +11,6 @@ import io.holunda.camunda.taskpool.view.mongo.ChangeTrackingMode import io.holunda.camunda.taskpool.view.mongo.TaskPoolMongoViewProperties import io.holunda.camunda.taskpool.view.mongo.repository.* import io.holunda.camunda.taskpool.view.query.FilterQuery -import io.holunda.camunda.taskpool.view.query.data.ReactiveDataEntryApi -import io.holunda.camunda.taskpool.view.query.task.ReactiveTaskApi import io.holunda.camunda.taskpool.view.query.data.* import io.holunda.camunda.taskpool.view.query.task.* import io.holunda.camunda.taskpool.view.task @@ -31,7 +29,8 @@ import org.springframework.data.domain.Sort import org.springframework.stereotype.Component import reactor.core.Disposable import reactor.core.publisher.Mono -import reactor.core.publisher.switchIfEmpty +import reactor.kotlin.core.publisher.switchIfEmpty +import reactor.util.retry.Retry import java.time.Duration import java.util.concurrent.CompletableFuture import javax.annotation.PostConstruct @@ -375,8 +374,7 @@ class TaskPoolMongoService( this.switchIfEmpty { logger.debug { "${logMessage()}, but will retry." } Mono.error(TaskNotFoundException()) - } - .retryBackoff(numRetries, firstBackoff) + }.retryWhen(Retry.backoff(numRetries, firstBackoff)) .onErrorMap { if (it is IllegalStateException && it.cause is TaskNotFoundException) it.cause else it } .onErrorResume(TaskNotFoundException::class.java) { logger.warn { "${logMessage()} and retries are exhausted." } diff --git a/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoServiceITest.kt b/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoServiceITest.kt index 9d9aabb9d..b19d063f2 100755 --- a/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoServiceITest.kt +++ b/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoServiceITest.kt @@ -9,14 +9,13 @@ import io.holunda.camunda.taskpool.view.TaskWithDataEntries import io.holunda.camunda.taskpool.view.auth.User import io.holunda.camunda.taskpool.view.mongo.TaskpoolMongoTestApplication import io.holunda.camunda.taskpool.view.mongo.utils.MongoLauncher -import io.holunda.camunda.taskpool.view.query.task.ApplicationWithTaskCount -import io.holunda.camunda.taskpool.view.query.task.TaskCountByApplicationQuery -import io.holunda.camunda.taskpool.view.query.task.TaskQueryResult -import io.holunda.camunda.taskpool.view.query.task.TasksForUserQuery -import io.holunda.camunda.taskpool.view.query.task.TasksWithDataEntriesForUserQuery +import io.holunda.camunda.taskpool.view.query.task.* import org.camunda.bpm.engine.variable.VariableMap import org.camunda.bpm.engine.variable.Variables -import org.junit.* +import org.junit.After +import org.junit.AfterClass +import org.junit.BeforeClass +import org.junit.Test import org.springframework.boot.test.context.SpringBootTest import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ActiveProfiles diff --git a/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoServiceRetryTest.kt b/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoServiceRetryTest.kt index 6dd0f53ef..83ade4675 100644 --- a/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoServiceRetryTest.kt +++ b/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/service/TaskPoolMongoServiceRetryTest.kt @@ -18,13 +18,14 @@ class TaskPoolMongoServiceRetryTest { private val taskRepository: TaskRepository = mock() private val taskPoolMongoService: TaskPoolMongoService = TaskPoolMongoService( - TaskPoolMongoViewProperties(changeTrackingMode = ChangeTrackingMode.CHANGE_STREAM), - taskRepository, - mock(), - mock(), - mock(), - mock(), - mock()) + properties = TaskPoolMongoViewProperties(changeTrackingMode = ChangeTrackingMode.CHANGE_STREAM), + taskRepository = taskRepository, + dataEntryRepository = mock(), + taskWithDataEntriesRepository = mock(), + taskChangeTracker = mock(), + queryUpdateEmitter = mock(), + configuration = mock() + ) private val taskId = "some-id" diff --git a/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/utils/MongoLauncher.kt b/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/utils/MongoLauncher.kt index 04f3d93f5..38bf5ecd6 100644 --- a/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/utils/MongoLauncher.kt +++ b/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/utils/MongoLauncher.kt @@ -1,7 +1,7 @@ package io.holunda.camunda.taskpool.view.mongo.utils import com.mongodb.* -import com.mongodb.client.MongoDatabase +import com.mongodb.client.MongoClients import de.flapdoodle.embed.mongo.Command import de.flapdoodle.embed.mongo.MongodExecutable import de.flapdoodle.embed.mongo.MongodProcess @@ -104,9 +104,11 @@ object MongoLauncher { this.mongod = mongoExecutable!!.start() if (asReplicaSet) { - MongoClient( - ServerAddress(LOCALHOST, MONGO_DEFAULT_PORT), - MongoClientOptions.builder() + // ServerAddress(LOCALHOST, MONGO_DEFAULT_PORT), + MongoClients.create( + MongoClientSettings + .builder() + .applyConnectionString(ConnectionString("mongodb://$LOCALHOST:$MONGO_DEFAULT_PORT")) .readPreference(ReadPreference.nearest()) .writeConcern(WriteConcern.W2) .build() @@ -115,7 +117,7 @@ object MongoLauncher { val config = Document(mapOf("_id" to "repembedded", "members" to BasicDBList().apply { - add(Document("_id", 0).append("host", "${LOCALHOST}:${MONGO_DEFAULT_PORT}")) + add(Document("_id", 0).append("host", "$LOCALHOST:$MONGO_DEFAULT_PORT")) })) logger.info { "MongoDB Replica Config: $config" } @@ -136,8 +138,9 @@ object MongoLauncher { * Clear client and db. */ fun clear() { - MongoClient(LOCALHOST, MONGO_DEFAULT_PORT).use { - it.dropDatabase(databaseName) + MongoClients.create("mongodb://$LOCALHOST:$MONGO_DEFAULT_PORT").use { + val database = it.getDatabase(databaseName) + database.drop() } } diff --git a/view/simple/pom.xml b/view/simple/pom.xml index 662367538..c470808d0 100755 --- a/view/simple/pom.xml +++ b/view/simple/pom.xml @@ -20,7 +20,6 @@ io.holunda.taskpool camunda-bpm-taskpool-view-api - org.axonframework axon-messaging @@ -29,7 +28,6 @@ org.axonframework axon-configuration - org.springframework.boot spring-boot-starter @@ -37,9 +35,14 @@ io.projectreactor reactor-core - ${project-reactor.version} + + io.projectreactor.kotlin + reactor-kotlin-extensions + + + org.springframework.boot spring-boot-starter-test @@ -47,21 +50,19 @@ com.tngtech.jgiven jgiven-junit - ${jgiven.version} test com.tngtech.jgiven jgiven-spring - ${jgiven.version} test com.tngtech.jgiven jgiven-html5-report - ${jgiven.version} test + From 8b44754d6a24ee71dc81fc551cd8fcf3cd17ed59 Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Thu, 18 Mar 2021 12:29:22 +0100 Subject: [PATCH 15/16] fix mongo test bug, fix #295 --- pom.xml | 52 +++---------------- .../view/mongo/utils/MongoLauncher.kt | 3 +- 2 files changed, 8 insertions(+), 47 deletions(-) diff --git a/pom.xml b/pom.xml index d465bd303..b5ce2adb9 100644 --- a/pom.xml +++ b/pom.xml @@ -43,7 +43,6 @@ 0.1.0 0.0.4 - 1.4.20 ${java.version} true @@ -101,7 +100,6 @@ camunda-bpm-taskpool-variable-serializer ${project.version} - io.holunda.taskpool camunda-bpm-datapool-api @@ -188,6 +186,7 @@ + org.axonframework axon-messaging @@ -250,12 +249,6 @@ - - org.jetbrains.kotlin - kotlin-test - ${kotlin.version} - test - org.jetbrains.kotlin kotlin-test-junit @@ -322,7 +315,6 @@ test - @@ -342,7 +334,7 @@ org.jetbrains.kotlin - kotlin-test + kotlin-test-junit test @@ -364,6 +356,7 @@ + io.swagger swagger-codegen-maven-plugin @@ -399,29 +392,16 @@ jacoco-maven-plugin 0.8.6 - pre-unit-test prepare-agent - ${project.build.directory}/coverage-reports/jacoco-ut.exec - surefireArgLine - post-unit-test test @@ -429,9 +409,7 @@ report - ${project.build.directory}/coverage-reports/jacoco-ut.exec - ${project.reporting.outputDirectory}/jacoco-ut ${pattern.package.itest} @@ -439,11 +417,6 @@ - - pre-integration-test pre-integration-test @@ -451,19 +424,10 @@ prepare-agent - ${project.build.directory}/coverage-reports/jacoco-it.exec - failsafeArgLine - post-integration-test post-integration-test @@ -471,9 +435,7 @@ report - ${project.build.directory}/coverage-reports/jacoco-it.exec - ${project.reporting.outputDirectory}/jacoco-it ${pattern.package.itest} @@ -598,7 +560,7 @@ com.github.eirslett frontend-maven-plugin - 1.8.0 + 1.10.0 @@ -681,7 +643,7 @@ org.codehaus.mojo versions-maven-plugin - 2.7 + 2.8.1 false @@ -740,7 +702,7 @@ com.amashchenko.maven.plugin gitflow-maven-plugin - 1.14.0 + 1.15.1 master @@ -798,7 +760,7 @@ org.apache.maven.plugins maven-source-plugin - 3.2.0 + 3.2.1 attach-sources diff --git a/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/utils/MongoLauncher.kt b/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/utils/MongoLauncher.kt index 38bf5ecd6..ea85ce999 100644 --- a/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/utils/MongoLauncher.kt +++ b/view/mongo/src/test/kotlin/io/holunda/camunda/taskpool/view/mongo/utils/MongoLauncher.kt @@ -104,11 +104,10 @@ object MongoLauncher { this.mongod = mongoExecutable!!.start() if (asReplicaSet) { - // ServerAddress(LOCALHOST, MONGO_DEFAULT_PORT), MongoClients.create( MongoClientSettings .builder() - .applyConnectionString(ConnectionString("mongodb://$LOCALHOST:$MONGO_DEFAULT_PORT")) + .applyConnectionString(ConnectionString("mongodb://$LOCALHOST:$MONGO_DEFAULT_PORT/?replicaSet=repembedded")) .readPreference(ReadPreference.nearest()) .writeConcern(WriteConcern.W2) .build() From 38145aa0e6a498037f7b9cdb6f41aad4fa5a25ed Mon Sep 17 00:00:00 2001 From: Simon Zambrovski Date: Fri, 19 Mar 2021 00:48:11 +0100 Subject: [PATCH 16/16] Update for next development version --- bom/datapool-dependencies/pom.xml | 2 +- bom/taskpool-dependencies/pom.xml | 4 ++-- datapool/datapool-api/pom.xml | 2 +- datapool/datapool-core/pom.xml | 2 +- datapool/datapool-event/pom.xml | 2 +- datapool/pom.xml | 2 +- docs/pom.xml | 2 +- engine/camunda-engine-client/pom.xml | 2 +- engine/datapool-collector/pom.xml | 2 +- engine/pom.xml | 2 +- engine/property-taskurl-resolver/pom.xml | 2 +- engine/taskpool-collector/pom.xml | 2 +- engine/taskpool-engine-springboot-starter/pom.xml | 2 +- engine/variable-serializer/pom.xml | 2 +- examples/components/process-backend/pom.xml | 2 +- examples/components/process-forms/pom.xml | 2 +- examples/components/tasklist-angular/pom.xml | 2 +- examples/components/tasklist-api/pom.xml | 2 +- examples/components/tasklist-backend/pom.xml | 2 +- examples/components/tasklist-reactive-backend/pom.xml | 2 +- examples/components/users/pom.xml | 2 +- examples/pom.xml | 2 +- .../camunda-webapp-application/pom.xml | 2 +- .../cockpit-application/application/pom.xml | 2 +- .../cockpit-application/backend/pom.xml | 2 +- .../cockpit-application/frontend/pom.xml | 2 +- .../distributed-axon-server/cockpit-application/pom.xml | 2 +- examples/scenarios/distributed-axon-server/pom.xml | 2 +- .../distributed-axon-server/process-application/pom.xml | 2 +- .../distributed-axon-server/taskpool-application/pom.xml | 2 +- examples/scenarios/pom.xml | 2 +- examples/scenarios/single-node/pom.xml | 2 +- pom.xml | 2 +- taskpool/pom.xml | 2 +- taskpool/taskpool-api/pom.xml | 2 +- taskpool/taskpool-core/pom.xml | 2 +- taskpool/taskpool-event/pom.xml | 2 +- view/mongo/pom.xml | 2 +- view/pom.xml | 2 +- view/simple/pom.xml | 2 +- view/view-api/pom.xml | 2 +- 41 files changed, 42 insertions(+), 42 deletions(-) diff --git a/bom/datapool-dependencies/pom.xml b/bom/datapool-dependencies/pom.xml index b9c8838de..fb7320732 100644 --- a/bom/datapool-dependencies/pom.xml +++ b/bom/datapool-dependencies/pom.xml @@ -6,7 +6,7 @@ camunda-bpm-taskpool io.holunda.taskpool - 2.1.3-SNAPSHOT + 2.1.3 ../../pom.xml diff --git a/bom/taskpool-dependencies/pom.xml b/bom/taskpool-dependencies/pom.xml index 6282298d4..74059f2fa 100644 --- a/bom/taskpool-dependencies/pom.xml +++ b/bom/taskpool-dependencies/pom.xml @@ -6,7 +6,7 @@ camunda-bpm-taskpool io.holunda.taskpool - 2.1.3-SNAPSHOT + 2.1.3 ../../pom.xml @@ -30,7 +30,7 @@ io.holunda.taskpool camunda-bpm-taskpool-collector - 2.1.3-SNAPSHOT + 2.1.3 io.holunda.taskpool diff --git a/datapool/datapool-api/pom.xml b/datapool/datapool-api/pom.xml index 21844cbe6..2b38f8ac1 100755 --- a/datapool/datapool-api/pom.xml +++ b/datapool/datapool-api/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-datapool-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-datapool-api diff --git a/datapool/datapool-core/pom.xml b/datapool/datapool-core/pom.xml index 407b260a3..586aa5534 100755 --- a/datapool/datapool-core/pom.xml +++ b/datapool/datapool-core/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-datapool-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-datapool-core diff --git a/datapool/datapool-event/pom.xml b/datapool/datapool-event/pom.xml index 17d2dd600..18e0116de 100755 --- a/datapool/datapool-event/pom.xml +++ b/datapool/datapool-event/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-datapool-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-datapool-event diff --git a/datapool/pom.xml b/datapool/pom.xml index a91a1264f..c9c557169 100755 --- a/datapool/pom.xml +++ b/datapool/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-datapool-root diff --git a/docs/pom.xml b/docs/pom.xml index 5613c8032..a900ce243 100644 --- a/docs/pom.xml +++ b/docs/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-docs diff --git a/engine/camunda-engine-client/pom.xml b/engine/camunda-engine-client/pom.xml index 8b3947cf4..70adbdb75 100644 --- a/engine/camunda-engine-client/pom.xml +++ b/engine/camunda-engine-client/pom.xml @@ -4,7 +4,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-engine-client diff --git a/engine/datapool-collector/pom.xml b/engine/datapool-collector/pom.xml index 2b59c9ff4..7366bb93f 100755 --- a/engine/datapool-collector/pom.xml +++ b/engine/datapool-collector/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-datapool-collector diff --git a/engine/pom.xml b/engine/pom.xml index 15903d101..9dc1a5c6c 100755 --- a/engine/pom.xml +++ b/engine/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-engine-root diff --git a/engine/property-taskurl-resolver/pom.xml b/engine/property-taskurl-resolver/pom.xml index f724c8365..1e4bfe2cd 100644 --- a/engine/property-taskurl-resolver/pom.xml +++ b/engine/property-taskurl-resolver/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.3-SNAPSHOT + 2.1.3 taskpool-property-taskurl-resolver diff --git a/engine/taskpool-collector/pom.xml b/engine/taskpool-collector/pom.xml index fb9a5d518..66ec8330f 100755 --- a/engine/taskpool-collector/pom.xml +++ b/engine/taskpool-collector/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-collector diff --git a/engine/taskpool-engine-springboot-starter/pom.xml b/engine/taskpool-engine-springboot-starter/pom.xml index 5db2f01e9..ccdd6ac4f 100755 --- a/engine/taskpool-engine-springboot-starter/pom.xml +++ b/engine/taskpool-engine-springboot-starter/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-engine-springboot-starter diff --git a/engine/variable-serializer/pom.xml b/engine/variable-serializer/pom.xml index c0efbad6b..87492390d 100755 --- a/engine/variable-serializer/pom.xml +++ b/engine/variable-serializer/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-engine-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-variable-serializer diff --git a/examples/components/process-backend/pom.xml b/examples/components/process-backend/pom.xml index 4526f1c1a..6261889e5 100755 --- a/examples/components/process-backend/pom.xml +++ b/examples/components/process-backend/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.3-SNAPSHOT + 2.1.3 ../../pom.xml diff --git a/examples/components/process-forms/pom.xml b/examples/components/process-forms/pom.xml index c4e278cd5..fd2013485 100755 --- a/examples/components/process-forms/pom.xml +++ b/examples/components/process-forms/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.3-SNAPSHOT + 2.1.3 ../../pom.xml diff --git a/examples/components/tasklist-angular/pom.xml b/examples/components/tasklist-angular/pom.xml index 230de72ab..d559e761b 100755 --- a/examples/components/tasklist-angular/pom.xml +++ b/examples/components/tasklist-angular/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.3-SNAPSHOT + 2.1.3 ../../pom.xml diff --git a/examples/components/tasklist-api/pom.xml b/examples/components/tasklist-api/pom.xml index cef90848d..1bec813ea 100755 --- a/examples/components/tasklist-api/pom.xml +++ b/examples/components/tasklist-api/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.3-SNAPSHOT + 2.1.3 ../../pom.xml diff --git a/examples/components/tasklist-backend/pom.xml b/examples/components/tasklist-backend/pom.xml index 9b8f86c78..e6ba98d77 100755 --- a/examples/components/tasklist-backend/pom.xml +++ b/examples/components/tasklist-backend/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.3-SNAPSHOT + 2.1.3 ../../pom.xml diff --git a/examples/components/tasklist-reactive-backend/pom.xml b/examples/components/tasklist-reactive-backend/pom.xml index 8575a83a4..311fef4e0 100755 --- a/examples/components/tasklist-reactive-backend/pom.xml +++ b/examples/components/tasklist-reactive-backend/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.3-SNAPSHOT + 2.1.3 ../../pom.xml diff --git a/examples/components/users/pom.xml b/examples/components/users/pom.xml index 24bdc97d2..37d1a59f8 100644 --- a/examples/components/users/pom.xml +++ b/examples/components/users/pom.xml @@ -7,7 +7,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.3-SNAPSHOT + 2.1.3 ../../pom.xml diff --git a/examples/pom.xml b/examples/pom.xml index ed2fb7fff..ba070f6dd 100755 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.3-SNAPSHOT + 2.1.3 taskpool-examples-root diff --git a/examples/scenarios/distributed-axon-server/camunda-webapp-application/pom.xml b/examples/scenarios/distributed-axon-server/camunda-webapp-application/pom.xml index 042594b18..fcae58282 100755 --- a/examples/scenarios/distributed-axon-server/camunda-webapp-application/pom.xml +++ b/examples/scenarios/distributed-axon-server/camunda-webapp-application/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-distributed-axon-server - 2.1.3-SNAPSHOT + 2.1.3 example-distributed-axon-server-webapp-application diff --git a/examples/scenarios/distributed-axon-server/cockpit-application/application/pom.xml b/examples/scenarios/distributed-axon-server/cockpit-application/application/pom.xml index 00e51bff7..5794f551a 100755 --- a/examples/scenarios/distributed-axon-server/cockpit-application/application/pom.xml +++ b/examples/scenarios/distributed-axon-server/cockpit-application/application/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-cockpit-root - 2.1.3-SNAPSHOT + 2.1.3 taskpool-example-cockpit diff --git a/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml b/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml index 8f21bf09c..57bec749d 100755 --- a/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml +++ b/examples/scenarios/distributed-axon-server/cockpit-application/backend/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-cockpit-root - 2.1.3-SNAPSHOT + 2.1.3 taskpool-example-cockpit-backend diff --git a/examples/scenarios/distributed-axon-server/cockpit-application/frontend/pom.xml b/examples/scenarios/distributed-axon-server/cockpit-application/frontend/pom.xml index 87a711906..3f8568a89 100755 --- a/examples/scenarios/distributed-axon-server/cockpit-application/frontend/pom.xml +++ b/examples/scenarios/distributed-axon-server/cockpit-application/frontend/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-cockpit-root - 2.1.3-SNAPSHOT + 2.1.3 taskpool-example-cockpit-frontend diff --git a/examples/scenarios/distributed-axon-server/cockpit-application/pom.xml b/examples/scenarios/distributed-axon-server/cockpit-application/pom.xml index 1dc152e67..f9ed7d406 100755 --- a/examples/scenarios/distributed-axon-server/cockpit-application/pom.xml +++ b/examples/scenarios/distributed-axon-server/cockpit-application/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-distributed-axon-server - 2.1.3-SNAPSHOT + 2.1.3 taskpool-example-cockpit-root diff --git a/examples/scenarios/distributed-axon-server/pom.xml b/examples/scenarios/distributed-axon-server/pom.xml index d9320c526..2cff8b001 100755 --- a/examples/scenarios/distributed-axon-server/pom.xml +++ b/examples/scenarios/distributed-axon-server/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-root - 2.1.3-SNAPSHOT + 2.1.3 taskpool-example-scenario-distributed-axon-server diff --git a/examples/scenarios/distributed-axon-server/process-application/pom.xml b/examples/scenarios/distributed-axon-server/process-application/pom.xml index 3d9b0ac62..e78afcdd4 100755 --- a/examples/scenarios/distributed-axon-server/process-application/pom.xml +++ b/examples/scenarios/distributed-axon-server/process-application/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-distributed-axon-server - 2.1.3-SNAPSHOT + 2.1.3 example-distributed-axon-server-process-application diff --git a/examples/scenarios/distributed-axon-server/taskpool-application/pom.xml b/examples/scenarios/distributed-axon-server/taskpool-application/pom.xml index bf9e96c07..7cb2fd23c 100755 --- a/examples/scenarios/distributed-axon-server/taskpool-application/pom.xml +++ b/examples/scenarios/distributed-axon-server/taskpool-application/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-distributed-axon-server - 2.1.3-SNAPSHOT + 2.1.3 example-distributed-axon-server-taskpool-application diff --git a/examples/scenarios/pom.xml b/examples/scenarios/pom.xml index b462253d7..62f981b32 100755 --- a/examples/scenarios/pom.xml +++ b/examples/scenarios/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-examples-root - 2.1.3-SNAPSHOT + 2.1.3 taskpool-example-scenario-root diff --git a/examples/scenarios/single-node/pom.xml b/examples/scenarios/single-node/pom.xml index 9e2bdcebe..075d462c2 100755 --- a/examples/scenarios/single-node/pom.xml +++ b/examples/scenarios/single-node/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool taskpool-example-scenario-root - 2.1.3-SNAPSHOT + 2.1.3 taskpool-example-scenario-single-node diff --git a/pom.xml b/pom.xml index b5ce2adb9..2f64377b1 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.3-SNAPSHOT + 2.1.3 pom ${project.artifactId} diff --git a/taskpool/pom.xml b/taskpool/pom.xml index 1fd2730a1..be1d943b4 100755 --- a/taskpool/pom.xml +++ b/taskpool/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-root diff --git a/taskpool/taskpool-api/pom.xml b/taskpool/taskpool-api/pom.xml index 50de9c474..0afde994b 100755 --- a/taskpool/taskpool-api/pom.xml +++ b/taskpool/taskpool-api/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-api diff --git a/taskpool/taskpool-core/pom.xml b/taskpool/taskpool-core/pom.xml index dab60ec09..72cae9e45 100755 --- a/taskpool/taskpool-core/pom.xml +++ b/taskpool/taskpool-core/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-core diff --git a/taskpool/taskpool-event/pom.xml b/taskpool/taskpool-event/pom.xml index 12394ea9c..af39b5e82 100755 --- a/taskpool/taskpool-event/pom.xml +++ b/taskpool/taskpool-event/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-event diff --git a/view/mongo/pom.xml b/view/mongo/pom.xml index 324bef147..20806f7fb 100755 --- a/view/mongo/pom.xml +++ b/view/mongo/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-view-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-view-mongo diff --git a/view/pom.xml b/view/pom.xml index bc20eb7cd..dc152c15c 100755 --- a/view/pom.xml +++ b/view/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-view-root diff --git a/view/simple/pom.xml b/view/simple/pom.xml index c470808d0..18200d50e 100755 --- a/view/simple/pom.xml +++ b/view/simple/pom.xml @@ -5,7 +5,7 @@ io.holunda.taskpool camunda-bpm-taskpool-view-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-view-simple diff --git a/view/view-api/pom.xml b/view/view-api/pom.xml index ea9834e5b..6bd3e202c 100755 --- a/view/view-api/pom.xml +++ b/view/view-api/pom.xml @@ -6,7 +6,7 @@ io.holunda.taskpool camunda-bpm-taskpool-view-root - 2.1.3-SNAPSHOT + 2.1.3 camunda-bpm-taskpool-view-api