Skip to content

Commit

Permalink
#466 task importer fix enrich wrong task query (#470)
Browse files Browse the repository at this point in the history
* #466 task importer fix enrich wrong task query

* Implement test, fixed #466 with a compound query to avoid Camunda API query problems

* remove limiting of multiple queries

* add logging for enrichment

* adopt tests

---------

Co-authored-by: Simon Zambrovski <[email protected]>
  • Loading branch information
simonhir and zambrovski authored Jun 19, 2023
1 parent 237c7c3 commit 354d867
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,15 @@
import org.camunda.bpm.engine.impl.persistence.entity.TaskEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.PostConstruct;
import javax.annotation.security.RolesAllowed;
import static io.holunda.camunda.bpm.data.CamundaBpmData.reader;

import static io.muenchendigital.digiwf.task.TaskVariables.TASK_SCHEMA_TYPE;
import java.util.HashSet;
import java.util.stream.Collectors;

import static org.springframework.http.ResponseEntity.noContent;

@RequiredArgsConstructor
Expand All @@ -44,16 +46,31 @@ void inform() {
@RolesAllowed(CLIENT_IMPORT_TASKS)
public ResponseEntity<Void> enrichExistingTasks() {

val tasks = taskService.createTaskQuery().active().withCandidateUsers().withCandidateGroups().list();
log.info("Selecting candidates for task enrichment from " + taskService.createTaskQuery().active().count() + " tasks.");
val tasks = new HashSet<TaskEntity>();
tasks.addAll(taskService.createTaskQuery()
.active()
.withCandidateUsers()
.list().stream().map(task -> ((TaskEntity)task)).collect(Collectors.toList()));
tasks.addAll(taskService.createTaskQuery()
.active()
.withCandidateGroups()
.list().stream().map(task -> ((TaskEntity)task)).collect(Collectors.toList()));
tasks.addAll(taskService.createTaskQuery()
.active()
.taskAssigned()
.list().stream().map(task -> ((TaskEntity)task)).collect(Collectors.toList()));

log.info("Selected for enrichment " + tasks.size() + " tasks");

tasks.forEach((task) -> {
val taskEntity = ((TaskEntity)task);
assignmentCreateTaskListener.taskCreated(taskEntity);
cancelableTaskStatusCreateTaskListener.taskCreated(taskEntity);
taskSchemaTypeCreateTaskListener.taskCreated(taskEntity);
taskDescriptionCreateTaskListener.taskCreated(taskEntity);
assignmentCreateTaskListener.taskCreated(task);
cancelableTaskStatusCreateTaskListener.taskCreated(task);
taskSchemaTypeCreateTaskListener.taskCreated(task);
taskDescriptionCreateTaskListener.taskCreated(task);
});

log.info("Enrichment of " + tasks.size() + " tasks finished");
return noContent().build();
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package io.muenchendigital.digiwf.task.importer;

import io.holunda.polyflow.taskpool.collector.task.TaskServiceCollectorService;
import io.muenchendigital.digiwf.task.listener.AssignmentCreateTaskListener;
import io.muenchendigital.digiwf.task.listener.CancelableTaskStatusCreateTaskListener;
import io.muenchendigital.digiwf.task.listener.TaskDescriptionCreateTaskListener;
import io.muenchendigital.digiwf.task.listener.TaskSchemaTypeCreateTaskListener;
import lombok.val;
import org.assertj.core.api.Assertions;
import org.camunda.bpm.engine.ProcessEngineConfiguration;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.delegate.DelegateTask;
import org.camunda.bpm.engine.impl.telemetry.TelemetryRegistry;
import org.camunda.bpm.engine.test.Deployment;
import org.camunda.bpm.engine.test.junit5.ProcessEngineExtension;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.mockito.ArgumentCaptor;

import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.assertThat;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;

@Disabled("This test is disabled from CI, since it uses the same in-mem H2 DB as CancelableTaskStatusCreateTaskListenerTest and interfers with it")
// FIXME - make sure we can run multiple tests with the engine -> maybe a dedicted ITEst-module for this is required.
class TaskImporterServiceTest {

@RegisterExtension
public static ProcessEngineExtension extension = ProcessEngineExtension
.builder()
.useProcessEngine(
ProcessEngineConfiguration
.createStandaloneInMemProcessEngineConfiguration()
.setHistory("none")
.setJdbcUrl("jdbc:h2:mem:camunda-importer;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;")
.setSkipHistoryOptimisticLockingExceptions(true)
.setTelemetryRegistry(mock(TelemetryRegistry.class))
.buildProcessEngine()
)
.build();

private final RuntimeService runtimeService = extension.getRuntimeService();
private final TaskService taskService = extension.getTaskService();

private final AssignmentCreateTaskListener listenerMock = mock(AssignmentCreateTaskListener.class);


private final TaskImporterService service = new TaskImporterService(
mock(TaskServiceCollectorService.class),
taskService,
listenerMock,
mock(CancelableTaskStatusCreateTaskListener.class),
mock(TaskSchemaTypeCreateTaskListener.class),
mock(TaskDescriptionCreateTaskListener.class)
);

private final ArgumentCaptor<DelegateTask> taskParamCaptor = ArgumentCaptor.forClass(DelegateTask.class);

@BeforeEach
void init_bridge() {
doNothing().when(listenerMock).taskCreated(taskParamCaptor.capture());
}

@Test
@Deployment(resources = "process_importer_service.bpmn")
public void queries_tasks() {

val instance = runtimeService.startProcessInstanceByKey("assignment_test_process");
assertThat(instance).isStarted();

Assertions.assertThat(taskService.createTaskQuery().processDefinitionKey("assignment_test_process").count()).isEqualTo(5);

service.enrichExistingTasks();

val invokedOnTasks = taskParamCaptor.getAllValues();
Assertions.assertThat(invokedOnTasks.stream().map(DelegateTask::getTaskDefinitionKey)).containsExactlyInAnyOrder("user_assigned", "user_candidate_users", "user_candidate_groups", "user_assigned_and_candidate_group");
Assertions.assertThat(invokedOnTasks.stream().map(DelegateTask::getTaskDefinitionKey)).doesNotContain("user_empty");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.delegate.DelegateTask;
import org.camunda.bpm.engine.delegate.TaskListener;
import org.camunda.bpm.engine.impl.telemetry.TelemetryRegistry;
import org.camunda.bpm.engine.test.Deployment;
import org.camunda.bpm.engine.test.junit5.ProcessEngineExtension;
import org.camunda.bpm.engine.test.mock.Mocks;
Expand All @@ -19,6 +20,7 @@
import static io.muenchendigital.digiwf.task.TaskVariables.TASK_CANCELABLE;
import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.assertThat;
import static org.camunda.bpm.engine.test.assertions.bpmn.BpmnAwareTests.task;
import static org.mockito.Mockito.mock;

class CancelableTaskStatusCreateTaskListenerTest {

Expand All @@ -28,15 +30,17 @@ class CancelableTaskStatusCreateTaskListenerTest {
.useProcessEngine(
ProcessEngineConfiguration
.createStandaloneInMemProcessEngineConfiguration()
.setJdbcUrl("jdbc:h2:mem:camunda;DB_CLOSE_DELAY=1000")
.setHistory("none")
.setJdbcUrl("jdbc:h2:mem:camunda;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;")
.setSkipHistoryOptimisticLockingExceptions(true)
.setTelemetryRegistry(mock(TelemetryRegistry.class))
.buildProcessEngine()
)
.ensureCleanAfterTest(true)
.build();

private final RuntimeService runtimeService = extension.getRuntimeService();
private final TaskService taskService = extension.getTaskService();


@BeforeEach
void init_bridge() {
Mocks.register("bridgeTestListener", new BridgeTestListener(new CancelableTaskStatusCreateTaskListener()));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:dc="http://www.omg.org/spec/DD/20100524/DC" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:di="http://www.omg.org/spec/DD/20100524/DI" xmlns:modeler="http://camunda.org/schema/modeler/1.0" id="Definitions_0da9eiw" targetNamespace="http://bpmn.io/schema/bpmn" exporter="Camunda Modeler" exporterVersion="5.6.0" modeler:executionPlatform="Camunda Platform" modeler:executionPlatformVersion="7.18.0">
<bpmn:process id="assignment_test_process" name="assignment_test_process" isExecutable="true">
<bpmn:startEvent id="StartEvent_1">
<bpmn:outgoing>Flow_08bu753</bpmn:outgoing>
</bpmn:startEvent>
<bpmn:sequenceFlow id="Flow_08bu753" sourceRef="StartEvent_1" targetRef="Gateway_06p5osr" />
<bpmn:parallelGateway id="Gateway_06p5osr">
<bpmn:incoming>Flow_08bu753</bpmn:incoming>
<bpmn:outgoing>Flow_0upa54l</bpmn:outgoing>
<bpmn:outgoing>Flow_0drqiws</bpmn:outgoing>
<bpmn:outgoing>Flow_1kme650</bpmn:outgoing>
<bpmn:outgoing>Flow_1onciql</bpmn:outgoing>
<bpmn:outgoing>Flow_1rhun6h</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:sequenceFlow id="Flow_0upa54l" sourceRef="Gateway_06p5osr" targetRef="user_assigned" />
<bpmn:sequenceFlow id="Flow_0drqiws" sourceRef="Gateway_06p5osr" targetRef="user_candidate_users" />
<bpmn:sequenceFlow id="Flow_1kme650" sourceRef="Gateway_06p5osr" targetRef="user_candidate_groups" />
<bpmn:sequenceFlow id="Flow_03ge0v5" sourceRef="user_assigned" targetRef="Gateway_1yud87a" />
<bpmn:sequenceFlow id="Flow_14zarld" sourceRef="user_candidate_users" targetRef="Gateway_1yud87a" />
<bpmn:sequenceFlow id="Flow_1qcgzhy" sourceRef="user_candidate_groups" targetRef="Gateway_1yud87a" />
<bpmn:endEvent id="Event_1q2so1q">
<bpmn:incoming>Flow_1yh2mao</bpmn:incoming>
</bpmn:endEvent>
<bpmn:sequenceFlow id="Flow_1yh2mao" sourceRef="Gateway_1yud87a" targetRef="Event_1q2so1q" />
<bpmn:parallelGateway id="Gateway_1yud87a">
<bpmn:incoming>Flow_03ge0v5</bpmn:incoming>
<bpmn:incoming>Flow_14zarld</bpmn:incoming>
<bpmn:incoming>Flow_1qcgzhy</bpmn:incoming>
<bpmn:incoming>Flow_04h13on</bpmn:incoming>
<bpmn:incoming>Flow_0bu7oeo</bpmn:incoming>
<bpmn:outgoing>Flow_1yh2mao</bpmn:outgoing>
</bpmn:parallelGateway>
<bpmn:sequenceFlow id="Flow_1onciql" sourceRef="Gateway_06p5osr" targetRef="user_empty" />
<bpmn:sequenceFlow id="Flow_04h13on" sourceRef="user_empty" targetRef="Gateway_1yud87a" />
<bpmn:userTask id="user_empty" name="Empty">
<bpmn:incoming>Flow_1onciql</bpmn:incoming>
<bpmn:outgoing>Flow_04h13on</bpmn:outgoing>
</bpmn:userTask>
<bpmn:userTask id="user_candidate_groups" name="Candidate Group" camunda:candidateGroups="group1">
<bpmn:incoming>Flow_1kme650</bpmn:incoming>
<bpmn:outgoing>Flow_1qcgzhy</bpmn:outgoing>
</bpmn:userTask>
<bpmn:userTask id="user_candidate_users" name="Candidate User" camunda:candidateUsers="johndoe">
<bpmn:incoming>Flow_0drqiws</bpmn:incoming>
<bpmn:outgoing>Flow_14zarld</bpmn:outgoing>
</bpmn:userTask>
<bpmn:userTask id="user_assigned" name="Assigned" camunda:assignee="johndoe">
<bpmn:incoming>Flow_0upa54l</bpmn:incoming>
<bpmn:outgoing>Flow_03ge0v5</bpmn:outgoing>
</bpmn:userTask>
<bpmn:sequenceFlow id="Flow_1rhun6h" sourceRef="Gateway_06p5osr" targetRef="user_assigned_and_candidate_group" />
<bpmn:sequenceFlow id="Flow_0bu7oeo" sourceRef="user_assigned_and_candidate_group" targetRef="Gateway_1yud87a" />
<bpmn:userTask id="user_assigned_and_candidate_group" name="Assigned and Candidate Group" camunda:assignee="johndoe" camunda:candidateGroups="group1">
<bpmn:incoming>Flow_1rhun6h</bpmn:incoming>
<bpmn:outgoing>Flow_0bu7oeo</bpmn:outgoing>
</bpmn:userTask>
</bpmn:process>
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="assignment_test_process">
<bpmndi:BPMNShape id="_BPMNShape_StartEvent_2" bpmnElement="StartEvent_1">
<dc:Bounds x="152" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_1xn7cba_di" bpmnElement="Gateway_06p5osr">
<dc:Bounds x="245" y="95" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Event_1q2so1q_di" bpmnElement="Event_1q2so1q">
<dc:Bounds x="642" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Gateway_0b1vznn_di" bpmnElement="Gateway_1yud87a">
<dc:Bounds x="525" y="95" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_01bp8m0_di" bpmnElement="user_empty">
<dc:Bounds x="360" y="410" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0va7dtl_di" bpmnElement="user_candidate_groups">
<dc:Bounds x="360" y="300" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_0pwur6i_di" bpmnElement="user_candidate_users">
<dc:Bounds x="360" y="190" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_1plx2zu_di" bpmnElement="user_assigned">
<dc:Bounds x="360" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Activity_13zpjs1_di" bpmnElement="user_assigned_and_candidate_group">
<dc:Bounds x="360" y="520" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="Flow_08bu753_di" bpmnElement="Flow_08bu753">
<di:waypoint x="188" y="120" />
<di:waypoint x="245" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0upa54l_di" bpmnElement="Flow_0upa54l">
<di:waypoint x="295" y="120" />
<di:waypoint x="360" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0drqiws_di" bpmnElement="Flow_0drqiws">
<di:waypoint x="270" y="145" />
<di:waypoint x="270" y="230" />
<di:waypoint x="360" y="230" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1kme650_di" bpmnElement="Flow_1kme650">
<di:waypoint x="270" y="145" />
<di:waypoint x="270" y="340" />
<di:waypoint x="360" y="340" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1onciql_di" bpmnElement="Flow_1onciql">
<di:waypoint x="270" y="145" />
<di:waypoint x="270" y="450" />
<di:waypoint x="360" y="450" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1yh2mao_di" bpmnElement="Flow_1yh2mao">
<di:waypoint x="575" y="120" />
<di:waypoint x="642" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_03ge0v5_di" bpmnElement="Flow_03ge0v5">
<di:waypoint x="460" y="120" />
<di:waypoint x="525" y="120" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_14zarld_di" bpmnElement="Flow_14zarld">
<di:waypoint x="460" y="230" />
<di:waypoint x="550" y="230" />
<di:waypoint x="550" y="145" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1qcgzhy_di" bpmnElement="Flow_1qcgzhy">
<di:waypoint x="460" y="340" />
<di:waypoint x="550" y="340" />
<di:waypoint x="550" y="145" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_04h13on_di" bpmnElement="Flow_04h13on">
<di:waypoint x="460" y="450" />
<di:waypoint x="550" y="450" />
<di:waypoint x="550" y="145" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_1rhun6h_di" bpmnElement="Flow_1rhun6h">
<di:waypoint x="270" y="145" />
<di:waypoint x="270" y="560" />
<di:waypoint x="360" y="560" />
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="Flow_0bu7oeo_di" bpmnElement="Flow_0bu7oeo">
<di:waypoint x="460" y="560" />
<di:waypoint x="550" y="560" />
<di:waypoint x="550" y="145" />
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

0 comments on commit 354d867

Please sign in to comment.