From 2067b522b1cea7b4314b08688e7a530892281ff3 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Mon, 4 Nov 2024 22:55:17 +0100 Subject: [PATCH 01/37] feat(api): add filter on incidentIdIn for HistoricProcessInstanceQuery related to: #4587 --------- Co-authored-by: Tassilo Weidner <3015690+tasso94@users.noreply.github.com> Backported commit 5d02cd39bc from the camunda-bpm-platform repository. Original author: Gergely Juhasz --- .../lib/commons/history-process-instance.ftl | 6 ++ .../HistoricProcessInstanceQueryDto.java | 9 ++ ...icProcessInstanceRestServiceQueryTest.java | 28 ++++++ .../history/HistoricProcessInstanceQuery.java | 5 + .../HistoricProcessInstanceQueryImpl.java | 11 +++ .../entity/HistoricProcessInstance.xml | 10 +- .../history/HistoricProcessInstanceTest.java | 96 +++++++++++++++++++ ...sAfterUserTaskCreateOneIncident.bpmn20.xml | 20 ++++ 8 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/failingProcessAfterUserTaskCreateOneIncident.bpmn20.xml diff --git a/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/history-process-instance.ftl b/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/history-process-instance.ftl index d24f16bb978..086b3aacceb 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/history-process-instance.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/history-process-instance.ftl @@ -123,6 +123,12 @@ "desc": "Only include process instances which have a root incident. Value may only be `true`, as `false` is the default behavior." }, + "incidentIdIn": { + "type": "array", + "itemType": "string", + "desc": "Restrict to instances that have an incident with one of the given ids. ${listTypeDescription}" + }, + "incidentType": { "type": "string", "desc": "Filter by the incident type. See the [User Guide](${docsUrl}/user-guide/process-engine/incidents/#incident-types) for a list of incident types." diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceQueryDto.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceQueryDto.java index a121c67dacb..31543c1b535 100644 --- a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceQueryDto.java +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceQueryDto.java @@ -114,6 +114,7 @@ public class HistoricProcessInstanceQueryDto extends AbstractQueryDto incidentIds; private List variables; @@ -306,6 +307,11 @@ public void setIncidentType(String incidentType) { this.incidentType = incidentType; } + @OperatonQueryParam(value = "incidentIdIn", converter = StringListConverter.class) + public void setIncidentIdIn(List incidentIds) { + this.incidentIds = incidentIds; + } + @OperatonQueryParam(value = "tenantIdIn", converter = StringListConverter.class) public void setTenantIdIn(List tenantIds) { this.tenantIds = tenantIds; @@ -443,6 +449,9 @@ protected void applyFilters(HistoricProcessInstanceQuery query) { if (withRootIncidents != null && withRootIncidents) { query.withRootIncidents(); } + if (incidentIds != null && !incidentIds.isEmpty()) { + query.incidentIdIn(incidentIds.toArray(new String[0])); + } if (incidentStatus != null) { query.incidentStatus(incidentStatus); } diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java index e63bf12bbb9..8c32e87df52 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java @@ -73,6 +73,7 @@ public class HistoricProcessInstanceRestServiceQueryTest extends AbstractRestSer protected static final String QUERY_PARAM_EXECUTED_ACTIVITY_AFTER = "executedActivityAfter"; protected static final String QUERY_PARAM_EXECUTED_ACTIVITY_IDS = "executedActivityIdIn"; protected static final String QUERY_PARAM_ACTIVE_ACTIVITY_IDS = "activeActivityIdIn"; + protected static final String QUERY_PARAM_INCIDENT_IDS = "incidentIdIn"; @ClassRule public static TestContainerRule rule = new TestContainerRule(); @@ -2315,5 +2316,32 @@ public void testQueryByRootProcessInstancesAsPost() { verify(mockedQuery).rootProcessInstances(); } + @Test + public void testQueryByIncidentIdIn() { + given() + .queryParam(QUERY_PARAM_INCIDENT_IDS, "1,2") + .then().expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .get(HISTORIC_PROCESS_INSTANCE_RESOURCE_URL); + + verify(mockedQuery).incidentIdIn("1", "2"); + } + + @Test + public void testQueryByIncidentIdInAsPost() { + Map> parameters = new HashMap>(); + parameters.put(QUERY_PARAM_INCIDENT_IDS, Arrays.asList("1", "2")); + + given() + .contentType(POST_JSON_CONTENT_TYPE) + .body(parameters) + .then().expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .post(HISTORIC_PROCESS_INSTANCE_RESOURCE_URL); + + verify(mockedQuery).incidentIdIn("1", "2"); + } } diff --git a/engine/src/main/java/org/operaton/bpm/engine/history/HistoricProcessInstanceQuery.java b/engine/src/main/java/org/operaton/bpm/engine/history/HistoricProcessInstanceQuery.java index 62fe37891ce..9e0f25cc66e 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/history/HistoricProcessInstanceQuery.java +++ b/engine/src/main/java/org/operaton/bpm/engine/history/HistoricProcessInstanceQuery.java @@ -127,6 +127,11 @@ public interface HistoricProcessInstanceQuery extends Query - + @@ -550,6 +550,14 @@ ${queryType} INC.INCIDENT_TYPE_ = #{query.incidentType} + + + ${queryType} INC.ID_ IN + + #{incidentId} + + + ${queryType} INC.INCIDENT_MSG_ = #{query.incidentMessage} diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.java b/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.java index 954e395d77f..5503e655285 100644 --- a/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.java +++ b/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.java @@ -39,6 +39,7 @@ import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.apache.commons.lang3.time.DateUtils; import org.operaton.bpm.engine.BadUserRequestException; import org.operaton.bpm.engine.CaseService; @@ -59,6 +60,7 @@ import org.operaton.bpm.engine.impl.history.event.HistoricProcessInstanceEventEntity; import org.operaton.bpm.engine.impl.util.ClockUtil; import org.operaton.bpm.engine.repository.ProcessDefinition; +import org.operaton.bpm.engine.runtime.Incident; import org.operaton.bpm.engine.runtime.Job; import org.operaton.bpm.engine.runtime.ProcessInstance; import org.operaton.bpm.engine.task.Task; @@ -1693,6 +1695,100 @@ public void testQueryByMultipleInvalidProcessDefinitionKeyIn() { } } + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + @Deployment(resources={"org/operaton/bpm/engine/test/api/runtime/failingProcessCreateOneIncident.bpmn20.xml"}) + public void shouldQueryProcessInstancesWithIncidentIdIn() { + // GIVEN + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("failingProcess"); + ProcessInstance processInstance2 = runtimeService.startProcessInstanceByKey("failingProcess"); + runtimeService.startProcessInstanceByKey("failingProcess"); + List queriedProcessInstances = Arrays.asList(processInstance.getId(), processInstance2.getId()); + + testHelper.executeAvailableJobs(); + Incident incident = runtimeService.createIncidentQuery().processInstanceId(queriedProcessInstances.get(0)).singleResult(); + Incident incident2 = runtimeService.createIncidentQuery().processInstanceId(queriedProcessInstances.get(1)).singleResult(); + + // WHEN + List processInstanceList = + historyService.createHistoricProcessInstanceQuery().incidentIdIn(incident.getId(), incident2.getId()).list(); + + // THEN + assertEquals(2, processInstanceList.size()); + assertThat(queriedProcessInstances) + .containsExactlyInAnyOrderElementsOf( + processInstanceList.stream() + .map(HistoricProcessInstance::getId) + .collect(Collectors.toList())); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + @Deployment(resources={"org/operaton/bpm/engine/test/api/runtime/failingProcessAfterUserTaskCreateOneIncident.bpmn20.xml"}) + public void shouldOnlyQueryProcessInstancesWithIncidentIdIn() { + // GIVEN + ProcessInstance processWithIncident1 = runtimeService.startProcessInstanceByKey("failingProcess"); + ProcessInstance processWithIncident2 = runtimeService.startProcessInstanceByKey("failingProcess"); + + List tasks = taskService.createTaskQuery().list(); + assertEquals(2, tasks.size()); + taskService.complete(tasks.get(0).getId()); + taskService.complete(tasks.get(1).getId()); + + ProcessInstance processWithoutIncident = runtimeService.startProcessInstanceByKey("failingProcess"); + + List queriedProcessInstances = Arrays.asList(processWithIncident1.getId(), processWithIncident2.getId()); + + testHelper.executeAvailableJobs(); + Incident incident = runtimeService.createIncidentQuery().processInstanceId(queriedProcessInstances.get(0)).singleResult(); + Incident incident2 = runtimeService.createIncidentQuery().processInstanceId(queriedProcessInstances.get(1)).singleResult(); + + // WHEN + List processInstanceList = + historyService.createHistoricProcessInstanceQuery().incidentIdIn(incident.getId(), incident2.getId()).list(); + + // THEN + assertEquals(2, processInstanceList.size()); + assertThat(queriedProcessInstances) + .containsExactlyInAnyOrderElementsOf( + processInstanceList.stream() + .map(HistoricProcessInstance::getId) + .collect(Collectors.toList())); + } + + @Test + public void shouldFailWhenQueryWithNullIncidentIdIn() { + try { + historyService.createHistoricProcessInstanceQuery().incidentIdIn(null).list(); + fail("incidentMessage with null value is not allowed"); + } catch( NullValueException nex ) { + // expected + } + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + @Deployment(resources={"org/operaton/bpm/engine/test/api/runtime/failingSubProcessCreateOneIncident.bpmn20.xml"}) + public void shouldQueryByIncidentIdInSubProcess() { + // given + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("failingSubProcess"); + + testHelper.executeAvailableJobs(); + + List incidentList = runtimeService.createIncidentQuery().list(); + assertEquals(1, incidentList.size()); + + Incident incident = runtimeService.createIncidentQuery().processInstanceId(processInstance.getId()).singleResult(); + + // when + HistoricProcessInstance historicPI = + historyService.createHistoricProcessInstanceQuery().incidentIdIn(incident.getId()).singleResult(); + + // then + assertThat(historicPI).isNotNull(); + assertThat(historicPI.getId()).isEqualTo(processInstance.getId()); + } + @Test @Deployment(resources = {"org/operaton/bpm/engine/test/history/oneAsyncTaskProcess.bpmn20.xml"}) public void testShouldStoreHistoricProcessInstanceVariableOnAsyncBefore() { diff --git a/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/failingProcessAfterUserTaskCreateOneIncident.bpmn20.xml b/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/failingProcessAfterUserTaskCreateOneIncident.bpmn20.xml new file mode 100644 index 00000000000..e7fb8eef394 --- /dev/null +++ b/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/failingProcessAfterUserTaskCreateOneIncident.bpmn20.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + From 143c59032cedf96bb8ed6cb3472ccc20cf1cf774 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Mon, 4 Nov 2024 23:25:18 +0100 Subject: [PATCH 02/37] Remove installAtEnd --- .mvn/maven.config | 1 - 1 file changed, 1 deletion(-) diff --git a/.mvn/maven.config b/.mvn/maven.config index b102b0e7b83..0a656548c59 100644 --- a/.mvn/maven.config +++ b/.mvn/maven.config @@ -2,6 +2,5 @@ --errors --show-version --no-transfer-progress --DinstallAtEnd=true -DdeployAtEnd=true -Duser.timezone=Europe/Berlin From fc8aac880404e61298d4e9f26549a3e1fc0e9af2 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Tue, 5 Nov 2024 00:01:39 +0100 Subject: [PATCH 03/37] [#27] JUnit 5 migration: submodule examples --- .../engine/impl/test/ProcessEngineAssert.java | 4 +- .../bpm/example/invoice/InvoiceTestCase.java | 62 ++++++++++++------- examples/pom.xml | 12 ++-- 3 files changed, 47 insertions(+), 31 deletions(-) diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/test/ProcessEngineAssert.java b/engine/src/main/java/org/operaton/bpm/engine/impl/test/ProcessEngineAssert.java index 0d13878bcfa..3d1586d03c7 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/test/ProcessEngineAssert.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/test/ProcessEngineAssert.java @@ -16,8 +16,6 @@ */ package org.operaton.bpm.engine.impl.test; -import junit.framework.AssertionFailedError; - import org.operaton.bpm.engine.ProcessEngine; import org.operaton.bpm.engine.runtime.ProcessInstance; @@ -31,7 +29,7 @@ public static void assertProcessEnded(ProcessEngine processEngine, String proces .singleResult(); if (processInstance!=null) { - throw new AssertionFailedError("expected finished process instance '"+processInstanceId+"' but it was still in the db"); + throw new AssertionError("expected finished process instance '"+processInstanceId+"' but it was still in the db"); } } } diff --git a/examples/invoice/src/test/java/org/operaton/bpm/example/invoice/InvoiceTestCase.java b/examples/invoice/src/test/java/org/operaton/bpm/example/invoice/InvoiceTestCase.java index a89adbeea14..208226105a3 100644 --- a/examples/invoice/src/test/java/org/operaton/bpm/example/invoice/InvoiceTestCase.java +++ b/examples/invoice/src/test/java/org/operaton/bpm/example/invoice/InvoiceTestCase.java @@ -16,27 +16,40 @@ */ package org.operaton.bpm.example.invoice; -import static org.operaton.bpm.engine.variable.Variables.fileValue; - -import java.io.InputStream; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.operaton.bpm.engine.ManagementService; +import org.operaton.bpm.engine.ProcessEngine; +import org.operaton.bpm.engine.RuntimeService; +import org.operaton.bpm.engine.TaskService; import org.operaton.bpm.engine.runtime.Job; import org.operaton.bpm.engine.runtime.ProcessInstance; import org.operaton.bpm.engine.task.IdentityLink; import org.operaton.bpm.engine.task.Task; import org.operaton.bpm.engine.test.Deployment; -import org.operaton.bpm.engine.test.ProcessEngineTestCase; +import org.operaton.bpm.engine.test.junit5.ProcessEngineExtension; import org.operaton.bpm.engine.variable.VariableMap; import org.operaton.bpm.engine.variable.Variables; -public class InvoiceTestCase extends ProcessEngineTestCase { +import java.io.InputStream; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; - @Deployment(resources= {"invoice.v1.bpmn", "invoiceBusinessDecisions.dmn"}) - public void testHappyPathV1() { +import static org.junit.jupiter.api.Assertions.*; +import static org.operaton.bpm.engine.impl.test.ProcessEngineAssert.assertProcessEnded; +import static org.operaton.bpm.engine.variable.Variables.fileValue; + +@ExtendWith(ProcessEngineExtension.class) +public class InvoiceTestCase { + ProcessEngine processEngine; + RuntimeService runtimeService; + TaskService taskService; + ManagementService managementService; + @Deployment(resources = {"invoice.v1.bpmn", "invoiceBusinessDecisions.dmn"}) + @Test + public void testHappyPathV1() { InputStream invoiceInputStream = InvoiceProcessApplication.class.getClassLoader().getResourceAsStream("invoice.pdf"); VariableMap variables = Variables.createVariables() .putValue("creditor", "Great Pizza for Everyone Inc.") @@ -75,11 +88,12 @@ public void testHappyPathV1() { assertNotNull(archiveInvoiceJob); managementService.executeJob(archiveInvoiceJob.getId()); - assertProcessEnded(pi.getId()); + assertProcessEnded(processEngine, pi.getId()); } - @Deployment(resources= {"invoice.v2.bpmn", "invoiceBusinessDecisions.dmn"}) - public void testHappyPathV2() { + @Deployment(resources = {"invoice.v2.bpmn", "invoiceBusinessDecisions.dmn"}) + @Test + public void testHappyPathV2() { InputStream invoiceInputStream = InvoiceProcessApplication.class.getClassLoader().getResourceAsStream("invoice.pdf"); VariableMap variables = Variables.createVariables() .putValue("creditor", "Great Pizza for Everyone Inc.") @@ -118,11 +132,12 @@ public void testHappyPathV2() { assertNotNull(archiveInvoiceJob); managementService.executeJob(archiveInvoiceJob.getId()); - assertProcessEnded(pi.getId()); + assertProcessEnded(processEngine, pi.getId()); } - @Deployment(resources= {"invoice.v2.bpmn", "invoiceBusinessDecisions.dmn"}) - public void testApproveInvoiceAssignment() { + @Deployment(resources = {"invoice.v2.bpmn", "invoiceBusinessDecisions.dmn"}) + @Test + public void testApproveInvoiceAssignment() { InputStream invoiceInputStream = InvoiceProcessApplication.class.getClassLoader().getResourceAsStream("invoice.pdf"); VariableMap variables = Variables.createVariables() @@ -165,8 +180,9 @@ public void testApproveInvoiceAssignment() { assertEquals("mary", taskService.getVariable(task.getId(), "approver")); } - @Deployment(resources= {"invoice.v2.bpmn", "reviewInvoice.bpmn", "invoiceBusinessDecisions.dmn"}) - public void testNonSuccessfulPath() { + @Deployment(resources = {"invoice.v2.bpmn", "reviewInvoice.bpmn", "invoiceBusinessDecisions.dmn"}) + @Test + public void testNonSuccessfulPath() { InputStream invoiceInputStream = InvoiceProcessApplication.class.getClassLoader().getResourceAsStream("invoice.pdf"); VariableMap variables = Variables.createVariables() .putValue("creditor", "Great Pizza for Everyone Inc.") @@ -210,9 +226,11 @@ public void testNonSuccessfulPath() { variables.put("clarified", Boolean.FALSE); taskService.complete(task.getId(), variables); - assertProcessEnded(task.getProcessInstanceId()); - assertProcessEnded(pi.getId()); + assertProcessEnded(processEngine, task.getProcessInstanceId()); + assertProcessEnded(processEngine, pi.getId()); } } + + diff --git a/examples/pom.xml b/examples/pom.xml index 01ac4583376..bf4675fcadd 100644 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -33,12 +33,6 @@ provided - - junit - junit - test - - com.h2database h2 @@ -57,6 +51,12 @@ test + + org.operaton.bpm + operaton-bpm-junit5 + test + + From b8b43e12c21400cae4aea8e69fb727e26b62911d Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Mon, 4 Nov 2024 16:04:23 +0100 Subject: [PATCH 04/37] feat(cockpit): add rootInstanceId filter to humanTask search (#4509) related to #4315 Backported commit e0b2c191e6 from the camunda-bpm-platform repository. Original author: Gergely Juhasz --- webapps/frontend/public/app/cockpit/locales/de.json | 1 + webapps/frontend/public/app/cockpit/locales/en.json | 1 + 2 files changed, 2 insertions(+) diff --git a/webapps/frontend/public/app/cockpit/locales/de.json b/webapps/frontend/public/app/cockpit/locales/de.json index 1eb3b4e6ce3..ed179e7f02b 100644 --- a/webapps/frontend/public/app/cockpit/locales/de.json +++ b/webapps/frontend/public/app/cockpit/locales/de.json @@ -1757,6 +1757,7 @@ "PLGN_SETA_CONF_PROCESS_DEFINITION_NAME": "Prozessdefinitions-Name", "PLGN_SETA_CONF_PROCESS_INSTANCE_ID": "Prozessinstanz-ID", "PLGN_SETA_CONF_PROCESS_VARIABLE": "Prozess-Variable", + "PLGN_SETA_CONF_ROOT_PROCESS_INSTANCE_ID": "Root Process Instance ID", "PLGN_SETA_CONF_TASK_ASSIGNEE": "Task-Assignee", "PLGN_SETA_CONF_TASK_DEFINITION_KEY": "Task-Definitions-Schlüssel", "PLGN_SETA_CONF_TASK_DELETE_REASON": "Löschgrund des Tasks", diff --git a/webapps/frontend/public/app/cockpit/locales/en.json b/webapps/frontend/public/app/cockpit/locales/en.json index 61c651cce78..ca5f5dda729 100644 --- a/webapps/frontend/public/app/cockpit/locales/en.json +++ b/webapps/frontend/public/app/cockpit/locales/en.json @@ -1757,6 +1757,7 @@ "PLGN_SETA_CONF_PROCESS_DEFINITION_NAME": "Process Definition Name", "PLGN_SETA_CONF_PROCESS_INSTANCE_ID": "Process Instance ID", "PLGN_SETA_CONF_PROCESS_VARIABLE": "Process Variable", + "PLGN_SETA_CONF_ROOT_PROCESS_INSTANCE_ID": "Root Process Instance ID", "PLGN_SETA_CONF_TASK_ASSIGNEE": "Task Assignee", "PLGN_SETA_CONF_TASK_DEFINITION_KEY": "Task Definition Key", "PLGN_SETA_CONF_TASK_DELETE_REASON": "Task Delete Reason", From 1bd2107dada211f021f1b33105d5f042850caa00 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Mon, 4 Nov 2024 22:38:36 +0100 Subject: [PATCH 05/37] fix(openapi): make description for POST /deployment/create more clear Related to https://github.com/camunda/camunda-bpm-platform/issues/4312 Backported commit 8789a9b748 from the camunda-bpm-platform repository. Original author: Miklas Boskamp --- .../org/operaton/bpm/engine/rest/dto/MultiFormDeploymentDto.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/MultiFormDeploymentDto.ftl b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/MultiFormDeploymentDto.ftl index 10e40a77388..4e3f8e26eb3 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/MultiFormDeploymentDto.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/MultiFormDeploymentDto.ftl @@ -17,7 +17,7 @@ defaultValue = 'false' desc = "A flag indicating whether the process engine should perform duplicate checking on a per-resource basis. If set to true, only those resources that have actually changed are deployed. - Checks are made against resources included previous deployments of the same name and only against the latest versions of those resources. + Checks are made against resources included previous deployments of the same name and source and only against the latest versions of those resources. If set to true, the option enable-duplicate-filtering is overridden and set to true." /> <@lib.property From 5832855edcce58a15e5fbd2768f2f1b60f8eb7fd Mon Sep 17 00:00:00 2001 From: Dirk Olmes Date: Tue, 5 Nov 2024 09:26:46 +0100 Subject: [PATCH 06/37] chore(sonar): Fix instanceof check and cast with pattern matching in engine-dmn/engine. (#85) --- .../impl/DefaultDmnEngineConfiguration.java | 4 ++-- .../impl/el/VariableContextScriptBindings.java | 8 ++++---- .../evaluation/ExpressionEvaluationHandler.java | 5 ++--- .../AbstractCollectNumberHitPolicyHandler.java | 12 ++++++------ .../metrics/DmnEngineMetricCollectorWrapper.java | 4 ++-- .../impl/type/BooleanDataTypeTransformer.java | 8 ++++---- .../impl/type/DateDataTypeTransformer.java | 16 ++++++++-------- .../impl/type/DoubleDataTypeTransformer.java | 8 ++++---- .../impl/type/IntegerDataTypeTransformer.java | 8 ++++---- .../impl/type/LongDataTypeTransformer.java | 8 ++++---- 10 files changed, 40 insertions(+), 41 deletions(-) diff --git a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/DefaultDmnEngineConfiguration.java b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/DefaultDmnEngineConfiguration.java index 8ea7c208e03..a6eb7f45f3e 100644 --- a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/DefaultDmnEngineConfiguration.java +++ b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/DefaultDmnEngineConfiguration.java @@ -168,8 +168,8 @@ protected void initDecisionEvaluationListener() { protected Collection getDefaultDmnDecisionEvaluationListeners() { List defaultListeners = new ArrayList<>(); - if (engineMetricCollector instanceof DmnDecisionEvaluationListener) { - defaultListeners.add((DmnDecisionEvaluationListener) engineMetricCollector); + if (engineMetricCollector instanceof DmnDecisionEvaluationListener listener) { + defaultListeners.add(listener); } else { defaultListeners.add(new DmnEngineMetricCollectorWrapper(engineMetricCollector)); } diff --git a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/el/VariableContextScriptBindings.java b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/el/VariableContextScriptBindings.java index 925ee916d46..bf999f1a73f 100644 --- a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/el/VariableContextScriptBindings.java +++ b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/el/VariableContextScriptBindings.java @@ -54,8 +54,8 @@ public boolean containsKey(Object key) { if(wrappedBindings.containsKey(key)) { return true; } - if (key instanceof String) { - return variableContext.containsVariable((String) key); + if (key instanceof String keyString) { + return variableContext.containsVariable(keyString); } else { return false; @@ -72,8 +72,8 @@ public Object get(Object key) { result = wrappedBindings.get(key); } else { - if (key instanceof String) { - TypedValue resolvedValue = variableContext.resolve((String) key); + if (key instanceof String keyString) { + TypedValue resolvedValue = variableContext.resolve(keyString); result = unpack(resolvedValue); } } diff --git a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/evaluation/ExpressionEvaluationHandler.java b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/evaluation/ExpressionEvaluationHandler.java index 5e3cc0ee57a..f143feb42c5 100644 --- a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/evaluation/ExpressionEvaluationHandler.java +++ b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/evaluation/ExpressionEvaluationHandler.java @@ -77,15 +77,14 @@ protected Object evaluateScriptExpression(String expressionLanguage, VariableCon bindings.put("variableContext", variableContext); try { - if (scriptEngine instanceof Compilable) { + if (scriptEngine instanceof Compilable compilableScriptEngine) { CompiledScript compiledScript = cachedCompiledScriptSupport.getCachedCompiledScript(); if (compiledScript == null) { synchronized (cachedCompiledScriptSupport) { compiledScript = cachedCompiledScriptSupport.getCachedCompiledScript(); - if(compiledScript == null) { - Compilable compilableScriptEngine = (Compilable) scriptEngine; + if (compiledScript == null) { compiledScript = compilableScriptEngine.compile(expressionText); cachedCompiledScriptSupport.cacheCompiledScript(compiledScript); diff --git a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/hitpolicy/AbstractCollectNumberHitPolicyHandler.java b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/hitpolicy/AbstractCollectNumberHitPolicyHandler.java index 049b2a75f5e..71d762a9ef7 100644 --- a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/hitpolicy/AbstractCollectNumberHitPolicyHandler.java +++ b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/hitpolicy/AbstractCollectNumberHitPolicyHandler.java @@ -135,8 +135,8 @@ protected List convertValuesToInteger(List typedValues) thr // check if it is an integer Object value = typedValue.getValue(); - if (value instanceof Integer) { - intValues.add((Integer) value); + if (value instanceof Integer integerValue) { + intValues.add(integerValue); } else { throw new IllegalArgumentException(); @@ -162,8 +162,8 @@ protected List convertValuesToLong(List typedValues) throws Il // check if it is a long or a string of a number Object value = typedValue.getValue(); - if (value instanceof Long) { - longValues.add((Long) value); + if (value instanceof Long longValue) { + longValues.add(longValue); } else { Long longValue = Long.valueOf(value.toString()); @@ -191,8 +191,8 @@ protected List convertValuesToDouble(List typedValues) throw // check if it is a double or a string of a decimal number Object value = typedValue.getValue(); - if (value instanceof Double) { - doubleValues.add((Double) value); + if (value instanceof Double doubleValue) { + doubleValues.add(doubleValue); } else { Double doubleValue = Double.valueOf(value.toString()); diff --git a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/metrics/DmnEngineMetricCollectorWrapper.java b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/metrics/DmnEngineMetricCollectorWrapper.java index cb26c19ccb3..40b0b30b963 100644 --- a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/metrics/DmnEngineMetricCollectorWrapper.java +++ b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/metrics/DmnEngineMetricCollectorWrapper.java @@ -45,8 +45,8 @@ public void notify(DmnDecisionEvaluationEvent evaluationEvent) { } protected void notifyCollector(DmnDecisionLogicEvaluationEvent evaluationEvent) { - if (evaluationEvent instanceof DmnDecisionTableEvaluationEvent) { - collector.notify((DmnDecisionTableEvaluationEvent) evaluationEvent); + if (evaluationEvent instanceof DmnDecisionTableEvaluationEvent dmnEvent) { + collector.notify(dmnEvent); } // ignore other evaluation events since the collector is implemented as decision table evaluation listener } diff --git a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/BooleanDataTypeTransformer.java b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/BooleanDataTypeTransformer.java index e47b5cc17f3..73130f79103 100644 --- a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/BooleanDataTypeTransformer.java +++ b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/BooleanDataTypeTransformer.java @@ -30,11 +30,11 @@ public class BooleanDataTypeTransformer implements DmnDataTypeTransformer { @Override public TypedValue transform(Object value) throws IllegalArgumentException { - if (value instanceof Boolean) { - return Variables.booleanValue((Boolean) value); + if (value instanceof Boolean booleanValue) { + return Variables.booleanValue(booleanValue); - } else if (value instanceof String) { - boolean booleanValue = transformString((String) value); + } else if (value instanceof String stringValue) { + boolean booleanValue = transformString(stringValue); return Variables.booleanValue(booleanValue); } else { diff --git a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/DateDataTypeTransformer.java b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/DateDataTypeTransformer.java index 7c11fa90cdf..a0cc8208ea0 100644 --- a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/DateDataTypeTransformer.java +++ b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/DateDataTypeTransformer.java @@ -49,22 +49,22 @@ public class DateDataTypeTransformer implements DmnDataTypeTransformer { @Override public TypedValue transform(Object value) throws IllegalArgumentException { - if (value instanceof Date) { - return Variables.dateValue((Date) value); + if (value instanceof Date dateValue) { + return Variables.dateValue(dateValue); - } else if (value instanceof String) { - Date date = transformString((String) value); + } else if (value instanceof String stringValue) { + Date date = transformString(stringValue); return Variables.dateValue(date); - } if (value instanceof ZonedDateTime) { - Instant instant = ((ZonedDateTime) value).toInstant(); + } if (value instanceof ZonedDateTime zonedDateTimeValue) { + Instant instant = (zonedDateTimeValue).toInstant(); Date date = Date.from(instant); return Variables.dateValue(date); - } else if (value instanceof LocalDateTime) { + } else if (value instanceof LocalDateTime localDateTimeValue) { ZoneId defaultTimeZone = ZoneId.systemDefault(); - Instant instant = ((LocalDateTime) value) + Instant instant = localDateTimeValue .atZone(defaultTimeZone) .toInstant(); diff --git a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/DoubleDataTypeTransformer.java b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/DoubleDataTypeTransformer.java index c02d88101ee..61e9d34345b 100644 --- a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/DoubleDataTypeTransformer.java +++ b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/DoubleDataTypeTransformer.java @@ -30,12 +30,12 @@ public class DoubleDataTypeTransformer implements DmnDataTypeTransformer { @Override public TypedValue transform(Object value) throws IllegalArgumentException { - if (value instanceof Number) { - double doubleValue = transformNumber((Number) value); + if (value instanceof Number numberValue) { + double doubleValue = transformNumber(numberValue); return Variables.doubleValue(doubleValue); - } else if (value instanceof String) { - double doubleValue = transformString((String) value); + } else if (value instanceof String stringValue) { + double doubleValue = transformString(stringValue); return Variables.doubleValue(doubleValue); } else { diff --git a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/IntegerDataTypeTransformer.java b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/IntegerDataTypeTransformer.java index 300ae45bcf3..e93e3f605e4 100644 --- a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/IntegerDataTypeTransformer.java +++ b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/IntegerDataTypeTransformer.java @@ -30,12 +30,12 @@ public class IntegerDataTypeTransformer implements DmnDataTypeTransformer { @Override public TypedValue transform(Object value) throws IllegalArgumentException { - if (value instanceof Number) { - int intValue = transformNumber((Number) value); + if (value instanceof Number numberValue) { + int intValue = transformNumber(numberValue); return Variables.integerValue(intValue); - } else if (value instanceof String) { - int intValue = transformString((String) value); + } else if (value instanceof String stringValue) { + int intValue = transformString(stringValue); return Variables.integerValue(intValue); } else { diff --git a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/LongDataTypeTransformer.java b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/LongDataTypeTransformer.java index a9e7d196f52..9c13ce931a0 100644 --- a/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/LongDataTypeTransformer.java +++ b/engine-dmn/engine/src/main/java/org/operaton/bpm/dmn/engine/impl/type/LongDataTypeTransformer.java @@ -31,12 +31,12 @@ public class LongDataTypeTransformer implements DmnDataTypeTransformer { @Override public TypedValue transform(Object value) throws IllegalArgumentException { - if (value instanceof Number) { - long longValue = transformNumber((Number) value); + if (value instanceof Number numberValue) { + long longValue = transformNumber(numberValue); return Variables.longValue(longValue); - } else if (value instanceof String) { - long longValue = transformString((String) value); + } else if (value instanceof String stringValue) { + long longValue = transformString(stringValue); return Variables.longValue(longValue); } else { From ceceba6dc8905cc1b4bf953278d2aaab46c0def0 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Mon, 4 Nov 2024 22:39:44 +0100 Subject: [PATCH 07/37] fix(client): load local file variable (#4594) related to: #4523 Backported commit f06cb967dd from the camunda-bpm-platform repository. Original author: Gergely Juhasz --- .../operaton/bpm/client/impl/EngineClient.java | 15 +++++++-------- .../bpm/client/task/impl/ExternalTaskImpl.java | 9 +++++++++ .../impl/value/DeferredFileValueImpl.java | 16 ++++++++++++++-- .../client/variable/value/DeferredFileValue.java | 16 ++++++++++++++++ 4 files changed, 46 insertions(+), 10 deletions(-) diff --git a/clients/java/client/src/main/java/org/operaton/bpm/client/impl/EngineClient.java b/clients/java/client/src/main/java/org/operaton/bpm/client/impl/EngineClient.java index 43e4b3a49bb..927aed3cb5c 100644 --- a/clients/java/client/src/main/java/org/operaton/bpm/client/impl/EngineClient.java +++ b/clients/java/client/src/main/java/org/operaton/bpm/client/impl/EngineClient.java @@ -52,11 +52,10 @@ public class EngineClient { public static final String FAILURE_RESOURCE_PATH = ID_RESOURCE_PATH + "/failure"; public static final String BPMN_ERROR_RESOURCE_PATH = ID_RESOURCE_PATH + "/bpmnError"; public static final String NAME_PATH_PARAM = "{name}"; - public static final String EXECUTION_RESOURCE_PATH = "/execution"; - public static final String EXECUTION_ID_RESOURCE_PATH = EXECUTION_RESOURCE_PATH + "/" + ID_PATH_PARAM; - public static final String GET_LOCAL_VARIABLE = EXECUTION_ID_RESOURCE_PATH + "/localVariables/" + NAME_PATH_PARAM; - public static final String GET_LOCAL_BINARY_VARIABLE = GET_LOCAL_VARIABLE + "/data"; - + public static final String PROCESS_INSTANCE_RESOURCE_PATH = "/process-instance"; + public static final String PROCESS_INSTANCE_ID_RESOURCE_PATH = PROCESS_INSTANCE_RESOURCE_PATH + "/" + ID_PATH_PARAM; + public static final String GET_BINARY_VARIABLE = + PROCESS_INSTANCE_ID_RESOURCE_PATH + "/variables/" + NAME_PATH_PARAM + "/data"; protected String baseUrl; protected String workerId; protected int maxTasks; @@ -147,9 +146,9 @@ public void extendLock(String taskId, long newDuration) { engineInteraction.postRequest(resourceUrl, payload, Void.class); } - public byte[] getLocalBinaryVariable(String variableName, String processInstanceId) { - String resourcePath = baseUrl + GET_LOCAL_BINARY_VARIABLE - .replace(ID_PATH_PARAM, processInstanceId) + public byte[] getLocalBinaryVariable(String variableName, String executionId) { + String resourcePath = baseUrl + GET_BINARY_VARIABLE + .replace(ID_PATH_PARAM, executionId) .replace(NAME_PATH_PARAM, variableName); return engineInteraction.getRequest(resourcePath); diff --git a/clients/java/client/src/main/java/org/operaton/bpm/client/task/impl/ExternalTaskImpl.java b/clients/java/client/src/main/java/org/operaton/bpm/client/task/impl/ExternalTaskImpl.java index efa9ea7d64f..171debec1fa 100644 --- a/clients/java/client/src/main/java/org/operaton/bpm/client/task/impl/ExternalTaskImpl.java +++ b/clients/java/client/src/main/java/org/operaton/bpm/client/task/impl/ExternalTaskImpl.java @@ -25,6 +25,7 @@ import org.operaton.bpm.client.task.ExternalTask; import org.operaton.bpm.client.variable.impl.TypedValueField; import org.operaton.bpm.client.variable.impl.VariableValue; +import org.operaton.bpm.client.variable.value.DeferredFileValue; import org.operaton.bpm.engine.variable.VariableMap; import org.operaton.bpm.engine.variable.Variables; import org.operaton.bpm.engine.variable.value.TypedValue; @@ -257,6 +258,10 @@ public T getVariable(String variableName) { VariableValue variableValue = receivedVariableMap.get(variableName); if (variableValue != null) { + if(variableValue.getTypedValue() instanceof DeferredFileValue) { + DeferredFileValue deferredFileValue = (DeferredFileValue) variableValue.getTypedValue(); + deferredFileValue.setExecutionId(this.executionId); + } value = (T) variableValue.getValue(); } @@ -295,6 +300,10 @@ public T getVariableTyped(String variableName, boolean de VariableValue variableValue = receivedVariableMap.get(variableName); if (variableValue != null) { typedValue = variableValue.getTypedValue(deserializeObjectValues); + if(typedValue instanceof DeferredFileValue) { + DeferredFileValue deferredFileValue = (DeferredFileValue) typedValue; + deferredFileValue.setExecutionId(this.executionId); + } } return (T) typedValue; diff --git a/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/value/DeferredFileValueImpl.java b/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/value/DeferredFileValueImpl.java index ba83d17c056..80510842f79 100644 --- a/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/value/DeferredFileValueImpl.java +++ b/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/value/DeferredFileValueImpl.java @@ -39,6 +39,7 @@ public class DeferredFileValueImpl extends FileValueImpl implements DeferredFile protected String variableName; protected String processInstanceId; protected EngineClient engineClient; + protected String executionId = null; public DeferredFileValueImpl(String filename, EngineClient engineClient) { super(PrimitiveValueType.FILE, filename); @@ -47,7 +48,7 @@ public DeferredFileValueImpl(String filename, EngineClient engineClient) { protected void load() { try { - byte[] bytes = engineClient.getLocalBinaryVariable(variableName, processInstanceId); + byte[] bytes = engineClient.getLocalBinaryVariable(variableName, executionId); setValue(bytes); this.isLoaded = true; @@ -79,9 +80,20 @@ public void setVariableName(String variableName) { this.variableName = variableName; } + @Override + public void setExecutionId(String executionId){ + this.executionId = executionId; + }; + + @Override + public String getExecutionId() { + return executionId; + } + @Override public String toString() { - return "DeferredFileValueImpl [mimeType=" + mimeType + ", filename=" + filename + ", type=" + type + ", isTransient=" + isTransient + ", isLoaded=" + isLoaded + "]"; + return "DeferredFileValueImpl [mimeType=" + mimeType + ", filename=" + filename + ", type=" + type + ", " + + "isTransient=" + isTransient + ", isLoaded=" + isLoaded + ", processInstanceId" + processInstanceId + ", executionId" + executionId + "]"; } } diff --git a/clients/java/client/src/main/java/org/operaton/bpm/client/variable/value/DeferredFileValue.java b/clients/java/client/src/main/java/org/operaton/bpm/client/variable/value/DeferredFileValue.java index fdc1a924b6e..a7bfc82e9dc 100644 --- a/clients/java/client/src/main/java/org/operaton/bpm/client/variable/value/DeferredFileValue.java +++ b/clients/java/client/src/main/java/org/operaton/bpm/client/variable/value/DeferredFileValue.java @@ -39,4 +39,20 @@ public interface DeferredFileValue extends FileValue { */ boolean isLoaded(); + /** + * Sets the executionId, which defines the scope of the DeferredFileValue. + * This identifier ensures that the correct scope is applied when loading the file value. + * + * @param executionId defines the scope of the DeferredFileValue + */ + void setExecutionId(String executionId); + + /** + * Returns the executionId, which specifies the scope of the DeferredFileValue. + * This identifier ensures that the correct scope is applied when loading the file value. + * + * @return the executionId which defines the scope of the DeferredFileValue + */ + String getExecutionId(); + } From d3912cac3d920d3d3018d592d17f150516fb6d90 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Mon, 4 Nov 2024 22:41:14 +0100 Subject: [PATCH 08/37] chore(docs): Fix sortOrder case in fetch and lock rest api example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related to https://github.com/camunda/camunda-bpm-platform/issues/4608 Backported commit 16f5002bdf from the camunda-bpm-platform repository. Original author: Joaquín --- .../main/templates/paths/external-task/fetchAndLock/post.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/external-task/fetchAndLock/post.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/external-task/fetchAndLock/post.ftl index 379a5d12964..9c236360571 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/external-task/fetchAndLock/post.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/external-task/fetchAndLock/post.ftl @@ -70,7 +70,7 @@ "sorting": [ { "sortBy":"createTime", - "sortOrder":"ASC" + "sortOrder":"asc" } ] } From 230ee7d7ee2ca2f2cc7b8c710a9a6f8c8c1f81ad Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Mon, 4 Nov 2024 15:56:39 +0100 Subject: [PATCH 09/37] chore(distro/tomcat/assembly): Add Juel to distro/lib Folder Context: This fix adds juel to distro/lib folder. Fixes: NoClassDefFound errors that users who copy distro/lib dependencies experience when starting with a Manual Installation of Tomcat 10 Related-to: https://github.com/camunda/camunda-bpm-platform/issues/4573 Backported commit 2fa8c6324c from the camunda-bpm-platform repository. Original author: psavidis <69160690+psavidis@users.noreply.github.com> --- distro/tomcat/assembly/assembly.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/distro/tomcat/assembly/assembly.xml b/distro/tomcat/assembly/assembly.xml index a896496ae50..7d8e8bbb04c 100644 --- a/distro/tomcat/assembly/assembly.xml +++ b/distro/tomcat/assembly/assembly.xml @@ -111,6 +111,7 @@ org.operaton.bpm.model:*:jar org.operaton.bpm.dmn:*:jar + org.operaton.bpm.juel:*:jar org.camunda.feel:*:jar From db0f12dec7053afe3ea313d1fca7d303a4e5d716 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Mon, 4 Nov 2024 16:07:42 +0100 Subject: [PATCH 10/37] feat(engine, engine-rest): Expose restartedProcessInstanceId Context: This commit introduces restartedProcessInstanceId for historic process instances. Why: To be able to track the originating process instances in restart - batch operations. Db-Migration: The commit introduces - RESTARTED_PROC_INST_ID_ column in ACT_HI_PROCINST table - ACT_IDX_HI_PRO_RST_PRO_INST_ID index on the above Unit-tests: Adds a unit test for verified the population of the column for completed and restarted process instances Related-to - https://github.com/camunda/camunda-bpm-platform/issues/4214 - https://github.com/camunda/camunda-bpm-platform/issues/4201 Backported commit 0509c7b114 from the camunda-bpm-platform repository. Original author: punitdarira --- .../history/HistoricProcessInstanceDto.ftl | 7 +++- .../paths/history/process-instance/get.ftl | 3 +- .../paths/history/process-instance/post.ftl | 3 +- .../history/process-instance/{id}/get.ftl | 3 +- .../history/HistoricProcessInstanceDto.java | 11 +++++ .../bpm/engine/rest/helper/MockProvider.java | 1 + ...essInstanceRestServiceInteractionTest.java | 2 + ...icProcessInstanceRestServiceQueryTest.java | 2 + .../history/HistoricProcessInstance.java | 5 +++ .../impl/ProcessInstantiationBuilderImpl.java | 10 +++++ .../impl/cmd/RestartProcessInstancesCmd.java | 3 +- .../StartProcessInstanceAtActivitiesCmd.java | 2 + .../HistoricProcessInstanceEventEntity.java | 12 ++++++ .../producer/DefaultHistoryEventProducer.java | 1 + .../persistence/entity/ExecutionEntity.java | 13 ++++++ .../db/create/activiti.db2.create.history.sql | 2 + .../db/create/activiti.h2.create.history.sql | 2 + .../activiti.mariadb.create.history.sql | 2 + .../create/activiti.mssql.create.history.sql | 2 + .../create/activiti.mysql.create.history.sql | 2 + .../create/activiti.oracle.create.history.sql | 2 + .../activiti.postgres.create.history.sql | 2 + .../db/drop/activiti.db2.drop.history.sql | 1 + .../db/drop/activiti.h2.drop.history.sql | 1 + .../db/drop/activiti.mariadb.drop.history.sql | 1 + .../db/drop/activiti.mssql.drop.history.sql | 1 + .../db/drop/activiti.mysql.drop.history.sql | 1 + .../db/drop/activiti.oracle.drop.history.sql | 1 + .../drop/activiti.postgres.drop.history.sql | 1 + .../db/upgrade/db2_engine_7.21_to_7.22.sql | 4 ++ .../db/upgrade/h2_engine_7.21_to_7.22.sql | 3 ++ .../upgrade/mariadb_engine_7.21_to_7.22.sql | 3 ++ .../db/upgrade/mssql_engine_7.21_to_7.22.sql | 3 ++ .../db/upgrade/mysql_engine_7.21_to_7.22.sql | 3 ++ .../db/upgrade/oracle_engine_7.21_to_7.22.sql | 3 ++ .../upgrade/postgres_engine_7.21_to_7.22.sql | 3 ++ .../entity/HistoricProcessInstance.xml | 7 +++- .../RestartProcessInstanceAsyncTest.java | 41 +++++++++++++++++++ .../RestartProcessInstanceSyncTest.java | 5 +++ .../HistoricProcessInstanceStateTest.java | 2 + 40 files changed, 169 insertions(+), 7 deletions(-) diff --git a/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceDto.ftl b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceDto.ftl index 6a47adab83e..3ff9134d65f 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceDto.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceDto.ftl @@ -101,7 +101,6 @@ name = "state" type = "string" enumValues = ["ACTIVE", "SUSPENDED", "COMPLETED", "EXTERNALLY_TERMINATED", "INTERNALLY_TERMINATED"] - last = true desc = "Last state of the process instance, possible values are: `ACTIVE` - running process instance @@ -114,5 +113,11 @@ `INTERNALLY_TERMINATED` - terminated internally, for instance by terminating boundary event"/> + <@lib.property + name = "restartedProcessInstanceId" + type = "string" + desc = "The id of the original process instance which was restarted." + last = true /> + \ No newline at end of file diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/get.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/get.ftl index c3ba6c8843e..e315a9842e8 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/get.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/get.ftl @@ -53,7 +53,8 @@ "superCaseInstanceId":null, "caseInstanceId":null, "tenantId":null, - "state":"ACTIVE" + "state":"ACTIVE", + "restartedProcessInstanceId":"2bef365d-3406-11ef-bd73-0a0027000003" } ] }'] /> diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/post.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/post.ftl index ecbfa354206..4a1ff6e53cc 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/post.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/post.ftl @@ -78,7 +78,8 @@ "superCaseInstanceId":null, "caseInstanceId":null, "tenantId":null, - "state":"ACTIVE" + "state":"ACTIVE", + "restartedProcessInstanceId":"2bef365d-3406-11ef-bd73-0a0027000003" } ] }'] /> diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/{id}/get.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/{id}/get.ftl index 8cb0e8f502a..e26e84a4490 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/{id}/get.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/process-instance/{id}/get.ftl @@ -46,7 +46,8 @@ "superCaseInstanceId":null, "caseInstanceId":null, "tenantId":null, - "state":"ACTIVE" + "state":"ACTIVE", + "restartedProcessInstanceId":"2bef365d-3406-11ef-bd73-0a0027000003" } }'] /> diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceDto.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceDto.java index fbc470d2a3a..cfdb502a9d2 100644 --- a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceDto.java +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricProcessInstanceDto.java @@ -40,6 +40,7 @@ public class HistoricProcessInstanceDto { private String caseInstanceId; private String tenantId; private String state; + private String restartedProcessInstanceId; public String getId() { return id; @@ -129,6 +130,15 @@ public void setRootProcessInstanceId(String rootProcessInstanceId) { this.rootProcessInstanceId = rootProcessInstanceId; } + public String getRestartedProcessInstanceId() { + return restartedProcessInstanceId; + } + + public void setRestartedProcessInstanceId(String restartedProcessInstanceId) { + this.restartedProcessInstanceId = restartedProcessInstanceId; + } + + public static HistoricProcessInstanceDto fromHistoricProcessInstance(HistoricProcessInstance historicProcessInstance) { HistoricProcessInstanceDto dto = new HistoricProcessInstanceDto(); @@ -152,6 +162,7 @@ public static HistoricProcessInstanceDto fromHistoricProcessInstance(HistoricPro dto.caseInstanceId = historicProcessInstance.getCaseInstanceId(); dto.tenantId = historicProcessInstance.getTenantId(); dto.state = historicProcessInstance.getState(); + dto.restartedProcessInstanceId = historicProcessInstance.getRestartedProcessInstanceId(); return dto; } diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java index 2f054bd8feb..7d925969c0e 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java @@ -2183,6 +2183,7 @@ public static HistoricProcessInstance createMockHistoricProcessInstance(String t when(mock.getCaseInstanceId()).thenReturn(EXAMPLE_HISTORIC_PROCESS_INSTANCE_CASE_INSTANCE_ID); when(mock.getTenantId()).thenReturn(tenantId); when(mock.getState()).thenReturn(EXAMPLE_HISTORIC_PROCESS_INSTANCE_STATE); + when(mock.getRestartedProcessInstanceId()).thenReturn(EXAMPLE_PROCESS_INSTANCE_ID); return mock; } diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceInteractionTest.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceInteractionTest.java index 5a853c12e63..748b78af686 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceInteractionTest.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceInteractionTest.java @@ -123,6 +123,7 @@ public void testGetSingleInstance() { String returnedCaseInstanceId = from(content).getString("caseInstanceId"); String returnedTenantId = from(content).getString("tenantId"); String returnedState = from(content).getString("state"); + String restartedProcessInstanceId = from(content).getString("restartedProcessInstanceId"); Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_ID, returnedProcessInstanceId); Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_BUSINESS_KEY, returnedProcessInstanceBusinessKey); @@ -139,6 +140,7 @@ public void testGetSingleInstance() { Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_CASE_INSTANCE_ID, returnedCaseInstanceId); Assert.assertEquals(MockProvider.EXAMPLE_TENANT_ID, returnedTenantId); Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_STATE, returnedState); + Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_ID, restartedProcessInstanceId); } diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java index e63bf12bbb9..218aef19822 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java @@ -429,6 +429,7 @@ public void testSimpleHistoricProcessQuery() { String returnedCaseInstanceId = from(content).getString("[0].caseInstanceId"); String returnedTenantId = from(content).getString("[0].tenantId"); String returnedState = from(content).getString("[0].state"); + String restartedProcessInstanceId = from(content).getString("[0].restartedProcessInstanceId"); Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_ID, returnedProcessInstanceId); Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_BUSINESS_KEY, returnedProcessInstanceBusinessKey); @@ -449,6 +450,7 @@ public void testSimpleHistoricProcessQuery() { Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_CASE_INSTANCE_ID, returnedCaseInstanceId); Assert.assertEquals(MockProvider.EXAMPLE_TENANT_ID, returnedTenantId); Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_STATE, returnedState); + Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_ID, restartedProcessInstanceId); } @Test diff --git a/engine/src/main/java/org/operaton/bpm/engine/history/HistoricProcessInstance.java b/engine/src/main/java/org/operaton/bpm/engine/history/HistoricProcessInstance.java index 8eb1422c0de..0b827cd69d6 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/history/HistoricProcessInstance.java +++ b/engine/src/main/java/org/operaton/bpm/engine/history/HistoricProcessInstance.java @@ -118,4 +118,9 @@ public interface HistoricProcessInstance { * STATE_INTERNALLY_TERMINATED - terminated internally, for instance by terminating boundary event */ String getState(); + + /** + * The id of the original process instance which was restarted. + */ + String getRestartedProcessInstanceId(); } diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/ProcessInstantiationBuilderImpl.java b/engine/src/main/java/org/operaton/bpm/engine/impl/ProcessInstantiationBuilderImpl.java index 9e226ecdae2..d48ff2e1e39 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/ProcessInstantiationBuilderImpl.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/ProcessInstantiationBuilderImpl.java @@ -50,6 +50,8 @@ public class ProcessInstantiationBuilderImpl implements ProcessInstantiationBuil protected String processDefinitionTenantId; protected boolean isProcessDefinitionTenantIdSet = false; + protected String restartedProcessInstanceId; + protected ProcessInstanceModificationBuilderImpl modificationBuilder; protected ProcessInstantiationBuilderImpl(CommandExecutor commandExecutor) { @@ -206,6 +208,14 @@ public void setModificationBuilder(ProcessInstanceModificationBuilderImpl modifi this.modificationBuilder = modificationBuilder; } + public void setRestartedProcessInstanceId(String restartedProcessInstanceId){ + this.restartedProcessInstanceId = restartedProcessInstanceId; + } + + public String getRestartedProcessInstanceId(){ + return restartedProcessInstanceId; + } + public static ProcessInstantiationBuilder createProcessInstanceById(CommandExecutor commandExecutor, String processDefinitionId) { ProcessInstantiationBuilderImpl builder = new ProcessInstantiationBuilderImpl(commandExecutor); builder.processDefinitionId = processDefinitionId; diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/RestartProcessInstancesCmd.java b/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/RestartProcessInstancesCmd.java index a97c7335941..2f56f656ed8 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/RestartProcessInstancesCmd.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/RestartProcessInstancesCmd.java @@ -103,6 +103,8 @@ public Void execute(final CommandContext commandContext) { getProcessInstantiationBuilder(commandExecutor, processDefinitionId); applyProperties(instantiationBuilder, processDefinition, historicProcessInstance); + instantiationBuilder.setRestartedProcessInstanceId(processInstanceId); + ProcessInstanceModificationBuilderImpl modificationBuilder = instantiationBuilder.getModificationBuilder(); @@ -167,7 +169,6 @@ protected void applyProperties(ProcessInstantiationBuilderImpl instantiationBuil if (!builder.isWithoutBusinessKey()) { instantiationBuilder.businessKey(processInstance.getBusinessKey()); } - } protected VariableMap collectVariables(CommandContext commandContext, diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/StartProcessInstanceAtActivitiesCmd.java b/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/StartProcessInstanceAtActivitiesCmd.java index e083f276b05..abb57e0a6ef 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/StartProcessInstanceAtActivitiesCmd.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/StartProcessInstanceAtActivitiesCmd.java @@ -79,6 +79,8 @@ public ProcessInstanceWithVariables execute(CommandContext commandContext) { processInstance.setTenantId(instantiationBuilder.getTenantId()); } + processInstance.setRestartedProcessInstanceId(instantiationBuilder.getRestartedProcessInstanceId()); + processInstance.setSkipCustomListeners(modificationBuilder.isSkipCustomListeners()); VariableMap variables = modificationBuilder.getProcessVariables(); diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/history/event/HistoricProcessInstanceEventEntity.java b/engine/src/main/java/org/operaton/bpm/engine/impl/history/event/HistoricProcessInstanceEventEntity.java index 35492493ae4..bcba6c0df41 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/history/event/HistoricProcessInstanceEventEntity.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/history/event/HistoricProcessInstanceEventEntity.java @@ -54,6 +54,9 @@ public class HistoricProcessInstanceEventEntity extends HistoricScopeInstanceEve protected String state; + /** completed HPI that has been restarted */ + protected String restartedProcessInstanceId; + // getters / setters //////////////////////////////////////// public String getEndActivityId() { @@ -128,6 +131,14 @@ public void setState(String state) { this.state = state; } + public String getRestartedProcessInstanceId() { + return restartedProcessInstanceId; + } + + public void setRestartedProcessInstanceId(String restartedProcessInstanceId) { + this.restartedProcessInstanceId = restartedProcessInstanceId; + } + @Override public String toString() { return this.getClass().getSimpleName() @@ -149,6 +160,7 @@ public String toString() { + ", processDefinitionId=" + processDefinitionId + ", processInstanceId=" + processInstanceId + ", tenantId=" + tenantId + + ", restartedProcessInstanceId=" + restartedProcessInstanceId + "]"; } diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java b/engine/src/main/java/org/operaton/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java index d864a020b5e..38e3128262d 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java @@ -204,6 +204,7 @@ protected void initProcessInstanceEvent(HistoricProcessInstanceEventEntity evt, evt.setCaseInstanceId(caseInstanceId); evt.setTenantId(tenantId); evt.setRootProcessInstanceId(execution.getRootProcessInstanceId()); + evt.setRestartedProcessInstanceId(execution.getRestartedProcessInstanceId()); if (execution.getSuperCaseExecution() != null) { evt.setSuperCaseInstanceId(execution.getSuperCaseExecution().getCaseInstanceId()); diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/ExecutionEntity.java b/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/ExecutionEntity.java index 3c8c757ac23..66dae261461 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/ExecutionEntity.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/ExecutionEntity.java @@ -234,6 +234,11 @@ public class ExecutionEntity extends PvmExecutionImpl implements Execution, Proc */ protected String superCaseExecutionId; + /** + * Completed HPI that is being restarted through this ExecutionEntity + */ + protected String restartedProcessInstanceId; + /** * Contains observers which are observe the execution. * @since 7.6 @@ -970,6 +975,14 @@ public void setSuperCaseExecutionId(String superCaseExecutionId) { this.superCaseExecutionId = superCaseExecutionId; } + public String getRestartedProcessInstanceId(){ + return restartedProcessInstanceId; + } + + public void setRestartedProcessInstanceId(String restartedProcessInstanceId){ + this.restartedProcessInstanceId = restartedProcessInstanceId; + } + @Override public CaseExecutionEntity getSuperCaseExecution() { ensureSuperCaseExecutionInitialized(); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.history.sql index f4008b1d6ef..e4090b67ed8 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.history.sql @@ -35,6 +35,7 @@ create table ACT_HI_PROCINST ( DELETE_REASON_ varchar(4000), TENANT_ID_ varchar(64), STATE_ varchar(255), + RESTARTED_PROC_INST_ID_ varchar(64), primary key (ID_) ); @@ -340,6 +341,7 @@ create index ACT_IDX_HI_PRO_INST_PROC_TIME on ACT_HI_PROCINST(START_TIME_, END_T create index ACT_IDX_HI_PI_PDEFID_END_TIME on ACT_HI_PROCINST(PROC_DEF_ID_, END_TIME_); create index ACT_IDX_HI_PRO_INST_ROOT_PI on ACT_HI_PROCINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_PRO_INST_RM_TIME on ACT_HI_PROCINST(REMOVAL_TIME_); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); create index ACT_IDX_HI_ACTINST_ROOT_PI on ACT_HI_ACTINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_ACT_INST_START_END on ACT_HI_ACTINST(START_TIME_, END_TIME_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.history.sql index 52a04fde94c..ad8c4dd42e6 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.history.sql @@ -35,6 +35,7 @@ create table ACT_HI_PROCINST ( DELETE_REASON_ varchar(4000), TENANT_ID_ varchar(64), STATE_ varchar(255), + RESTARTED_PROC_INST_ID_ varchar(64), primary key (ID_), unique (PROC_INST_ID_) ); @@ -339,6 +340,7 @@ create index ACT_IDX_HI_PRO_INST_PROC_TIME on ACT_HI_PROCINST(START_TIME_, END_T create index ACT_IDX_HI_PI_PDEFID_END_TIME on ACT_HI_PROCINST(PROC_DEF_ID_, END_TIME_); create index ACT_IDX_HI_PRO_INST_ROOT_PI on ACT_HI_PROCINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_PRO_INST_RM_TIME on ACT_HI_PROCINST(REMOVAL_TIME_); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); create index ACT_IDX_HI_ACTINST_ROOT_PI on ACT_HI_ACTINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_ACT_INST_START_END on ACT_HI_ACTINST(START_TIME_, END_TIME_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.history.sql index 01a1cc72d12..e9c95f12f81 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.history.sql @@ -35,6 +35,7 @@ create table ACT_HI_PROCINST ( DELETE_REASON_ varchar(4000), TENANT_ID_ varchar(64), STATE_ varchar(255), + RESTARTED_PROC_INST_ID_ varchar(64), primary key (ID_), unique (PROC_INST_ID_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; @@ -339,6 +340,7 @@ create index ACT_IDX_HI_PRO_INST_PROC_TIME on ACT_HI_PROCINST(START_TIME_, END_T create index ACT_IDX_HI_PI_PDEFID_END_TIME on ACT_HI_PROCINST(PROC_DEF_ID_, END_TIME_); create index ACT_IDX_HI_PRO_INST_ROOT_PI on ACT_HI_PROCINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_PRO_INST_RM_TIME on ACT_HI_PROCINST(REMOVAL_TIME_); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); create index ACT_IDX_HI_ACTINST_ROOT_PI on ACT_HI_ACTINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_ACT_INST_START_END on ACT_HI_ACTINST(START_TIME_, END_TIME_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.history.sql index d6b3f9a6d06..27a26b37212 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.history.sql @@ -35,6 +35,7 @@ create table ACT_HI_PROCINST ( DELETE_REASON_ nvarchar(4000), TENANT_ID_ nvarchar(64), STATE_ nvarchar(255), + RESTARTED_PROC_INST_ID_ nvarchar(64), primary key (ID_), unique (PROC_INST_ID_) ); @@ -338,6 +339,7 @@ create index ACT_IDX_HI_PRO_INST_PROC_TIME on ACT_HI_PROCINST(START_TIME_, END_T create index ACT_IDX_HI_PI_PDEFID_END_TIME on ACT_HI_PROCINST(PROC_DEF_ID_, END_TIME_); create index ACT_IDX_HI_PRO_INST_ROOT_PI on ACT_HI_PROCINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_PRO_INST_RM_TIME on ACT_HI_PROCINST(REMOVAL_TIME_); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); create index ACT_IDX_HI_ACTINST_ROOT_PI on ACT_HI_ACTINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_ACT_INST_START_END on ACT_HI_ACTINST(START_TIME_, END_TIME_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.history.sql index 478f30ea48a..4c8d0720f44 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.history.sql @@ -35,6 +35,7 @@ create table ACT_HI_PROCINST ( DELETE_REASON_ varchar(4000), TENANT_ID_ varchar(64), STATE_ varchar(255), + RESTARTED_PROC_INST_ID_ varchar(64), primary key (ID_), unique (PROC_INST_ID_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; @@ -340,6 +341,7 @@ create index ACT_IDX_HI_PRO_INST_PROC_TIME on ACT_HI_PROCINST(START_TIME_, END_T create index ACT_IDX_HI_PI_PDEFID_END_TIME on ACT_HI_PROCINST(PROC_DEF_ID_, END_TIME_); create index ACT_IDX_HI_PRO_INST_ROOT_PI on ACT_HI_PROCINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_PRO_INST_RM_TIME on ACT_HI_PROCINST(REMOVAL_TIME_); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); create index ACT_IDX_HI_ACTINST_ROOT_PI on ACT_HI_ACTINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_ACT_INST_START_END on ACT_HI_ACTINST(START_TIME_, END_TIME_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.history.sql index 430ed1ee56d..ffe27b569ff 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.history.sql @@ -35,6 +35,7 @@ create table ACT_HI_PROCINST ( DELETE_REASON_ NVARCHAR2(2000), TENANT_ID_ NVARCHAR2(64), STATE_ NVARCHAR2(255), + RESTARTED_PROC_INST_ID_ NVARCHAR2(64), primary key (ID_), unique (PROC_INST_ID_) ); @@ -339,6 +340,7 @@ create index ACT_IDX_HI_PRO_INST_PROC_TIME on ACT_HI_PROCINST(START_TIME_, END_T create index ACT_IDX_HI_PI_PDEFID_END_TIME on ACT_HI_PROCINST(PROC_DEF_ID_, END_TIME_); create index ACT_IDX_HI_PRO_INST_ROOT_PI on ACT_HI_PROCINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_PRO_INST_RM_TIME on ACT_HI_PROCINST(REMOVAL_TIME_); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); create index ACT_IDX_HI_ACTINST_ROOT_PI on ACT_HI_ACTINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_ACT_INST_START_END on ACT_HI_ACTINST(START_TIME_, END_TIME_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.history.sql index 2126975e74a..aa111103f25 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.history.sql @@ -35,6 +35,7 @@ create table ACT_HI_PROCINST ( DELETE_REASON_ varchar(4000), TENANT_ID_ varchar(64), STATE_ varchar(255), + RESTARTED_PROC_INST_ID_ varchar(64), primary key (ID_), unique (PROC_INST_ID_) ); @@ -339,6 +340,7 @@ create index ACT_IDX_HI_PRO_INST_PROC_TIME on ACT_HI_PROCINST(START_TIME_, END_T create index ACT_IDX_HI_PI_PDEFID_END_TIME on ACT_HI_PROCINST(PROC_DEF_ID_, END_TIME_); create index ACT_IDX_HI_PRO_INST_ROOT_PI on ACT_HI_PROCINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_PRO_INST_RM_TIME on ACT_HI_PROCINST(REMOVAL_TIME_); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); create index ACT_IDX_HI_ACTINST_ROOT_PI on ACT_HI_ACTINST(ROOT_PROC_INST_ID_); create index ACT_IDX_HI_ACT_INST_START_END on ACT_HI_ACTINST(START_TIME_, END_TIME_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.db2.drop.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.db2.drop.history.sql index bdd56029478..9d8be4d3f31 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.db2.drop.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.db2.drop.history.sql @@ -23,6 +23,7 @@ drop index ACT_IDX_HI_PRO_INST_PROC_TIME; drop index ACT_IDX_HI_PI_PDEFID_END_TIME; drop index ACT_IDX_HI_PRO_INST_ROOT_PI; drop index ACT_IDX_HI_PRO_INST_RM_TIME; +drop index ACT_IDX_HI_PRO_RST_PRO_INST_ID; drop index ACT_IDX_HI_ACTINST_ROOT_PI; drop index ACT_IDX_HI_ACT_INST_START_END; diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.h2.drop.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.h2.drop.history.sql index 8bf4e2a4655..bc856ed8645 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.h2.drop.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.h2.drop.history.sql @@ -23,6 +23,7 @@ drop index ACT_IDX_HI_PRO_INST_PROC_TIME; drop index ACT_IDX_HI_PI_PDEFID_END_TIME; drop index ACT_IDX_HI_PRO_INST_ROOT_PI; drop index ACT_IDX_HI_PRO_INST_RM_TIME; +drop index ACT_IDX_HI_PRO_RST_PRO_INST_ID; drop index ACT_IDX_HI_ACTINST_ROOT_PI; drop index ACT_IDX_HI_ACT_INST_START_END; diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mariadb.drop.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mariadb.drop.history.sql index 2fff71cc558..0cebb8ea81f 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mariadb.drop.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mariadb.drop.history.sql @@ -23,6 +23,7 @@ drop index ACT_IDX_HI_PRO_INST_PROC_TIME on ACT_HI_PROCINST; drop index ACT_IDX_HI_PI_PDEFID_END_TIME on ACT_HI_PROCINST; drop index ACT_IDX_HI_PRO_INST_ROOT_PI on ACT_HI_PROCINST; drop index ACT_IDX_HI_PRO_INST_RM_TIME on ACT_HI_PROCINST; +drop index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST; drop index ACT_IDX_HI_ACTINST_ROOT_PI on ACT_HI_ACTINST; drop index ACT_IDX_HI_ACT_INST_START_END on ACT_HI_ACTINST; diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mssql.drop.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mssql.drop.history.sql index 3cbce879033..de4b0ab35b7 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mssql.drop.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mssql.drop.history.sql @@ -23,6 +23,7 @@ drop index ACT_HI_PROCINST.ACT_IDX_HI_PRO_INST_PROC_TIME; drop index ACT_HI_PROCINST.ACT_IDX_HI_PI_PDEFID_END_TIME; drop index ACT_HI_PROCINST.ACT_IDX_HI_PRO_INST_ROOT_PI; drop index ACT_HI_PROCINST.ACT_IDX_HI_PRO_INST_RM_TIME; +drop index ACT_HI_PROCINST.ACT_IDX_HI_PRO_RST_PRO_INST_ID; drop index ACT_HI_ACTINST.ACT_IDX_HI_ACTINST_ROOT_PI; drop index ACT_HI_ACTINST.ACT_IDX_HI_ACT_INST_START_END; diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mysql.drop.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mysql.drop.history.sql index cc7fae60ffd..e63914408cb 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mysql.drop.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.mysql.drop.history.sql @@ -23,6 +23,7 @@ drop index ACT_IDX_HI_PRO_INST_PROC_TIME on ACT_HI_PROCINST; drop index ACT_IDX_HI_PI_PDEFID_END_TIME on ACT_HI_PROCINST; drop index ACT_IDX_HI_PRO_INST_ROOT_PI on ACT_HI_PROCINST; drop index ACT_IDX_HI_PRO_INST_RM_TIME on ACT_HI_PROCINST; +drop index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST; drop index ACT_IDX_HI_ACTINST_ROOT_PI on ACT_HI_ACTINST; drop index ACT_IDX_HI_ACT_INST_START_END on ACT_HI_ACTINST; diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.oracle.drop.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.oracle.drop.history.sql index b7318b2807f..e6acb942fd6 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.oracle.drop.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.oracle.drop.history.sql @@ -23,6 +23,7 @@ drop index ACT_IDX_HI_PRO_INST_PROC_TIME; drop index ACT_IDX_HI_PI_PDEFID_END_TIME; drop index ACT_IDX_HI_PRO_INST_ROOT_PI; drop index ACT_IDX_HI_PRO_INST_RM_TIME; +drop index ACT_IDX_HI_PRO_RST_PRO_INST_ID; drop index ACT_IDX_HI_ACTINST_ROOT_PI; drop index ACT_IDX_HI_ACT_INST_START_END; diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.postgres.drop.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.postgres.drop.history.sql index 5f9c798074d..bb0e521ff91 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.postgres.drop.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/drop/activiti.postgres.drop.history.sql @@ -23,6 +23,7 @@ drop index ACT_IDX_HI_PRO_INST_PROC_TIME; drop index ACT_IDX_HI_PI_PDEFID_END_TIME; drop index ACT_IDX_HI_PRO_INST_ROOT_PI; drop index ACT_IDX_HI_PRO_INST_RM_TIME; +drop index ACT_IDX_HI_PRO_RST_PRO_INST_ID; drop index ACT_IDX_HI_ACTINST_ROOT_PI; drop index ACT_IDX_HI_ACT_INST_START_END; diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/db2_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/db2_engine_7.21_to_7.22.sql index 7a8ada55ac2..566033c3f1a 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/db2_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/db2_engine_7.21_to_7.22.sql @@ -21,3 +21,7 @@ values ('1100', CURRENT_TIMESTAMP, '7.22.0'); alter table ACT_RU_TASK add column TASK_STATE_ varchar(64); alter table ACT_HI_TASKINST add column TASK_STATE_ varchar(64); + + +alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ varchar(64); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); \ No newline at end of file diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/h2_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/h2_engine_7.21_to_7.22.sql index 7a8ada55ac2..8918a9bdc81 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/h2_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/h2_engine_7.21_to_7.22.sql @@ -21,3 +21,6 @@ values ('1100', CURRENT_TIMESTAMP, '7.22.0'); alter table ACT_RU_TASK add column TASK_STATE_ varchar(64); alter table ACT_HI_TASKINST add column TASK_STATE_ varchar(64); + +alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ varchar(64); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mariadb_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mariadb_engine_7.21_to_7.22.sql index 7a8ada55ac2..8918a9bdc81 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mariadb_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mariadb_engine_7.21_to_7.22.sql @@ -21,3 +21,6 @@ values ('1100', CURRENT_TIMESTAMP, '7.22.0'); alter table ACT_RU_TASK add column TASK_STATE_ varchar(64); alter table ACT_HI_TASKINST add column TASK_STATE_ varchar(64); + +alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ varchar(64); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mssql_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mssql_engine_7.21_to_7.22.sql index 5c49433ff26..4e884d3918e 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mssql_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mssql_engine_7.21_to_7.22.sql @@ -21,3 +21,6 @@ values ('1100', CURRENT_TIMESTAMP, '7.22.0'); alter table ACT_RU_TASK add TASK_STATE_ nvarchar(64); alter table ACT_HI_TASKINST add TASK_STATE_ nvarchar(64); + +alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ nvarchar(64); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mysql_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mysql_engine_7.21_to_7.22.sql index 7a8ada55ac2..8918a9bdc81 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mysql_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mysql_engine_7.21_to_7.22.sql @@ -21,3 +21,6 @@ values ('1100', CURRENT_TIMESTAMP, '7.22.0'); alter table ACT_RU_TASK add column TASK_STATE_ varchar(64); alter table ACT_HI_TASKINST add column TASK_STATE_ varchar(64); + +alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ varchar(64); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/oracle_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/oracle_engine_7.21_to_7.22.sql index 1136a2087ef..235e7284d10 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/oracle_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/oracle_engine_7.21_to_7.22.sql @@ -21,3 +21,6 @@ values ('1100', CURRENT_TIMESTAMP, '7.22.0'); alter table ACT_RU_TASK add TASK_STATE_ NVARCHAR2(64); alter table ACT_HI_TASKINST add TASK_STATE_ NVARCHAR2(64); + +alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ NVARCHAR2(64); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/postgres_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/postgres_engine_7.21_to_7.22.sql index 7a8ada55ac2..8918a9bdc81 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/postgres_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/postgres_engine_7.21_to_7.22.sql @@ -21,3 +21,6 @@ values ('1100', CURRENT_TIMESTAMP, '7.22.0'); alter table ACT_RU_TASK add column TASK_STATE_ varchar(64); alter table ACT_HI_TASKINST add column TASK_STATE_ varchar(64); + +alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ varchar(64); +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/HistoricProcessInstance.xml b/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/HistoricProcessInstance.xml index 8b21d26ad67..23b0bcdd71c 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/HistoricProcessInstance.xml +++ b/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/HistoricProcessInstance.xml @@ -55,7 +55,8 @@ CASE_INST_ID_, DELETE_REASON_, TENANT_ID_, - STATE_ + STATE_, + RESTARTED_PROC_INST_ID_ ) values ( #{id ,jdbcType=VARCHAR}, #{processInstanceId, jdbcType=VARCHAR}, @@ -75,7 +76,8 @@ #{caseInstanceId, jdbcType=VARCHAR}, #{deleteReason, jdbcType=VARCHAR}, #{tenantId, jdbcType=VARCHAR}, - #{state, jdbcType=VARCHAR} + #{state, jdbcType=VARCHAR}, + #{restartedProcessInstanceId, jdbcType=VARCHAR} ) @@ -313,6 +315,7 @@ + diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/RestartProcessInstanceAsyncTest.java b/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/RestartProcessInstanceAsyncTest.java index d119c317319..18351ad5360 100644 --- a/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/RestartProcessInstanceAsyncTest.java +++ b/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/RestartProcessInstanceAsyncTest.java @@ -48,6 +48,7 @@ import org.operaton.bpm.engine.impl.cfg.multitenancy.TenantIdProviderCaseInstanceContext; import org.operaton.bpm.engine.impl.cfg.multitenancy.TenantIdProviderHistoricDecisionInstanceContext; import org.operaton.bpm.engine.impl.cfg.multitenancy.TenantIdProviderProcessInstanceContext; +import org.operaton.bpm.engine.impl.persistence.entity.HistoricProcessInstanceEntity; import org.operaton.bpm.engine.impl.util.ClockUtil; import org.operaton.bpm.engine.repository.ProcessDefinition; import org.operaton.bpm.engine.runtime.ActivityInstance; @@ -248,6 +249,46 @@ public void shouldRestartProcessInstance() { Assert.assertEquals(task2.getTaskDefinitionKey(), restartedTask.getTaskDefinitionKey()); } + @Test + public void shouldAssignRestartProcessInstanceIdOnlyToRestartedProcessInstances() { + // given process instances 1 and 2 + ProcessDefinition processDefinition = testRule.deployAndGetDefinition(ProcessModels.TWO_TASKS_PROCESS); + + var processInstance1 = runtimeService.startProcessInstanceByKey("Process"); + var processInstance2 = runtimeService.startProcessInstanceByKey("Process"); + + runtimeService.deleteProcessInstance(processInstance1.getId(), "test"); + runtimeService.deleteProcessInstance(processInstance2.getId(), "test"); + + // when process instance 1 is restarted + Batch batch = runtimeService.restartProcessInstances(processDefinition.getId()) + .startBeforeActivity("userTask1") + .processInstanceIds(processInstance1.getId()) + .executeAsync(); + + helper.completeSeedJobs(batch); + + helper.getExecutionJobs(batch).forEach(j -> assertEquals(processDefinition.getDeploymentId(), j.getDeploymentId())); + helper.completeExecutionJobs(batch); + helper.completeMonitorJobs(batch); + + // then the restartedProcessInstanceId should be populated only for the restarted process instance 1 + var restartedProcessInstance = runtimeService.createProcessInstanceQuery() + .active() + .singleResult(); + + var historicProcessInstance1 = (HistoricProcessInstanceEntity) historyService.createHistoricProcessInstanceQuery() + .processInstanceId(restartedProcessInstance.getId()) + .singleResult(); + + var historicProcessInstance2 = (HistoricProcessInstanceEntity) historyService.createHistoricProcessInstanceQuery() + .processInstanceId(processInstance2.getId()) + .singleResult(); + + assertThat(historicProcessInstance1.getRestartedProcessInstanceId()).isEqualTo(processInstance1.getId()); + assertThat(historicProcessInstance2.getRestartedProcessInstanceId()).isNull(); + } + @Test public void shouldRestartProcessInstanceWithParallelGateway() { // given diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/RestartProcessInstanceSyncTest.java b/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/RestartProcessInstanceSyncTest.java index d79c8abca82..5ee3d46f066 100644 --- a/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/RestartProcessInstanceSyncTest.java +++ b/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/RestartProcessInstanceSyncTest.java @@ -44,6 +44,7 @@ import org.operaton.bpm.engine.impl.cfg.multitenancy.TenantIdProviderHistoricDecisionInstanceContext; import org.operaton.bpm.engine.impl.cfg.multitenancy.TenantIdProviderProcessInstanceContext; import org.operaton.bpm.engine.impl.history.event.HistoricVariableUpdateEventEntity; +import org.operaton.bpm.engine.impl.persistence.entity.HistoricProcessInstanceEntity; import org.operaton.bpm.engine.repository.ProcessDefinition; import org.operaton.bpm.engine.runtime.ActivityInstance; import org.operaton.bpm.engine.runtime.Execution; @@ -122,6 +123,10 @@ public void shouldRestartSimpleProcessInstance() { ProcessInstance restartedProcessInstance = runtimeService.createProcessInstanceQuery().active().singleResult(); Task restartedTask = engineRule.getTaskService().createTaskQuery().processInstanceId(restartedProcessInstance.getId()).active().singleResult(); Assert.assertEquals(task.getTaskDefinitionKey(), restartedTask.getTaskDefinitionKey()); + + HistoricProcessInstanceEntity historicProcessInstanceEntity = (HistoricProcessInstanceEntity) historyService.createHistoricProcessInstanceQuery().processInstanceId(restartedProcessInstance.getId()).singleResult(); + Assert.assertEquals(processInstance.getId(), historicProcessInstanceEntity.getRestartedProcessInstanceId()); + } @Test diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceStateTest.java b/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceStateTest.java index a9c066c5bc0..e0e42c61990 100644 --- a/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceStateTest.java +++ b/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceStateTest.java @@ -83,6 +83,8 @@ public void testCompletedOnEndEvent() { ProcessDefinition processDefinition = processEngineTestRule.deployAndGetDefinition(instance); processEngineRule.getRuntimeService().startProcessInstanceById(processDefinition.getId()); HistoricProcessInstance entity = getHistoricProcessInstanceWithAssertion(processDefinition); + + assertThat(entity.getRestartedProcessInstanceId()).isNull(); assertThat(entity.getState()).isEqualTo(HistoricProcessInstance.STATE_COMPLETED); } From 4eda0948dbe8bdd83b833d0a774e02fe533cb24c Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 4 Nov 2024 09:06:54 +0000 Subject: [PATCH 11/37] chore(deps): bump com.ibm.db2:jcc from 11.5.0.0 to 11.5.9.0 Bumps com.ibm.db2:jcc from 11.5.0.0 to 11.5.9.0. --- updated-dependencies: - dependency-name: com.ibm.db2:jcc dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- database/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/pom.xml b/database/pom.xml index 082192f20ce..8ee94a7c920 100644 --- a/database/pom.xml +++ b/database/pom.xml @@ -24,7 +24,7 @@ 1.1.8 8.3.0 8.4.1.jre8 - 11.5.0.0 + 11.5.9.0 ${version.db2-11.5} 42.5.5 4.8.0 From e69be73b0808c5a2f83ae601fee6eea2bd95cfe9 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Tue, 5 Nov 2024 08:26:59 +0100 Subject: [PATCH 12/37] feat(tests): Enable ProcessEngineExtension to inject services into the super class of a test case This is to allow a class hierarchy where the base class is annotated with @ExtendWith(ProcessEngineExtension.class) and declares (protected/package private) fields for engine services. --- .../test/junit5/ProcessEngineExtension.java | 17 ++++++++++++++--- ...cessEngineExtensionSubTypeInjectionTest.java | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 test-utils/junit5-extension/src/test/java/org/operaton/bpm/engine/test/junit5/ProcessEngineExtensionSubTypeInjectionTest.java diff --git a/test-utils/junit5-extension/src/main/java/org/operaton/bpm/engine/test/junit5/ProcessEngineExtension.java b/test-utils/junit5-extension/src/main/java/org/operaton/bpm/engine/test/junit5/ProcessEngineExtension.java index a626a61ea74..eac300eb485 100644 --- a/test-utils/junit5-extension/src/main/java/org/operaton/bpm/engine/test/junit5/ProcessEngineExtension.java +++ b/test-utils/junit5-extension/src/main/java/org/operaton/bpm/engine/test/junit5/ProcessEngineExtension.java @@ -34,6 +34,7 @@ import java.lang.reflect.Method; import java.util.*; import java.util.function.Supplier; +import java.util.stream.Stream; /** * Junit 5 Extension to create and inject a {@link ProcessEngine} into the test class. @@ -60,6 +61,7 @@ * you can register the extension directly and use the builder pattern to configure it. *
* Usage with configuration: + * *

* Usage: *

@@ -216,10 +218,10 @@ public void postProcessTestInstance(Object testInstance, ExtensionContext contex // allow other extensions to access the engine instance created by this extension context.getStore(ExtensionContext.Namespace.create("Operaton")).put(ProcessEngine.class, processEngine); } - Arrays.stream(testInstance.getClass().getDeclaredFields()) + getAllFields(testInstance.getClass()) .filter(field -> field.getType() == ProcessEngine.class) .forEach(field -> inject(testInstance, field, processEngine)); - Arrays.stream(testInstance.getClass().getDeclaredFields()) + getAllFields(testInstance.getClass()) .filter(field -> ProcessEngineConfiguration.class.isAssignableFrom(field.getType())) .forEach(field -> inject(testInstance, field, processEngine.getProcessEngineConfiguration())); @@ -229,6 +231,15 @@ public void postProcessTestInstance(Object testInstance, ExtensionContext contex .forEach(serviceType -> injectProcessEngineService(testInstance, serviceType)); } + private Stream getAllFields(Class clazz) { + Stream fields = Stream.of(clazz.getDeclaredFields()); + Class superclass = clazz.getSuperclass(); + + return superclass != null + ? Stream.concat(fields, getAllFields(superclass)) + : fields; + } + private void injectProcessEngineService(Object testInstance, Class serviceType) { Objects.requireNonNull(processEngine, "ProcessEngine not initialized"); Optional serviceInstance = Arrays.stream(ProcessEngineServices.class.getDeclaredMethods()) @@ -243,7 +254,7 @@ private void injectProcessEngineService(Object testInstance, Class serviceTyp }); if (serviceInstance.isPresent()) { - Arrays.stream(testInstance.getClass().getDeclaredFields()) + getAllFields(testInstance.getClass()) .filter(field -> field.getType().isAssignableFrom(serviceType)) .forEach(field -> inject(testInstance, field, serviceInstance.get())); } diff --git a/test-utils/junit5-extension/src/test/java/org/operaton/bpm/engine/test/junit5/ProcessEngineExtensionSubTypeInjectionTest.java b/test-utils/junit5-extension/src/test/java/org/operaton/bpm/engine/test/junit5/ProcessEngineExtensionSubTypeInjectionTest.java new file mode 100644 index 00000000000..e733f74d1db --- /dev/null +++ b/test-utils/junit5-extension/src/test/java/org/operaton/bpm/engine/test/junit5/ProcessEngineExtensionSubTypeInjectionTest.java @@ -0,0 +1,15 @@ +package org.operaton.bpm.engine.test.junit5; + +import org.junit.jupiter.api.Test; + +/** + * This test is checking that a ProcessEngineExtension annotated to the superclass of a test is injecting the + * services into the superclass fields. + */ +class ProcessEngineExtensionSubTypeInjectionTest extends ProcessEngineExtensionServiceInjectionTest { + @Test + @Override + void extensionInjectsServiceInstances() { + super.extensionInjectsServiceInstances(); + } +} From c126ff2871cb7a0ee1863a8fcfdb0a9dc2753908 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Mon, 4 Nov 2024 22:41:52 +0100 Subject: [PATCH 13/37] feat(core): task API enhancement to include attachment/comments info (#4306) * task API response include attachments and comments info * when `withCommentAttachmentInfo` is enabled * additional queries if a attachment/comment is present * count query is not affected related to https://github.com/camunda/camunda-bpm-platform/issues/2404 --------- Signed-off-by: Kumar Pani, Suman Backported commit ddf039c4f3 from the camunda-bpm-platform repository. Original author: sumankumarpani --- .../lib/commons/task-query-params.ftl | 12 ++++- .../task/TaskWithAttachmentAndCommentDto.ftl | 17 ++++++ .../src/main/templates/paths/task/get.ftl | 41 +++++++++++++- .../src/main/templates/paths/task/post.ftl | 7 ++- .../main/templates/paths/task/{id}/get.ftl | 34 +++++++++++- .../bpm/engine/rest/TaskRestService.java | 2 +- .../bpm/engine/rest/dto/task/TaskDto.java | 39 ++++++++++++++ .../engine/rest/dto/task/TaskQueryDto.java | 12 +++++ .../task/TaskWithAttachmentAndCommentDto.java | 54 +++++++++++++++++++ .../engine/rest/impl/TaskRestServiceImpl.java | 16 +++--- .../rest/sub/task/impl/TaskResourceImpl.java | 38 +++++++------ .../rest/TaskRestServiceInteractionTest.java | 33 ++++++++++++ .../engine/rest/TaskRestServiceQueryTest.java | 28 ++++++++++ .../bpm/engine/rest/helper/MockProvider.java | 10 +++- .../engine/rest/helper/MockTaskBuilder.java | 17 ++++++ .../bpm/engine/impl/TaskQueryImpl.java | 15 ++++++ .../impl/persistence/entity/TaskEntity.java | 15 +++++- .../org/operaton/bpm/engine/task/Task.java | 5 ++ .../operaton/bpm/engine/task/TaskQuery.java | 7 +++ .../engine/test/api/task/TaskQueryTest.java | 37 ++++++++++++- 20 files changed, 407 insertions(+), 32 deletions(-) create mode 100644 engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/runtime/task/TaskWithAttachmentAndCommentDto.ftl create mode 100644 engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskWithAttachmentAndCommentDto.java diff --git a/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/task-query-params.ftl b/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/task-query-params.ftl index 81cbdedf485..23fefe039ff 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/task-query-params.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/task-query-params.ftl @@ -657,5 +657,15 @@ <@lib.parameter name = "parentTaskId" location = "query" type = "string" + desc = "Restrict query to all tasks that are sub tasks of the given task. Takes a task id." /> + + <@lib.parameter name = "withCommentAttachmentInfo" + location = "query" + type = "boolean" + defaultValue = "false" last = last - desc = "Restrict query to all tasks that are sub tasks of the given task. Takes a task id." /> \ No newline at end of file + desc = "Check if task has attachments and/or comments. Value may only be `true`, as + `false` is the default behavior. + Adding the filter will do additional attachment and comments queries to the database, + it might slow down the query in case of tables having high volume of data. + This param is not considered for count queries" /> \ No newline at end of file diff --git a/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/runtime/task/TaskWithAttachmentAndCommentDto.ftl b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/runtime/task/TaskWithAttachmentAndCommentDto.ftl new file mode 100644 index 00000000000..5b6b13ff4ad --- /dev/null +++ b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/runtime/task/TaskWithAttachmentAndCommentDto.ftl @@ -0,0 +1,17 @@ +<#macro dto_macro docsUrl=""> +<@lib.dto + extends = "TaskDto" > + + <@lib.property + name = "attachment" + type = "boolean" + desc = "Specifies if an attachment exists for the task." /> + + <@lib.property + name = "comment" + type = "boolean" + last = true + desc = "Specifies if an comment exists for the task." /> + + + \ No newline at end of file diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/task/get.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/task/get.ftl index bfd8941a0cf..d52fcbb8195 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/task/get.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/task/get.ftl @@ -34,11 +34,11 @@ <@lib.response code = "200" - dto = "TaskDto" + dto = "TaskWithAttachmentAndCommentDto" array = true desc = "Request successful." examples = ['"example-1": { - "summary": "Status 200 response", + "summary": "Status 200 response 1", "description": "Response for GET `/task?assignee=anAssignee&delegationState=RESOLVED&maxPriority=50`", "value": [ { @@ -72,6 +72,43 @@ "taskState": "aTaskState" } ] + }', + '"example-2": { + "summary": "Status 200 response 2", + "description": "Response for GET `/task?assignee=anAssignee&withCommentAttachmentInfo=true`", + "value": [ + { + "id":"anId", + "name":"aName", + "assignee":"anAssignee", + "created":"2013-01-23T13:42:42.657+0200", + "due":"2013-01-23T13:49:42.323+0200", + "followUp:":"2013-01-23T13:44:42.987+0200", + "lastUpdated:":"2013-01-23T13:44:42.987+0200", + "delegationState":"RESOLVED", + "description":"aDescription", + "executionId":"anExecution", + "owner":"anOwner", + "parentTaskId":"aParentId", + "priority":42, + "processDefinitionId":"aProcDefId", + "processInstanceId":"aProcInstId", + "caseDefinitionId":"aCaseDefId", + "caseInstanceId":"aCaseInstId", + "caseExecutionId":"aCaseExecution", + "taskDefinitionKey":"aTaskDefinitionKey", + "suspended": false, + "formKey":"aFormKey", + "operatonFormRef":{ + "key": "aOperatonFormKey", + "binding": "version", + "version": 2 + }, + "tenantId": "aTenantId", + "attachment":false, + "comment":false + } + ] }'] /> <@lib.response diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/task/post.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/task/post.ftl index f6ef45141db..70785997c0d 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/task/post.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/task/post.ftl @@ -68,6 +68,7 @@ "description": "Logical query: assignee = \\"John Munda\\" AND (name = \\"Approve Invoice\\" OR priority = 5) AND (suspended = false OR taskDefinitionKey = \\"approveInvoice\\")", "value": { "assignee": "John Munda", + "withCommentAttachmentInfo": "true", "orQueries": [ { "name": "Approve Invoice", @@ -86,7 +87,7 @@ <@lib.response code = "200" - dto = "TaskDto" + dto = "TaskWithAttachmentAndCommentDto" array = true desc = "Request successful." examples = ['"example-1": { @@ -150,7 +151,9 @@ "suspended": false, "formKey": "embedded:app:develop/invoice-forms/approve-invoice.html", "tenantId": null, - "taskState": "aTaskState" + "taskState": "aTaskState", + "attachment":false, + "comment":false } ] }' diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/task/{id}/get.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/task/{id}/get.ftl index f7298125e60..847cca6566b 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/task/{id}/get.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/task/{id}/get.ftl @@ -23,7 +23,7 @@ <@lib.response code = "200" - dto = "TaskDto" + dto = "TaskWithAttachmentAndCommentDto" desc = "Request successful." examples = ['"example-1": { "summary": "GET /task/anId Response", @@ -56,6 +56,38 @@ "tenantId":"aTenantId", "taskState": "aTaskState" } + }', + '"example-2": { + "summary": "GET /task/anId?withCommentAttachmentInfo=true Response", + "value": [ + { + "id": "349fffa8-6571-11e7-9a44-d6940f5ef88d", + "name": "Approve Invoice", + "assignee": "John Munda", + "created": "2017-07-10T15:10:54.670+0200", + "due": "2017-07-17T15:10:54.670+0200", + "followUp": null, + "lastUpdated": "2017-07-17T15:10:54.670+0200", + "delegationState": null, + "description": "Approve the invoice (or not).", + "executionId": "349f8a5c-6571-11e7-9a44-d6940f5ef88d", + "owner": null, + "parentTaskId": null, + "priority": 50, + "processDefinitionId": "invoice:1:2c8d8057-6571-11e7-9a44-d6940f5ef88d", + "processInstanceId": "349f8a5c-6571-11e7-9a44-d6940f5ef88d", + "taskDefinitionKey": "approveInvoice", + "caseExecutionId": null, + "caseInstanceId": null, + "caseDefinitionId": null, + "suspended": false, + "formKey": "embedded:app:develop/invoice-forms/approve-invoice.html", + "tenantId": null, + "taskState": "aTaskState", + "attachment":false, + "comment":false + } + ] }'] /> <@lib.response diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/TaskRestService.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/TaskRestService.java index 9638e9061d6..facd75ff18c 100644 --- a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/TaskRestService.java +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/TaskRestService.java @@ -36,7 +36,7 @@ public interface TaskRestService { public static final String PATH = "/task"; @Path("/{id}") - TaskResource getTask(@PathParam("id") String id); + TaskResource getTask(@PathParam("id") String id, @QueryParam("withCommentAttachmentInfo") boolean withCommentAttachmentInfo); @GET @Produces({MediaType.APPLICATION_JSON, Hal.APPLICATION_HAL_JSON}) diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskDto.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskDto.java index 64643dcc4f9..e30284c44be 100644 --- a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskDto.java +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskDto.java @@ -21,6 +21,7 @@ import org.operaton.bpm.engine.BadUserRequestException; import org.operaton.bpm.engine.form.OperatonFormRef; import org.operaton.bpm.engine.rest.dto.converter.DelegationStateConverter; +import org.operaton.bpm.engine.runtime.ProcessInstance; import org.operaton.bpm.engine.task.DelegationState; import org.operaton.bpm.engine.task.Task; @@ -54,6 +55,44 @@ public class TaskDto { */ private String taskState; + public TaskDto() { + } + + public TaskDto(Task task) { + this.id = task.getId(); + this.name = task.getName(); + this.assignee = task.getAssignee(); + this.created = task.getCreateTime(); + this.lastUpdated = task.getLastUpdated(); + this.due = task.getDueDate(); + this.followUp = task.getFollowUpDate(); + + if (task.getDelegationState() != null) { + this.delegationState = task.getDelegationState().toString(); + } + + this.description = task.getDescription(); + this.executionId = task.getExecutionId(); + this.owner = task.getOwner(); + this.parentTaskId = task.getParentTaskId(); + this.priority = task.getPriority(); + this.processDefinitionId = task.getProcessDefinitionId(); + this.processInstanceId = task.getProcessInstanceId(); + this.taskDefinitionKey = task.getTaskDefinitionKey(); + this.caseDefinitionId = task.getCaseDefinitionId(); + this.caseExecutionId = task.getCaseExecutionId(); + this.caseInstanceId = task.getCaseInstanceId(); + this.suspended = task.isSuspended(); + this.tenantId = task.getTenantId(); + this.taskState = task.getTaskState(); + try { + this.formKey = task.getFormKey(); + this.operatonFormRef = task.getOperatonFormRef(); + } + catch (BadUserRequestException e) { + // ignore (initializeFormKeys was not called) + } + } public String getId() { return id; } diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskQueryDto.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskQueryDto.java index 797eba1ec42..387474bb4e2 100644 --- a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskQueryDto.java +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskQueryDto.java @@ -212,6 +212,8 @@ public class TaskQueryDto extends AbstractQueryDto { private List orQueries; + private Boolean withCommentAttachmentInfo; + public TaskQueryDto() { } @@ -708,6 +710,11 @@ public void setVariableValuesIgnoreCase(Boolean variableValuesCaseInsensitive) { this.variableValuesIgnoreCase = variableValuesCaseInsensitive; } + @OperatonQueryParam(value = "withCommentAttachmentInfo", converter = BooleanConverter.class) + public void setWithCommentAttachmentInfo(Boolean withCommentAttachmentInfo) { + this.withCommentAttachmentInfo = withCommentAttachmentInfo; + } + @Override protected boolean isValidSortByValue(String value) { return VALID_SORT_BY_VALUES.contains(value); @@ -1078,6 +1085,8 @@ public Boolean isVariableValuesIgnoreCase() { return variableValuesIgnoreCase; } + public Boolean getWithCommentAttachmentInfo() { return withCommentAttachmentInfo;} + @Override protected void applyFilters(TaskQuery query) { if (orQueries != null) { @@ -1442,6 +1451,9 @@ protected void applyFilters(TaskQuery query) { } } } + if (withCommentAttachmentInfo != null && withCommentAttachmentInfo) { + query.withCommentAttachmentInfo(); + } } @Override diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskWithAttachmentAndCommentDto.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskWithAttachmentAndCommentDto.java new file mode 100644 index 00000000000..c37a6c432ef --- /dev/null +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/task/TaskWithAttachmentAndCommentDto.java @@ -0,0 +1,54 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. Camunda licenses this file to you under the Apache License, + * Version 2.0; you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.operaton.bpm.engine.rest.dto.task; + +import org.operaton.bpm.engine.task.Task; + +public class TaskWithAttachmentAndCommentDto extends TaskDto { + + private boolean hasAttachment; + private boolean hasComment; + + public TaskWithAttachmentAndCommentDto() { + } + + public TaskWithAttachmentAndCommentDto(Task task) { + super(task); + } + public boolean getAttachment() { + return hasAttachment; + } + public void setAttachment(boolean hasAttachment) { + this.hasAttachment = hasAttachment; + } + + public boolean getComment() { + return hasComment; + } + + public void setComment(boolean hasComment) { + this.hasComment = hasComment; + } + + public static TaskDto fromEntity(Task task) { + TaskWithAttachmentAndCommentDto result = new TaskWithAttachmentAndCommentDto(task); + + result.hasAttachment = task.hasAttachment(); + result.hasComment = task.hasComment(); + return result; + } +} diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/impl/TaskRestServiceImpl.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/impl/TaskRestServiceImpl.java index 73225023602..cfd6ab8d4e2 100644 --- a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/impl/TaskRestServiceImpl.java +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/impl/TaskRestServiceImpl.java @@ -19,6 +19,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Request; import javax.ws.rs.core.Response; @@ -32,6 +33,7 @@ import org.operaton.bpm.engine.rest.dto.CountResultDto; import org.operaton.bpm.engine.rest.dto.task.TaskDto; import org.operaton.bpm.engine.rest.dto.task.TaskQueryDto; +import org.operaton.bpm.engine.rest.dto.task.TaskWithAttachmentAndCommentDto; import org.operaton.bpm.engine.rest.exception.InvalidRequestException; import org.operaton.bpm.engine.rest.hal.Hal; import org.operaton.bpm.engine.rest.hal.task.HalTaskList; @@ -66,6 +68,7 @@ else if (Hal.APPLICATION_HAL_JSON_TYPE.equals(variant.getMediaType())) { } public List getJsonTasks(UriInfo uriInfo, Integer firstResult, Integer maxResults) { + // get list of tasks TaskQueryDto queryDto = new TaskQueryDto(getObjectMapper(), uriInfo.getQueryParameters()); return queryTasks(queryDto, firstResult, maxResults); } @@ -95,11 +98,12 @@ public List queryTasks(TaskQueryDto queryDto, Integer firstResult, List matchingTasks = executeTaskQuery(firstResult, maxResults, query); List tasks = new ArrayList(); - for (Task task : matchingTasks) { - TaskDto returnTask = TaskDto.fromEntity(task); - tasks.add(returnTask); + if (Boolean.TRUE.equals(queryDto.getWithCommentAttachmentInfo())) { + tasks = matchingTasks.stream().map(TaskWithAttachmentAndCommentDto::fromEntity).collect(Collectors.toList()); + } + else { + tasks = matchingTasks.stream().map(TaskDto::fromEntity).collect(Collectors.toList()); } - return tasks; } @@ -130,8 +134,8 @@ public CountResultDto queryTasksCount(TaskQueryDto queryDto) { } @Override - public TaskResource getTask(String id) { - return new TaskResourceImpl(getProcessEngine(), id, relativeRootResourcePath, getObjectMapper()); + public TaskResource getTask(String id, boolean withCommentAttachmentInfo) { + return new TaskResourceImpl(getProcessEngine(), id, relativeRootResourcePath, getObjectMapper(), withCommentAttachmentInfo); } @Override diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/sub/task/impl/TaskResourceImpl.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/sub/task/impl/TaskResourceImpl.java index a4ea338a33e..4bec9af4f24 100755 --- a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/sub/task/impl/TaskResourceImpl.java +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/sub/task/impl/TaskResourceImpl.java @@ -23,6 +23,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.function.Supplier; import javax.ws.rs.core.MediaType; @@ -46,13 +47,7 @@ import org.operaton.bpm.engine.impl.identity.Authentication; import org.operaton.bpm.engine.rest.dto.VariableValueDto; import org.operaton.bpm.engine.rest.dto.converter.StringListConverter; -import org.operaton.bpm.engine.rest.dto.task.CompleteTaskDto; -import org.operaton.bpm.engine.rest.dto.task.FormDto; -import org.operaton.bpm.engine.rest.dto.task.IdentityLinkDto; -import org.operaton.bpm.engine.rest.dto.task.TaskBpmnErrorDto; -import org.operaton.bpm.engine.rest.dto.task.TaskDto; -import org.operaton.bpm.engine.rest.dto.task.TaskEscalationDto; -import org.operaton.bpm.engine.rest.dto.task.UserIdDto; +import org.operaton.bpm.engine.rest.dto.task.*; import org.operaton.bpm.engine.rest.exception.InvalidRequestException; import org.operaton.bpm.engine.rest.exception.RestException; import org.operaton.bpm.engine.rest.hal.Hal; @@ -78,12 +73,14 @@ public class TaskResourceImpl implements TaskResource { protected String taskId; protected String rootResourcePath; protected ObjectMapper objectMapper; + protected boolean withCommentAttachmentInfo; - public TaskResourceImpl(ProcessEngine engine, String taskId, String rootResourcePath, ObjectMapper objectMapper) { + public TaskResourceImpl(ProcessEngine engine, String taskId, String rootResourcePath, ObjectMapper objectMapper, boolean withCommentAttachmentInfo) { this.engine = engine; this.taskId = taskId; this.rootResourcePath = rootResourcePath; this.objectMapper = objectMapper; + this.withCommentAttachmentInfo = withCommentAttachmentInfo; } @Override @@ -192,16 +189,20 @@ else if (Hal.APPLICATION_HAL_JSON_TYPE.equals(variant.getMediaType())) { } public TaskDto getJsonTask() { - Task task = getTaskById(taskId); + Task task = getTaskById(taskId, withCommentAttachmentInfo); if (task == null) { throw new InvalidRequestException(Status.NOT_FOUND, "No matching task with id " + taskId); } - - return TaskDto.fromEntity(task); + if (withCommentAttachmentInfo) { + return TaskWithAttachmentAndCommentDto.fromEntity(task); + } + else { + return TaskDto.fromEntity(task); + } } public HalTask getHalTask() { - Task task = getTaskById(taskId); + Task task = getTaskById(taskId, withCommentAttachmentInfo); if (task == null) { throw new InvalidRequestException(Status.NOT_FOUND, "No matching task with id " + taskId); } @@ -212,7 +213,7 @@ public HalTask getHalTask() { @Override public FormDto getForm() { FormService formService = engine.getFormService(); - Task task = getTaskById(taskId); + Task task = getTaskById(taskId, withCommentAttachmentInfo); FormData formData; try { formData = formService.getTaskFormData(taskId); @@ -368,7 +369,7 @@ public Map getFormVariables(String variableNames, bool public void updateTask(TaskDto taskDto) { TaskService taskService = engine.getTaskService(); - Task task = getTaskById(taskId); + Task task = getTaskById(taskId, withCommentAttachmentInfo); if (task == null) { throw new InvalidRequestException(Status.NOT_FOUND, "No matching task with id " + taskId); @@ -433,8 +434,13 @@ public void handleEscalation(TaskEscalationDto dto) { } } - protected Task getTaskById(String id) { - return engine.getTaskService().createTaskQuery().taskId(id).initializeFormKeys().singleResult(); + protected Task getTaskById(String id, boolean withCommentAttachmentInfo) { + if (withCommentAttachmentInfo) { + return engine.getTaskService().createTaskQuery().taskId(id).withCommentAttachmentInfo().initializeFormKeys().singleResult(); + } + else{ + return engine.getTaskService().createTaskQuery().taskId(id).initializeFormKeys().singleResult(); + } } protected String getTaskFormMediaType(String taskId) { diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/TaskRestServiceInteractionTest.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/TaskRestServiceInteractionTest.java index cadfbae2be2..2c45ffa4616 100755 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/TaskRestServiceInteractionTest.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/TaskRestServiceInteractionTest.java @@ -146,6 +146,8 @@ import io.restassured.http.ContentType; import io.restassured.path.json.JsonPath; import io.restassured.response.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class TaskRestServiceInteractionTest extends AbstractRestServiceTest { @@ -214,6 +216,7 @@ public void setUpRuntimeData() { mockQuery = mock(TaskQuery.class); when(mockQuery.initializeFormKeys()).thenReturn(mockQuery); when(mockQuery.taskId(any())).thenReturn(mockQuery); + when(mockQuery.withCommentAttachmentInfo()).thenReturn(mockQuery); when(mockQuery.singleResult()).thenReturn(mockTask); when(taskServiceMock.createTaskQuery()).thenReturn(mockQuery); @@ -316,6 +319,36 @@ public void testGetSingleTask() { .body("taskState", equalTo(MockProvider.EXAMPLE_HISTORIC_TASK_STATE)) .when().get(SINGLE_TASK_URL); } + @Test + public void testGetSingleTaskWithQueryParam() { + given().pathParam("id", EXAMPLE_TASK_ID) + .queryParam("withCommentAttachmentInfo", true) + .header("accept", MediaType.APPLICATION_JSON) + .then().expect().statusCode(Status.OK.getStatusCode()) + .body("id", equalTo(EXAMPLE_TASK_ID)) + .body("name", equalTo(MockProvider.EXAMPLE_TASK_NAME)) + .body("assignee", equalTo(MockProvider.EXAMPLE_TASK_ASSIGNEE_NAME)) + .body("created", equalTo(MockProvider.EXAMPLE_TASK_CREATE_TIME)) + .body("due", equalTo(MockProvider.EXAMPLE_TASK_DUE_DATE)) + .body("delegationState", equalTo(MockProvider.EXAMPLE_TASK_DELEGATION_STATE.toString())) + .body("description", equalTo(MockProvider.EXAMPLE_TASK_DESCRIPTION)) + .body("executionId", equalTo(MockProvider.EXAMPLE_TASK_EXECUTION_ID)) + .body("owner", equalTo(MockProvider.EXAMPLE_TASK_OWNER)) + .body("parentTaskId", equalTo(MockProvider.EXAMPLE_TASK_PARENT_TASK_ID)) + .body("priority", equalTo(MockProvider.EXAMPLE_TASK_PRIORITY)) + .body("processDefinitionId", equalTo(MockProvider.EXAMPLE_PROCESS_DEFINITION_ID)) + .body("processInstanceId", equalTo(MockProvider.EXAMPLE_PROCESS_INSTANCE_ID)) + .body("taskDefinitionKey", equalTo(MockProvider.EXAMPLE_TASK_DEFINITION_KEY)) + .body("suspended", equalTo(MockProvider.EXAMPLE_TASK_SUSPENSION_STATE)) + .body("caseExecutionId", equalTo(MockProvider.EXAMPLE_CASE_EXECUTION_ID)) + .body("caseInstanceId", equalTo(MockProvider.EXAMPLE_CASE_INSTANCE_ID)) + .body("caseDefinitionId", equalTo(MockProvider.EXAMPLE_CASE_DEFINITION_ID)) + .body("tenantId", equalTo(MockProvider.EXAMPLE_TENANT_ID)) + .body("lastUpdated", equalTo(MockProvider.EXAMPLE_TASK_LAST_UPDATED)) + .body("attachment", equalTo(MockProvider.EXAMPLE_TASK_ATTACHMENT_STATE)) + .body("comment", equalTo(MockProvider.EXAMPLE_TASK_COMMENT_STATE)) + .when().get(SINGLE_TASK_URL); + } @Test @SuppressWarnings("unchecked") diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/TaskRestServiceQueryTest.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/TaskRestServiceQueryTest.java index 48d7a8eb388..11998d2aea1 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/TaskRestServiceQueryTest.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/TaskRestServiceQueryTest.java @@ -211,6 +211,32 @@ public void testSimpleTaskQuery() { assertThat(MockProvider.EXAMPLE_FORM_KEY).isEqualTo(returnedFormKey); assertThat(MockProvider.EXAMPLE_TENANT_ID).isEqualTo(returnedTenantId); + } + @Test + public void testTaskQueryWithAttachmentAndComment() { + String queryName = "name"; + + Response response = given().queryParam("name", queryName) + .queryParam("withCommentAttachmentInfo","true") + .header("accept", MediaType.APPLICATION_JSON) + .then().expect().statusCode(Status.OK.getStatusCode()) + .when().get(TASK_QUERY_URL); + + InOrder inOrder = inOrder(mockQuery); + inOrder.verify(mockQuery).taskName(queryName); + inOrder.verify(mockQuery).list(); + + String content = response.asString(); + List> instances = from(content).getList(""); + assertThat(instances).hasSize(1).as("There should be one task returned."); + assertThat(instances.get(0)).isNotNull().as("The returned task should not be null."); + + boolean returnedAttachmentsInfo = from(content).getBoolean("[0].attachment"); + boolean returnedCommentsInfo = from(content).getBoolean("[0].comment"); + + assertThat(MockProvider.EXAMPLE_TASK_ATTACHMENT_STATE).isEqualTo(returnedAttachmentsInfo); + assertThat(MockProvider.EXAMPLE_TASK_COMMENT_STATE).isEqualTo(returnedCommentsInfo); + } @Test @@ -521,6 +547,7 @@ private Map getCompleteBooleanQueryParameters() { parameters.put("withCandidateUsers", true); parameters.put("withoutCandidateUsers", true); parameters.put("withoutDueDate", true); + parameters.put("withCommentAttachmentInfo", true); return parameters; } @@ -586,6 +613,7 @@ private void verifyBooleanParameterQueryInvocation() { verify(mockQuery).withCandidateUsers(); verify(mockQuery).withoutCandidateUsers(); verify(mockQuery).withoutDueDate(); + verify(mockQuery).withCommentAttachmentInfo(); } @Test diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java index 7d925969c0e..c953b0729bc 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java @@ -198,6 +198,10 @@ public abstract class MockProvider { public static final String EXAMPLE_TASK_DEFINITION_KEY = "aTaskDefinitionKey"; public static final boolean EXAMPLE_TASK_SUSPENSION_STATE = false; + public static final boolean EXAMPLE_TASK_ATTACHMENT_STATE = false; + + public static final boolean EXAMPLE_TASK_COMMENT_STATE = false; + // task comment public static final String EXAMPLE_TASK_COMMENT_ID = "aTaskCommentId"; public static final String EXAMPLE_TASK_COMMENT_FULL_MESSAGE = "aTaskCommentFullMessage"; @@ -1057,7 +1061,11 @@ public static MockTaskBuilder mockTask() { .caseExecutionId(EXAMPLE_CASE_EXECUTION_ID) .formKey(EXAMPLE_FORM_KEY) .operatonFormRef(EXAMPLE_FORM_KEY, EXAMPLE_FORM_REF_BINDING, EXAMPLE_FORM_REF_VERSION) - .tenantId(EXAMPLE_TENANT_ID).taskState(EXAMPLE_HISTORIC_TASK_STATE); + .tenantId(EXAMPLE_TENANT_ID) + .taskState(EXAMPLE_HISTORIC_TASK_STATE) + .tenantId(EXAMPLE_TENANT_ID) + .hasAttachment(EXAMPLE_TASK_ATTACHMENT_STATE) + .hasComment(EXAMPLE_TASK_COMMENT_STATE); } public static List createMockTasks() { diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockTaskBuilder.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockTaskBuilder.java index d80ddbe5268..95b9ebaf007 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockTaskBuilder.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockTaskBuilder.java @@ -50,6 +50,11 @@ public class MockTaskBuilder { private String formKey; private OperatonFormRef operatonFormRef; private String tenantId; + private boolean hasAttachment; + + private boolean hasComment; + + private String taskState; @@ -170,6 +175,16 @@ public MockTaskBuilder taskState(String taskState) { return this; } + public MockTaskBuilder hasAttachment(boolean hasAttachment) { + this.hasAttachment = hasAttachment; + return this; + } + + public MockTaskBuilder hasComment(boolean hasComment) { + this.hasComment = hasComment; + return this; + } + public Task build() { Task mockTask = mock(Task.class); when(mockTask.getId()).thenReturn(id); @@ -195,6 +210,8 @@ public Task build() { when(mockTask.getOperatonFormRef()).thenReturn(operatonFormRef); when(mockTask.getTenantId()).thenReturn(tenantId); when(mockTask.getTaskState()).thenReturn(taskState); + when(mockTask.hasAttachment()).thenReturn(hasAttachment); + when(mockTask.hasComment()).thenReturn(hasComment); return mockTask; } diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/TaskQueryImpl.java b/engine/src/main/java/org/operaton/bpm/engine/impl/TaskQueryImpl.java index a72999e9d5c..e14fc46463a 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/TaskQueryImpl.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/TaskQueryImpl.java @@ -44,6 +44,7 @@ import org.operaton.bpm.engine.task.Task; import org.operaton.bpm.engine.task.TaskQuery; import org.operaton.bpm.engine.variable.type.ValueType; +import org.operaton.bpm.engine.impl.history.HistoryLevel; /** * @author Joram Barrez @@ -175,6 +176,7 @@ public class TaskQueryImpl extends AbstractQuery implements Tas // or query ///////////////////////////// protected List queries = new ArrayList<>(Arrays.asList(this)); protected boolean isOrQueryActive = false; + protected boolean withCommentAttachmentInfo; public TaskQueryImpl() { } @@ -1088,6 +1090,12 @@ protected boolean hasExcludingConditions() { || CompareUtil.elementIsNotContainedInArray(processInstanceBusinessKey, processInstanceBusinessKeys); } + @Override + public TaskQuery withCommentAttachmentInfo() { + this.withCommentAttachmentInfo = true; + return this; + } + public List getCandidateGroups() { if (cachedCandidateGroups != null) { return cachedCandidateGroups; @@ -1441,6 +1449,13 @@ public List executeList(CommandContext commandContext, Page page) { } } + if (withCommentAttachmentInfo && !Context.getProcessEngineConfiguration().getHistoryLevel().equals(HistoryLevel.HISTORY_LEVEL_NONE)) { + for (Task task : taskList) { + // verify attachment and comments exists for the task + ((TaskEntity) task).initializeAttachmentAndComments(); + } + } + return taskList; } diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/TaskEntity.java b/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/TaskEntity.java index 075ae2b129b..862d7c052c1 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/TaskEntity.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/TaskEntity.java @@ -162,6 +162,8 @@ public class TaskEntity extends AbstractVariableScope implements Task, DelegateT protected boolean isFormKeyInitialized = false; protected String formKey; protected OperatonFormRef operatonFormRef; + protected boolean attachmentExists; + protected boolean commentExists; @SuppressWarnings({ "unchecked" }) protected transient VariableStore variableStore @@ -1462,6 +1464,10 @@ public void initializeFormKey() { } } } + public void initializeAttachmentAndComments(){ + this.attachmentExists = !Context.getCommandContext().getAttachmentManager().findAttachmentsByTaskId(id).isEmpty(); + this.commentExists = !Context.getCommandContext().getCommentManager().findCommentsByTaskId(id).isEmpty(); + } @Override public String getFormKey() { @@ -1780,7 +1786,14 @@ public void bpmnError(String errorCode, String errorMessage, Map throw ProcessEngineLogger.CMD_LOGGER.exceptionBpmnErrorPropagationFailed(errorCode, ex); } } - + @Override + public boolean hasAttachment() { + return attachmentExists; + } + @Override + public boolean hasComment() { + return commentExists; + } public void escalation(String escalationCode, Map variables) { ensureTaskActive(); ActivityExecution activityExecution = getExecution(); diff --git a/engine/src/main/java/org/operaton/bpm/engine/task/Task.java b/engine/src/main/java/org/operaton/bpm/engine/task/Task.java index 34cb43536e9..8dfad21c148 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/task/Task.java +++ b/engine/src/main/java/org/operaton/bpm/engine/task/Task.java @@ -202,4 +202,9 @@ public interface Task { * @param taskState the taskState to set */ void setTaskState(String taskState); + /** Returns if an attachment exists for the task */ + boolean hasAttachment(); + /** Signifies if a comment exists for the task */ + boolean hasComment(); + } diff --git a/engine/src/main/java/org/operaton/bpm/engine/task/TaskQuery.java b/engine/src/main/java/org/operaton/bpm/engine/task/TaskQuery.java index b995b5e0ccd..18dc04869cf 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/task/TaskQuery.java +++ b/engine/src/main/java/org/operaton/bpm/engine/task/TaskQuery.java @@ -1104,4 +1104,11 @@ public interface TaskQuery extends Query { * this exception, {@link #or()} must be invoked first. */ TaskQuery endOr(); + + /** + * Evaluates existence of attachment and comments associated with the task, defaults to false. + * Adding the filter will do additional attachment and comments queries to the database, + * it might slow down the query in case of tables having high volume of data. + */ + TaskQuery withCommentAttachmentInfo(); } diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/api/task/TaskQueryTest.java b/engine/src/test/java/org/operaton/bpm/engine/test/api/task/TaskQueryTest.java index b15226cc40f..57d089c2100 100644 --- a/engine/src/test/java/org/operaton/bpm/engine/test/api/task/TaskQueryTest.java +++ b/engine/src/test/java/org/operaton/bpm/engine/test/api/task/TaskQueryTest.java @@ -33,6 +33,7 @@ import static org.operaton.bpm.engine.test.api.runtime.TestOrderingUtil.taskByProcessInstanceId; import static org.operaton.bpm.engine.test.api.runtime.TestOrderingUtil.verifySortingAndCount; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -55,6 +56,7 @@ import java.util.stream.Collectors; import org.operaton.bpm.engine.BadUserRequestException; +import org.operaton.bpm.engine.ProcessEngineConfiguration; import org.operaton.bpm.engine.ProcessEngineException; import org.operaton.bpm.engine.exception.NullValueException; import org.operaton.bpm.engine.filter.Filter; @@ -72,6 +74,7 @@ import org.operaton.bpm.engine.task.Task; import org.operaton.bpm.engine.task.TaskQuery; import org.operaton.bpm.engine.test.Deployment; +import org.operaton.bpm.engine.test.RequiredHistoryLevel; import org.operaton.bpm.engine.test.util.PluggableProcessEngineTest; import org.operaton.bpm.engine.variable.Variables; import org.operaton.bpm.engine.variable.type.ValueType; @@ -5602,7 +5605,39 @@ public void shouldFindStandaloneTaskWithUpdateByLastUpdated() { assertThat(taskResult.getLastUpdated()).isAfter(beforeSave); assertThat(taskResult.getLastUpdated()).isAfter(taskResult.getCreateTime()); } - + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_ACTIVITY) + @Deployment(resources = "org/operaton/bpm/engine/test/api/oneTaskProcess.bpmn20.xml") + public void shouldNotFindAttachmentAndCommentInfoWithoutQueryParam() { + // given + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess"); + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); + task.setAssignee("myself"); + // when + taskService.createComment(task.getId(), processInstance.getId(), "testComment"); + taskService.createAttachment("foo", task.getId(), processInstance.getId(), "testAttachment", "testDesc", "http://operaton.org"); + // then + Task taskResult = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); + assertThat(taskResult).isNotNull(); + assertFalse(taskResult.hasComment()); + assertFalse(taskResult.hasAttachment()); + } + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_ACTIVITY) + @Deployment(resources = "org/operaton/bpm/engine/test/api/oneTaskProcess.bpmn20.xml") + public void shouldFindAttachmentAndCommentInfoWithQueryParam() { + // given + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("oneTaskProcess"); + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); + // when + taskService.createComment(task.getId(), processInstance.getId(), "testComment"); + taskService.createAttachment("foo", task.getId(), processInstance.getId(), "testAttachment", "testDesc", "http://operaton.org"); + // then + Task taskResult = taskService.createTaskQuery().processInstanceId(processInstance.getId()).withCommentAttachmentInfo().singleResult(); + assertThat(taskResult).isNotNull(); + assertTrue(taskResult.hasComment()); + assertTrue(taskResult.hasAttachment()); + } // ---------------------- HELPER ------------------------------ // make sure that time passes between two fast operations From 30280236efb0749ae2161f62c3e4c05090b2b3ec Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Tue, 5 Nov 2024 13:04:54 +0100 Subject: [PATCH 14/37] chore(webapps): bump webpack to the latest version (#4614) related to camunda/camunda-bpm-platform#4613 Backported commit 8de6e2d4da from the camunda-bpm-platform repository. Original author: tasso94 <3015690+tasso94@users.noreply.github.com> --- webapps/frontend/package-lock.json | 161 +++++++++++++++++------------ webapps/frontend/package.json | 2 +- 2 files changed, 94 insertions(+), 69 deletions(-) diff --git a/webapps/frontend/package-lock.json b/webapps/frontend/package-lock.json index dd9e73b30be..49b5cdd26a8 100644 --- a/webapps/frontend/package-lock.json +++ b/webapps/frontend/package-lock.json @@ -82,7 +82,7 @@ "raw-loader": "4.0.2", "svg-inline-loader": "0.8.2", "terser-webpack-plugin": "5.3.10", - "webpack": "5.90.1", + "webpack": "5.96.1", "webpack-bundle-analyzer": "4.10.1", "webpack-cli": "5.1.4", "webpack-dev-server": "4.15.1", @@ -2369,6 +2369,8 @@ }, "node_modules/@types/eslint-scope": { "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, "license": "MIT", "dependencies": { @@ -2377,7 +2379,9 @@ } }, "node_modules/@types/estree": { - "version": "1.0.5", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true, "license": "MIT" }, @@ -2744,7 +2748,9 @@ } }, "node_modules/acorn": { - "version": "8.12.1", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true, "license": "MIT", "bin": { @@ -2754,14 +2760,6 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-assertions": { - "version": "1.9.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^8" - } - }, "node_modules/acorn-jsx": { "version": "5.3.2", "dev": true, @@ -3996,7 +3994,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.2", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "funding": [ { @@ -4014,10 +4014,10 @@ ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.1.0" + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" }, "bin": { "browserslist": "cli.js" @@ -4110,7 +4110,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001644", + "version": "1.0.30001677", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz", + "integrity": "sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog==", "dev": true, "funding": [ { @@ -5295,7 +5297,9 @@ "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.5.3", + "version": "1.5.51", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.51.tgz", + "integrity": "sha512-kKeWV57KSS8jH4alKt/jKnvHPmJgBxXzGUSbMd4eQF+iOsVPl7bz2KUmu6eo80eMP8wVioTfTyTzdMgM15WXNg==", "dev": true, "license": "ISC" }, @@ -5438,7 +5442,9 @@ "license": "MIT" }, "node_modules/escalade": { - "version": "3.1.2", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { @@ -8703,7 +8709,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.1", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, "license": "ISC" }, @@ -10559,7 +10567,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.1.0", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "funding": [ { @@ -10577,8 +10587,8 @@ ], "license": "MIT", "dependencies": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -10684,25 +10694,26 @@ } }, "node_modules/webpack": { - "version": "5.90.1", + "version": "5.96.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", + "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", "dev": true, "license": "MIT", "dependencies": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.21.10", + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", @@ -10710,7 +10721,7 @@ "schema-utils": "^3.2.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.0", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { @@ -12611,6 +12622,8 @@ }, "@types/eslint-scope": { "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", "dev": true, "requires": { "@types/eslint": "*", @@ -12618,7 +12631,9 @@ } }, "@types/estree": { - "version": "1.0.5", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true }, "@types/express": { @@ -12913,14 +12928,11 @@ } }, "acorn": { - "version": "8.12.1", + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", "dev": true }, - "acorn-import-assertions": { - "version": "1.9.0", - "dev": true, - "requires": {} - }, "acorn-jsx": { "version": "5.3.2", "dev": true, @@ -13901,13 +13913,15 @@ } }, "browserslist": { - "version": "4.23.2", + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30001640", - "electron-to-chromium": "^1.4.820", - "node-releases": "^2.0.14", - "update-browserslist-db": "^1.1.0" + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" } }, "btoa": { @@ -13963,7 +13977,9 @@ } }, "caniuse-lite": { - "version": "1.0.30001644", + "version": "1.0.30001677", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001677.tgz", + "integrity": "sha512-fmfjsOlJUpMWu+mAAtZZZHz7UEwsUxIIvu1TJfO1HqFQvB/B+ii0xr9B5HpbZY/mC4XZ8SvjHJqtAY6pDPQEog==", "dev": true }, "chalk": { @@ -14785,7 +14801,9 @@ "dev": true }, "electron-to-chromium": { - "version": "1.5.3", + "version": "1.5.51", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.51.tgz", + "integrity": "sha512-kKeWV57KSS8jH4alKt/jKnvHPmJgBxXzGUSbMd4eQF+iOsVPl7bz2KUmu6eo80eMP8wVioTfTyTzdMgM15WXNg==", "dev": true }, "emoji-regex": { @@ -14876,7 +14894,9 @@ "dev": true }, "escalade": { - "version": "3.1.2", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true }, "escape-html": { @@ -16912,7 +16932,9 @@ "dev": true }, "picocolors": { - "version": "1.0.1", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "picomatch": { @@ -18080,11 +18102,13 @@ "dev": true }, "update-browserslist-db": { - "version": "1.1.0", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", "dev": true, "requires": { - "escalade": "^3.1.2", - "picocolors": "^1.0.1" + "escalade": "^3.2.0", + "picocolors": "^1.1.0" } }, "uri-js": { @@ -18155,24 +18179,25 @@ } }, "webpack": { - "version": "5.90.1", - "dev": true, - "requires": { - "@types/eslint-scope": "^3.7.3", - "@types/estree": "^1.0.5", - "@webassemblyjs/ast": "^1.11.5", - "@webassemblyjs/wasm-edit": "^1.11.5", - "@webassemblyjs/wasm-parser": "^1.11.5", - "acorn": "^8.7.1", - "acorn-import-assertions": "^1.9.0", - "browserslist": "^4.21.10", + "version": "5.96.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz", + "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==", + "dev": true, + "requires": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.12.1", + "@webassemblyjs/wasm-edit": "^1.12.1", + "@webassemblyjs/wasm-parser": "^1.12.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.15.0", + "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.9", + "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", @@ -18180,7 +18205,7 @@ "schema-utils": "^3.2.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.10", - "watchpack": "^2.4.0", + "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "dependencies": { diff --git a/webapps/frontend/package.json b/webapps/frontend/package.json index b9e2746f7a4..de1191719f0 100644 --- a/webapps/frontend/package.json +++ b/webapps/frontend/package.json @@ -92,7 +92,7 @@ "raw-loader": "4.0.2", "svg-inline-loader": "0.8.2", "terser-webpack-plugin": "5.3.10", - "webpack": "5.90.1", + "webpack": "5.96.1", "webpack-bundle-analyzer": "4.10.1", "webpack-cli": "5.1.4", "webpack-dev-server": "4.15.1", From ba37bd5c36239cc6629d0989c1ca78bd08b7d57d Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Tue, 5 Nov 2024 12:58:52 +0100 Subject: [PATCH 15/37] chore(deps): bump Tomcat to 10.1.29 (#4623) related to camunda/camunda-bpm-platform#4622 Backported commit 79ff55d871 from the camunda-bpm-platform repository. Original author: tasso94 <3015690+tasso94@users.noreply.github.com> --- parent/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parent/pom.xml b/parent/pom.xml index c32246077d4..1b3989303eb 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -64,7 +64,7 @@ 18.0.4.Final 9.0.90 - 10.1.25 + 10.1.30 1.1.10.Final 2.2.2 From 84608486e79877c8ad90a20ff2f5dea2f387a606 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Tue, 5 Nov 2024 13:19:54 +0100 Subject: [PATCH 16/37] chore(engine): Bump Spring Framework Related to https://github.com/camunda/camunda-bpm-platform/issues/4551 Backported commit 1e800652da from the camunda-bpm-platform repository. Original author: Miklas Boskamp --- parent/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parent/pom.xml b/parent/pom.xml index 1b3989303eb..a8660fe6f98 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -19,8 +19,8 @@ 3.8.5 - 5.3.36 - 6.1.8 + 5.3.39 + 6.1.13 3.3.5 3.15.6.Final 2.34 From 9ea14e1e937b9f5aae300421d8e32231f3269f0a Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Wed, 6 Nov 2024 14:29:05 +0100 Subject: [PATCH 17/37] chore(quarkus): Bump quarkus version to 3.15 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related to https://github.com/camunda/camunda-bpm-platform/issues/4580 Backported commit 64274723bb from the camunda-bpm-platform repository. Original author: Joaquín --- parent/pom.xml | 2 +- quarkus-extension/README.md | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/parent/pom.xml b/parent/pom.xml index a8660fe6f98..f915bf01731 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -18,7 +18,7 @@ - 3.8.5 + 3.15.0 5.3.39 6.1.13 3.3.5 diff --git a/quarkus-extension/README.md b/quarkus-extension/README.md index 2681dd522f1..96de365277a 100644 --- a/quarkus-extension/README.md +++ b/quarkus-extension/README.md @@ -26,18 +26,18 @@ can look like the following: ```properties # process engine configuration -quarkus.operaton.cmmn-enabled=false -quarkus.operaton.dmn-enabled=false -quarkus.operaton.history=none +quarkus.operaton.generic-config.cmmn-enabled=false +quarkus.operaton.generic-config.dmn-enabled=false +quarkus.operaton.generic-config.history=none # job executor configuration quarkus.operaton.job-executor.thread-pool.max-pool-size=12 quarkus.operaton.job-executor.thread-pool.queue-size=5 -quarkus.operaton.job-executor.max-jobs-per-acquisition=5 -quarkus.operaton.job-executor.lock-time-in-millis=500000 -quarkus.operaton.job-executor.wait-time-in-millis=7000 -quarkus.operaton.job-executor.max-wait=65000 -quarkus.operaton.job-executor.backoff-time-in-millis=5 +quarkus.operaton.job-executor.generic-config.max-jobs-per-acquisition=5 +quarkus.operaton.job-executor.generic-config.lock-time-in-millis=500000 +quarkus.operaton.job-executor.generic-config.wait-time-in-millis=7000 +quarkus.operaton.job-executor.generic-config.max-wait=65000 +quarkus.operaton.job-executor.generic-config.backoff-time-in-millis=5 # custom data source configuration and selection quarkus.datasource.my-datasource.db-kind=h2 @@ -80,4 +80,4 @@ Bytecode: 0000000: 2ab7 0007 2abb 000c 59b7 000e b500 0f2a 0000010: 03b5 0013 2abb 0017 59b7 0019 b500 1a2a 0000020: 2bb5 001e b1``` - \ No newline at end of file + From 696b01df31b09137fafa25c204af26b01ed89fab Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Wed, 6 Nov 2024 14:35:06 +0100 Subject: [PATCH 18/37] feat(spring-boot/run): add spring security & oauth2 modules (#4478) related to https://github.com/camunda/camunda-bpm-platform/issues/4451 Backported commit 2368e55663 from the camunda-bpm-platform repository. Original author: Daniel Kelemen --- bom/operaton-only-bom/pom.xml | 5 ++ clients/java/client/pom.xml | 3 +- distro/run/assembly/assembly.xml | 11 ++++ distro/run/assembly/pom.xml | 15 +++++ distro/run/assembly/resources/run.bat | 8 +++ distro/run/assembly/resources/run.sh | 11 +++- distro/run/modules/oauth2/pom.xml | 41 ++++++++++++ ...pringSecurityDisableAutoConfiguration.java | 40 ++++++++++++ ...ot.autoconfigure.AutoConfiguration.imports | 1 + distro/run/pom.xml | 1 + .../bpm/run/qa/ComponentAvailabilityIT.java | 3 +- parent/pom.xml | 1 + spring-boot-starter/pom.xml | 2 + spring-boot-starter/starter-security/pom.xml | 59 ++++++++++++++++++ .../boot/project/SampleApplication.java | 47 ++++++++++++++ .../project/SamplePermitAllApplication.java | 43 +++++++++++++ .../OperatonBpmSampleApplicationTest.java | 62 +++++++++++++++++++ ...atonBpmSamplePermitAllApplicationTest.java | 47 ++++++++++++++ .../src/test/resources/logback-test.xml | 8 +++ 19 files changed, 404 insertions(+), 4 deletions(-) create mode 100644 distro/run/modules/oauth2/pom.xml create mode 100644 distro/run/modules/oauth2/src/main/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSpringSecurityDisableAutoConfiguration.java create mode 100644 distro/run/modules/oauth2/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports create mode 100644 spring-boot-starter/starter-security/pom.xml create mode 100644 spring-boot-starter/starter-security/src/test/java/my/own/custom/spring/boot/project/SampleApplication.java create mode 100644 spring-boot-starter/starter-security/src/test/java/my/own/custom/spring/boot/project/SamplePermitAllApplication.java create mode 100644 spring-boot-starter/starter-security/src/test/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSampleApplicationTest.java create mode 100644 spring-boot-starter/starter-security/src/test/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSamplePermitAllApplicationTest.java create mode 100644 spring-boot-starter/starter-security/src/test/resources/logback-test.xml diff --git a/bom/operaton-only-bom/pom.xml b/bom/operaton-only-bom/pom.xml index 7d242edb0e7..a7358dd69bc 100644 --- a/bom/operaton-only-bom/pom.xml +++ b/bom/operaton-only-bom/pom.xml @@ -179,6 +179,11 @@ operaton-bpm-spring-boot-starter-webapp ${project.version} + + org.operaton.bpm.springboot + operaton-bpm-spring-boot-starter-security + ${project.version} + org.operaton.bpm.springboot operaton-bpm-spring-boot-starter-webapp-ee diff --git a/clients/java/client/pom.xml b/clients/java/client/pom.xml index c6bc5cebeff..52023d4a020 100644 --- a/clients/java/client/pom.xml +++ b/clients/java/client/pom.xml @@ -14,7 +14,6 @@ - 5.3 ${project.build.directory}/operaton-tomcat ${engine.runtime}/server/apache-tomcat-${version.tomcat} ${tomcat.connector.http.port} @@ -66,7 +65,7 @@ org.apache.httpcomponents.client5 httpclient5 - ${version.httpclient} + ${version.httpclient5} diff --git a/distro/run/assembly/assembly.xml b/distro/run/assembly/assembly.xml index 0d08b498d68..aaf88cd03f0 100644 --- a/distro/run/assembly/assembly.xml +++ b/distro/run/assembly/assembly.xml @@ -19,6 +19,13 @@ ${artifact.artifactId}.${artifact.extension} + + internal/oauth2/ + + org.operaton.bpm.run:operaton-bpm-run-modules-oauth2 + + ${artifact.artifactId}.${artifact.extension} + internal/example/ @@ -122,6 +129,10 @@ ../modules/rest/target/dependency/ internal/rest/ + + ../modules/oauth2/target/dependency/ + internal/oauth2/ + resources/dummyResource diff --git a/distro/run/assembly/pom.xml b/distro/run/assembly/pom.xml index 18b1a2e9172..6163b802528 100644 --- a/distro/run/assembly/pom.xml +++ b/distro/run/assembly/pom.xml @@ -49,6 +49,21 @@ + + + org.operaton.bpm.run + operaton-bpm-run-modules-oauth2 + ${project.version} + jar + + + + * + * + + + + org.operaton.bpm.run operaton-bpm-run-modules-example-invoice diff --git a/distro/run/assembly/resources/run.bat b/distro/run/assembly/resources/run.bat index b17b03bcdf5..f4b0d43017a 100644 --- a/distro/run/assembly/resources/run.bat +++ b/distro/run/assembly/resources/run.bat @@ -5,6 +5,7 @@ SET BASEDIR=%~dp0 SET PARENTDIR=%BASEDIR%..\ SET DEPLOYMENTDIR=%PARENTDIR%configuration/resources SET WEBAPPS_PATH=%BASEDIR%webapps +SET OAUTH2_PATH=%BASEDIR%oauth2 SET REST_PATH=%BASEDIR%rest SET EXAMPLE_PATH=%BASEDIR%example SET APPNAME=Operaton Run @@ -79,6 +80,12 @@ IF [%~1]==[--webapps] ( ECHO WebApps enabled ) +IF [%~1]==[--oauth2] ( + SET optionalComponentChosen=true + SET classPath=%OAUTH2_PATH%,%classPath% + ECHO Spring Security OAuth2 enabled +) + IF [%~1]==[--rest] ( SET optionalComponentChosen=true SET restChosen=true @@ -159,6 +166,7 @@ ECHO Usage: run.bat [start^|stop] (options...) :ArgsHelp ECHO Options: ECHO --webapps - Enables the Operaton Webapps +ECHO --oauth2 - Enables the Operaton Platform Spring Security OAuth2 integration ECHO --rest - Enables the REST API ECHO --example - Enables the example application ECHO --production - Applies the production.yaml configuration file diff --git a/distro/run/assembly/resources/run.sh b/distro/run/assembly/resources/run.sh index bd2612553a0..1db9420bce6 100644 --- a/distro/run/assembly/resources/run.sh +++ b/distro/run/assembly/resources/run.sh @@ -5,11 +5,13 @@ BASEDIR=$(dirname "$0") PARENTDIR=$(builtin cd "$BASEDIR/.."; pwd) DEPLOYMENT_DIR=$PARENTDIR/configuration/resources WEBAPPS_PATH=$BASEDIR/webapps/ +OAUTH2_PATH=$BASEDIR/oauth2/ REST_PATH=$BASEDIR/rest/ EXAMPLE_PATH=$BASEDIR/example PID_PATH=$BASEDIR/run.pid OPTIONS_HELP="Options: --webapps - Enables the Operaton Webapps + --oauth2 - Enables the Operaton Platform Spring Security OAuth2 integration --rest - Enables the REST API --example - Enables the example application --production - Applies the production.yaml configuration file @@ -57,6 +59,10 @@ if [ "$1" = "start" ] ; then classPath=$WEBAPPS_PATH,$classPath echo WebApps enabled ;; + --oauth2 ) optionalComponentChosen=true + classPath=$OAUTH2_PATH,$classPath + echo Spring Security OAuth2 enabled + ;; --rest ) optionalComponentChosen=true restChosen=true classPath=$REST_PATH,$classPath @@ -76,7 +82,10 @@ if [ "$1" = "start" ] ; then --help ) printf "%s" "$OPTIONS_HELP" exit 0 ;; - * ) exit 1 + * ) printf "Unexpected argument '%s'!" "$1" + printf "%s" "$OPTIONS_HELP" + exit 1 + ;; esac shift done diff --git a/distro/run/modules/oauth2/pom.xml b/distro/run/modules/oauth2/pom.xml new file mode 100644 index 00000000000..7756249f270 --- /dev/null +++ b/distro/run/modules/oauth2/pom.xml @@ -0,0 +1,41 @@ + + + 4.0.0 + + + org.operaton.bpm.run + operaton-bpm-run-modules + 7.22.0-SNAPSHOT + .. + + + operaton-bpm-run-modules-oauth2 + Operaton Platform - Run - Module Spring Security + jar + + + + false + + + + + + org.operaton.bpm.springboot + operaton-bpm-spring-boot-starter-security + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + + + \ No newline at end of file diff --git a/distro/run/modules/oauth2/src/main/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSpringSecurityDisableAutoConfiguration.java b/distro/run/modules/oauth2/src/main/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSpringSecurityDisableAutoConfiguration.java new file mode 100644 index 00000000000..53d0ace690b --- /dev/null +++ b/distro/run/modules/oauth2/src/main/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSpringSecurityDisableAutoConfiguration.java @@ -0,0 +1,40 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. Camunda licenses this file to you under the Apache License, + * Version 2.0; you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.operaton.bpm.spring.boot.starter.security; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.SecurityFilterChain; + +public class OperatonBpmSpringSecurityDisableAutoConfiguration { + + private static final Logger logger = LoggerFactory.getLogger(OperatonBpmSpringSecurityDisableAutoConfiguration.class); + + @Bean + public SecurityFilterChain filterChainPermitAll(HttpSecurity http) throws Exception { + logger.info("Disabling Operaton Spring Security oauth2 integration"); + + http.authorizeHttpRequests(customizer -> customizer.anyRequest().permitAll()) + .cors(AbstractHttpConfigurer::disable) + .csrf(AbstractHttpConfigurer::disable); + return http.build(); + } + +} diff --git a/distro/run/modules/oauth2/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/distro/run/modules/oauth2/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports new file mode 100644 index 00000000000..1a45bc3236b --- /dev/null +++ b/distro/run/modules/oauth2/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -0,0 +1 @@ +org.operaton.bpm.spring.boot.starter.security.OperatonBpmSpringSecurityDisableAutoConfiguration \ No newline at end of file diff --git a/distro/run/pom.xml b/distro/run/pom.xml index 5b51c84fbe0..dc729ca55b5 100644 --- a/distro/run/pom.xml +++ b/distro/run/pom.xml @@ -80,6 +80,7 @@ modules/webapps + modules/oauth2 distro qa diff --git a/distro/run/qa/integration-tests/src/test/java/org/operaton/bpm/run/qa/ComponentAvailabilityIT.java b/distro/run/qa/integration-tests/src/test/java/org/operaton/bpm/run/qa/ComponentAvailabilityIT.java index ce4946f2fad..c92dbc606f7 100644 --- a/distro/run/qa/integration-tests/src/test/java/org/operaton/bpm/run/qa/ComponentAvailabilityIT.java +++ b/distro/run/qa/integration-tests/src/test/java/org/operaton/bpm/run/qa/ComponentAvailabilityIT.java @@ -57,7 +57,8 @@ public static Collection commands() { { new String[]{"--rest", "--example"}, true, false, true }, { new String[]{"--webapps"}, false, true, false }, { new String[]{"--rest", "--webapps"}, true, true, false }, - { new String[]{"--rest", "--webapps", "--example"}, true, true, true } + { new String[]{"--rest", "--webapps", "--example"}, true, true, true }, + { new String[]{"--rest", "--webapps", "--example", "--oauth2"}, true, true, true } }); } diff --git a/parent/pom.xml b/parent/pom.xml index a8660fe6f98..e76933c946c 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -43,6 +43,7 @@ 4.0.5 4.0.2 4.5.14 + 5.3 1.7.26 1.2.11 diff --git a/spring-boot-starter/pom.xml b/spring-boot-starter/pom.xml index cd37eb626c8..ee63de16841 100644 --- a/spring-boot-starter/pom.xml +++ b/spring-boot-starter/pom.xml @@ -36,6 +36,7 @@ starter starter-rest + starter-security starter-test starter-client/spring starter-client/spring-boot @@ -72,6 +73,7 @@ starter-qa starter starter-rest + starter-security starter-client/spring-boot starter-webapp-core diff --git a/spring-boot-starter/starter-security/pom.xml b/spring-boot-starter/starter-security/pom.xml new file mode 100644 index 00000000000..06cc75760a1 --- /dev/null +++ b/spring-boot-starter/starter-security/pom.xml @@ -0,0 +1,59 @@ + + + 4.0.0 + + + org.operaton.bpm.springboot.project + operaton-bpm-spring-boot-starter-root + 7.22.0-SNAPSHOT + + + org.operaton.bpm.springboot + operaton-bpm-spring-boot-starter-security + Operaton Platform - Spring Boot Starter - Spring Security + + + + ${project.groupId} + operaton-bpm-spring-boot-starter + ${project.version} + provided + + + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.boot + spring-boot-starter-oauth2-client + + + + ${project.groupId} + operaton-bpm-spring-boot-starter-rest + ${project.version} + test + + + operaton-bpm-spring-boot-starter-test + ${project.groupId} + ${project.version} + test + + + org.apache.httpcomponents.client5 + httpclient5 + ${version.httpclient5} + test + + + com.h2database + h2 + test + + + + diff --git a/spring-boot-starter/starter-security/src/test/java/my/own/custom/spring/boot/project/SampleApplication.java b/spring-boot-starter/starter-security/src/test/java/my/own/custom/spring/boot/project/SampleApplication.java new file mode 100644 index 00000000000..6e670d23149 --- /dev/null +++ b/spring-boot-starter/starter-security/src/test/java/my/own/custom/spring/boot/project/SampleApplication.java @@ -0,0 +1,47 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. Camunda licenses this file to you under the Apache License, + * Version 2.0; you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package my.own.custom.spring.boot.project; + +import org.apache.hc.client5.http.impl.classic.HttpClientBuilder; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; + +@SpringBootConfiguration +@EnableAutoConfiguration +public class SampleApplication { + + public static void main(String... args) { + SpringApplication.run(SampleApplication.class, args); + } + + @Bean + public TestRestTemplate restTemplate(RestTemplateBuilder builder) { + builder.requestFactory(() -> { + var factory = new HttpComponentsClientHttpRequestFactory(); + var httpClient = HttpClientBuilder.create().disableRedirectHandling().build(); + factory.setHttpClient(httpClient); + return factory; + }); + return new TestRestTemplate(builder); + } + +} diff --git a/spring-boot-starter/starter-security/src/test/java/my/own/custom/spring/boot/project/SamplePermitAllApplication.java b/spring-boot-starter/starter-security/src/test/java/my/own/custom/spring/boot/project/SamplePermitAllApplication.java new file mode 100644 index 00000000000..b18d8c194d4 --- /dev/null +++ b/spring-boot-starter/starter-security/src/test/java/my/own/custom/spring/boot/project/SamplePermitAllApplication.java @@ -0,0 +1,43 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. Camunda licenses this file to you under the Apache License, + * Version 2.0; you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package my.own.custom.spring.boot.project; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.SecurityFilterChain; + +@SpringBootConfiguration +@EnableAutoConfiguration +public class SamplePermitAllApplication { + + public static void main(String... args) { + SpringApplication.run(SamplePermitAllApplication.class, args); + } + + @Bean + public SecurityFilterChain filterChainPermitAll(HttpSecurity http) throws Exception { + http.authorizeHttpRequests(customizer -> customizer.anyRequest().permitAll()) + .cors(AbstractHttpConfigurer::disable) + .csrf(AbstractHttpConfigurer::disable); + return http.build(); + } + +} diff --git a/spring-boot-starter/starter-security/src/test/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSampleApplicationTest.java b/spring-boot-starter/starter-security/src/test/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSampleApplicationTest.java new file mode 100644 index 00000000000..09fa9e8df4c --- /dev/null +++ b/spring-boot-starter/starter-security/src/test/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSampleApplicationTest.java @@ -0,0 +1,62 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. Camunda licenses this file to you under the Apache License, + * Version 2.0; you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.operaton.bpm.spring.boot.starter.security; + +import jakarta.annotation.PostConstruct; +import my.own.custom.spring.boot.project.SampleApplication; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.entry; +import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = SampleApplication.class, webEnvironment = RANDOM_PORT) +public class OperatonBpmSampleApplicationTest { + + private String baseUrl; + + @LocalServerPort + private int port; + + @Autowired + private TestRestTemplate testRestTemplate; + + @PostConstruct + public void postConstruct() { + baseUrl = "http://localhost:" + port; + } + + @Test + public void restApiIsAvailable() { + ResponseEntity entity = testRestTemplate.getForEntity(baseUrl + "/engine-rest/engine/", String.class); + // default Spring Security filter chain config redirects to /login + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FOUND); + assertThat(entity.getHeaders()).contains(entry(HttpHeaders.LOCATION, List.of(baseUrl + "/login"))); + } +} diff --git a/spring-boot-starter/starter-security/src/test/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSamplePermitAllApplicationTest.java b/spring-boot-starter/starter-security/src/test/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSamplePermitAllApplicationTest.java new file mode 100644 index 00000000000..c0335954f78 --- /dev/null +++ b/spring-boot-starter/starter-security/src/test/java/org/operaton/bpm/spring/boot/starter/security/OperatonBpmSamplePermitAllApplicationTest.java @@ -0,0 +1,47 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. Camunda licenses this file to you under the Apache License, + * Version 2.0; you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.operaton.bpm.spring.boot.starter.security; + +import my.own.custom.spring.boot.project.SamplePermitAllApplication; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +@RunWith(SpringRunner.class) +@SpringBootTest( + classes = SamplePermitAllApplication.class, + webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT +) +public class OperatonBpmSamplePermitAllApplicationTest { + + @Autowired + private TestRestTemplate testRestTemplate; + + @Test + public void restApiIsAvailable() { + ResponseEntity entity = testRestTemplate.getForEntity("/engine-rest/engine/", String.class); + assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(entity.getBody()).isEqualTo("[{\"name\":\"default\"}]"); + } +} diff --git a/spring-boot-starter/starter-security/src/test/resources/logback-test.xml b/spring-boot-starter/starter-security/src/test/resources/logback-test.xml new file mode 100644 index 00000000000..559f9d5c889 --- /dev/null +++ b/spring-boot-starter/starter-security/src/test/resources/logback-test.xml @@ -0,0 +1,8 @@ + + + + + + + + From 11a59e02fbcae14acac1b46a86b189aca6c0ebcf Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Wed, 6 Nov 2024 14:42:47 +0100 Subject: [PATCH 19/37] fixed version --- distro/run/modules/oauth2/pom.xml | 2 +- spring-boot-starter/starter-security/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/distro/run/modules/oauth2/pom.xml b/distro/run/modules/oauth2/pom.xml index 7756249f270..21c13db8fb9 100644 --- a/distro/run/modules/oauth2/pom.xml +++ b/distro/run/modules/oauth2/pom.xml @@ -5,7 +5,7 @@ org.operaton.bpm.run operaton-bpm-run-modules - 7.22.0-SNAPSHOT + 1.0.0-beta-2 .. diff --git a/spring-boot-starter/starter-security/pom.xml b/spring-boot-starter/starter-security/pom.xml index 06cc75760a1..3b97451a353 100644 --- a/spring-boot-starter/starter-security/pom.xml +++ b/spring-boot-starter/starter-security/pom.xml @@ -6,7 +6,7 @@ org.operaton.bpm.springboot.project operaton-bpm-spring-boot-starter-root - 7.22.0-SNAPSHOT + 1.0.0-beta-2 org.operaton.bpm.springboot From 86c18e61246ed5fdf8d577307297c2e96346b468 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Wed, 6 Nov 2024 15:46:17 +0100 Subject: [PATCH 20/37] fix(tests): Fix sonar.coverage.jacoco.xmlReportPaths (#78) With #951aef77 the wrong property slipped in. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 177eb6d547b..14710023bbd 100644 --- a/pom.xml +++ b/pom.xml @@ -35,7 +35,7 @@ 17 operaton https://sonarcloud.io - **/target/jacoco/jacoco.xml + **/target/jacoco/jacoco.xml From ebda83fb6d22985ace97a177740fdb93577d83c7 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Wed, 6 Nov 2024 21:05:46 +0100 Subject: [PATCH 21/37] chore(quarkus): Bump quarkus version to 3.14 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Related-to: https://github.com/camunda/camunda-bpm-platform/issues/4163 Backported commit 816b58f from the camunda-bpm-platform repository. Original author: Joaquín <165814090+joaquinfelici@users.noreply.github.com>" --- .../config/OperatonEngineConfigFileTest.java | 6 ++--- ...OperatonEngineConfigurationConfigTest.java | 6 ++--- .../OperatonEngineJobExecutorConfigTest.java | 20 ++++++++-------- ...onEngineProgrammaticAndConfigFileTest.java | 6 ++--- .../src/test/resources/application.properties | 2 +- .../job-executor-application.properties | 18 +++++++------- .../test/config/mixed-application.properties | 18 +++++++------- ...ocess-engine-config-application.properties | 8 +++---- .../src/test/resources/application.properties | 2 +- .../extension/OperatonEngineConfig.java | 21 +++++++--------- .../extension/OperatonJobExecutorConfig.java | 24 +++++++------------ .../impl/OperatonEngineRecorder.java | 10 ++++---- 12 files changed, 66 insertions(+), 75 deletions(-) diff --git a/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineConfigFileTest.java b/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineConfigFileTest.java index 2d201a4bb3e..14cc0c57733 100644 --- a/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineConfigFileTest.java +++ b/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineConfigFileTest.java @@ -67,10 +67,10 @@ public void shouldLoadAllConfigProperties() throws SQLException { assertThat(jobExecutor.getMaxWait()).isEqualTo(65000); assertThat(jobExecutor.getBackoffTimeInMillis()).isEqualTo(5); // assert correct thread pool config - assertThat(config.jobExecutor.threadPool.maxPoolSize).isEqualTo(12); - assertThat(config.jobExecutor.threadPool.queueSize).isEqualTo(5); + assertThat(config.jobExecutor().threadPool().maxPoolSize()).isEqualTo(12); + assertThat(config.jobExecutor().threadPool().queueSize()).isEqualTo(5); // assert correct datasource - assertThat(config.datasource).hasValue("operaton"); + assertThat(config.datasource()).hasValue("operaton"); assertThat(configuration.getDataSource().getConnection()).asString().contains("h2:mem:operaton"); } } \ No newline at end of file diff --git a/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineConfigurationConfigTest.java b/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineConfigurationConfigTest.java index 9fcde2bebfd..806775351b7 100644 --- a/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineConfigurationConfigTest.java +++ b/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineConfigurationConfigTest.java @@ -49,9 +49,9 @@ public void shouldLoadProcessEngineConfigurationProperties() { // given a custom application.properties file // then - assertThat(config.genericConfig.get("cmmn-enabled")).isEqualTo("false"); - assertThat(config.genericConfig.get("dmn-enabled")).isEqualTo("false"); - assertThat(config.genericConfig.get("history")).isEqualTo("none"); + assertThat(config.genericConfig().get("cmmn-enabled")).isEqualTo("false"); + assertThat(config.genericConfig().get("dmn-enabled")).isEqualTo("false"); + assertThat(config.genericConfig().get("history")).isEqualTo("none"); } @Test diff --git a/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineJobExecutorConfigTest.java b/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineJobExecutorConfigTest.java index bd99ec2bea2..6b44ab75cb2 100644 --- a/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineJobExecutorConfigTest.java +++ b/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineJobExecutorConfigTest.java @@ -44,8 +44,8 @@ public void shouldLoadJobExecutorThreadPoolProperties() { // given a custom application.properties file // then - assertThat(config.jobExecutor.threadPool.maxPoolSize).isEqualTo(12); - assertThat(config.jobExecutor.threadPool.queueSize).isEqualTo(5); + assertThat(config.jobExecutor().threadPool().maxPoolSize()).isEqualTo(12); + assertThat(config.jobExecutor().threadPool().queueSize()).isEqualTo(5); } @Test @@ -53,13 +53,13 @@ public void shouldLoadJobAcquisitionProperties() { // given a custom application.properties file // then - assertThat(config.jobExecutor.genericConfig.get("max-jobs-per-acquisition")).isEqualTo("5"); - assertThat(config.jobExecutor.genericConfig.get("lock-time-in-millis")).isEqualTo("500000"); - assertThat(config.jobExecutor.genericConfig.get("wait-time-in-millis")).isEqualTo("7000"); - assertThat(config.jobExecutor.genericConfig.get("max-wait")).isEqualTo("65000"); - assertThat(config.jobExecutor.genericConfig.get("backoff-time-in-millis")).isEqualTo("5"); - assertThat(config.jobExecutor.genericConfig.get("max-backoff")).isEqualTo("5"); - assertThat(config.jobExecutor.genericConfig.get("backoff-decrease-threshold")).isEqualTo("120"); - assertThat(config.jobExecutor.genericConfig.get("wait-increase-factor")).isEqualTo("3"); + assertThat(config.jobExecutor().genericConfig().get("max-jobs-per-acquisition")).isEqualTo("5"); + assertThat(config.jobExecutor().genericConfig().get("lock-time-in-millis")).isEqualTo("500000"); + assertThat(config.jobExecutor().genericConfig().get("wait-time-in-millis")).isEqualTo("7000"); + assertThat(config.jobExecutor().genericConfig().get("max-wait")).isEqualTo("65000"); + assertThat(config.jobExecutor().genericConfig().get("backoff-time-in-millis")).isEqualTo("5"); + assertThat(config.jobExecutor().genericConfig().get("max-backoff")).isEqualTo("5"); + assertThat(config.jobExecutor().genericConfig().get("backoff-decrease-threshold")).isEqualTo("120"); + assertThat(config.jobExecutor().genericConfig().get("wait-increase-factor")).isEqualTo("3"); } } diff --git a/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineProgrammaticAndConfigFileTest.java b/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineProgrammaticAndConfigFileTest.java index 4cf8c72f87d..ab0a29dd672 100644 --- a/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineProgrammaticAndConfigFileTest.java +++ b/quarkus-extension/engine/deployment/src/test/java/org/operaton/bpm/quarkus/engine/test/config/OperatonEngineProgrammaticAndConfigFileTest.java @@ -88,10 +88,10 @@ public void shouldUseProvidedConfigurationAndConfigProperties() throws SQLExcept assertThat(jobExecutor.getMaxWait()).isEqualTo(65000); assertThat(jobExecutor.getBackoffTimeInMillis()).isEqualTo(5); // assert correct thread pool config - assertThat(config.jobExecutor.threadPool.maxPoolSize).isEqualTo(12); - assertThat(config.jobExecutor.threadPool.queueSize).isEqualTo(5); + assertThat(config.jobExecutor().threadPool().maxPoolSize()).isEqualTo(12); + assertThat(config.jobExecutor().threadPool().queueSize()).isEqualTo(5); // assert correct datasource - assertThat(config.datasource).hasValue("operaton"); + assertThat(config.datasource()).hasValue("operaton"); assertThat(configuration.getDataSource().getConnection()).asString().contains("h2:mem:operaton"); } } \ No newline at end of file diff --git a/quarkus-extension/engine/deployment/src/test/resources/application.properties b/quarkus-extension/engine/deployment/src/test/resources/application.properties index c4d90ee12a6..22ce7663147 100644 --- a/quarkus-extension/engine/deployment/src/test/resources/application.properties +++ b/quarkus-extension/engine/deployment/src/test/resources/application.properties @@ -1,2 +1,2 @@ quarkus.datasource.jdbc.url=jdbc:h2:mem:operaton;TRACE_LEVEL_FILE=0;DB_CLOSE_ON_EXIT=FALSE -quarkus.operaton.enforce-history-time-to-live=false \ No newline at end of file +quarkus.operaton.generic-config.enforce-history-time-to-live=false \ No newline at end of file diff --git a/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/job-executor-application.properties b/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/job-executor-application.properties index 341a2533df9..b6f7df1bf20 100644 --- a/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/job-executor-application.properties +++ b/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/job-executor-application.properties @@ -1,15 +1,15 @@ quarkus.operaton.job-executor.thread-pool.max-pool-size=12 quarkus.operaton.job-executor.thread-pool.queue-size=5 -quarkus.operaton.job-executor.max-jobs-per-acquisition=5 -quarkus.operaton.job-executor.lock-time-in-millis=500000 -quarkus.operaton.job-executor.wait-time-in-millis=7000 -quarkus.operaton.job-executor.max-wait=65000 -quarkus.operaton.job-executor.backoff-time-in-millis=5 -quarkus.operaton.job-executor.max-backoff=5 -quarkus.operaton.job-executor.backoff-decrease-threshold=120 -quarkus.operaton.job-executor.wait-increase-factor=3 +quarkus.operaton.job-executor.generic-config.max-jobs-per-acquisition=5 +quarkus.operaton.job-executor.generic-config.lock-time-in-millis=500000 +quarkus.operaton.job-executor.generic-config.wait-time-in-millis=7000 +quarkus.operaton.job-executor.generic-config.max-wait=65000 +quarkus.operaton.job-executor.generic-config.backoff-time-in-millis=5 +quarkus.operaton.job-executor.generic-config.max-backoff=5 +quarkus.operaton.job-executor.generic-config.backoff-decrease-threshold=120 +quarkus.operaton.job-executor.generic-config.wait-increase-factor=3 quarkus.datasource.jdbc.url=jdbc:h2:mem:operaton;TRACE_LEVEL_FILE=0;DB_CLOSE_ON_EXIT=FALSE -quarkus.operaton.enforce-history-time-to-live=false \ No newline at end of file +quarkus.operaton.generic-config.enforce-history-time-to-live=false \ No newline at end of file diff --git a/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/mixed-application.properties b/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/mixed-application.properties index 363710ce92b..77829f68b26 100644 --- a/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/mixed-application.properties +++ b/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/mixed-application.properties @@ -1,16 +1,16 @@ -quarkus.operaton.cmmn-enabled=false -quarkus.operaton.dmn-enabled=false -quarkus.operaton.history=none -quarkus.operaton.enforce-history-time-to-live=false +quarkus.operaton.generic-config.cmmn-enabled=false +quarkus.operaton.generic-config.dmn-enabled=false +quarkus.operaton.generic-config.history=none +quarkus.operaton.generic-config.enforce-history-time-to-live=false quarkus.operaton.job-executor.thread-pool.max-pool-size=12 quarkus.operaton.job-executor.thread-pool.queue-size=5 -quarkus.operaton.job-executor.max-jobs-per-acquisition=5 -quarkus.operaton.job-executor.lock-time-in-millis=500000 -quarkus.operaton.job-executor.wait-time-in-millis=7000 -quarkus.operaton.job-executor.max-wait=65000 -quarkus.operaton.job-executor.backoff-time-in-millis=5 +quarkus.operaton.job-executor.generic-config.max-jobs-per-acquisition=5 +quarkus.operaton.job-executor.generic-config.lock-time-in-millis=500000 +quarkus.operaton.job-executor.generic-config.wait-time-in-millis=7000 +quarkus.operaton.job-executor.generic-config.max-wait=65000 +quarkus.operaton.job-executor.generic-config.backoff-time-in-millis=5 quarkus.datasource.operaton.db-kind=h2 quarkus.datasource.operaton.username=operaton diff --git a/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/process-engine-config-application.properties b/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/process-engine-config-application.properties index f288bf295e2..1662729a065 100644 --- a/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/process-engine-config-application.properties +++ b/quarkus-extension/engine/deployment/src/test/resources/org/operaton/bpm/quarkus/engine/test/config/process-engine-config-application.properties @@ -1,6 +1,6 @@ -quarkus.operaton.cmmn-enabled=false -quarkus.operaton.dmn-enabled=false -quarkus.operaton.history=none -quarkus.operaton.enforce-history-time-to-live=false +quarkus.operaton.generic-config.cmmn-enabled=false +quarkus.operaton.generic-config.dmn-enabled=false +quarkus.operaton.generic-config.history=none +quarkus.operaton.generic-config.enforce-history-time-to-live=false quarkus.datasource.jdbc.url=jdbc:h2:mem:operaton;TRACE_LEVEL_FILE=0;DB_CLOSE_ON_EXIT=FALSE \ No newline at end of file diff --git a/quarkus-extension/engine/qa/src/test/resources/application.properties b/quarkus-extension/engine/qa/src/test/resources/application.properties index 8bdeecb7689..3abfea8fd1f 100644 --- a/quarkus-extension/engine/qa/src/test/resources/application.properties +++ b/quarkus-extension/engine/qa/src/test/resources/application.properties @@ -6,4 +6,4 @@ quarkus.log.category."org.operaton".level=INFO quarkus.datasource.jdbc.url=jdbc:h2:mem:operaton;TRACE_LEVEL_FILE=0;DB_CLOSE_ON_EXIT=FALSE -quarkus.operaton.enforce-history-time-to-live=false \ No newline at end of file +quarkus.operaton.generic-config.enforce-history-time-to-live=false \ No newline at end of file diff --git a/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/OperatonEngineConfig.java b/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/OperatonEngineConfig.java index 00fead4723a..e3ef6311874 100644 --- a/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/OperatonEngineConfig.java +++ b/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/OperatonEngineConfig.java @@ -16,22 +16,21 @@ */ package org.operaton.bpm.quarkus.engine.extension; -import java.util.Map; -import java.util.Optional; - -import io.quarkus.runtime.annotations.ConfigItem; import io.quarkus.runtime.annotations.ConfigPhase; import io.quarkus.runtime.annotations.ConfigRoot; +import io.smallrye.config.ConfigMapping; +import java.util.Map; +import java.util.Optional; -@ConfigRoot(phase = ConfigPhase.RUN_TIME, name = "operaton") -public class OperatonEngineConfig { +@ConfigMapping(prefix = "quarkus.operaton") +@ConfigRoot(phase = ConfigPhase.RUN_TIME) +public interface OperatonEngineConfig { /** * The Operaton ProcessEngineConfiguration properties. For more details, * @see Process Engine Configuration Properties. */ - @ConfigItem(name = ConfigItem.PARENT) - public Map genericConfig; + Map genericConfig(); /** * The Operaton JobExecutor config. It provides available job acquisition thread configuration @@ -39,13 +38,11 @@ public class OperatonEngineConfig { * * The JobExecutor is responsible for running Operaton jobs. */ - @ConfigItem - public OperatonJobExecutorConfig jobExecutor; + OperatonJobExecutorConfig jobExecutor(); /** * Select a datasource by name or the default datasource is used. */ - @ConfigItem - public Optional datasource; + Optional datasource(); } \ No newline at end of file diff --git a/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/OperatonJobExecutorConfig.java b/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/OperatonJobExecutorConfig.java index b9d7f5a6bf3..4693588ae6a 100644 --- a/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/OperatonJobExecutorConfig.java +++ b/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/OperatonJobExecutorConfig.java @@ -16,42 +16,36 @@ */ package org.operaton.bpm.quarkus.engine.extension; +import io.smallrye.config.WithDefault; import java.util.Map; -import io.quarkus.runtime.annotations.ConfigGroup; -import io.quarkus.runtime.annotations.ConfigItem; - -@ConfigGroup -public class OperatonJobExecutorConfig { +public interface OperatonJobExecutorConfig { /** * The Operaton JobExecutor configuration properties. For more details, * @see Job-Acquisition Configuration Properties */ - @ConfigItem(name = ConfigItem.PARENT) - public Map genericConfig; + Map genericConfig(); /** * The Operaton JobExecutor thread pool config. This thread pool is responsible for running * Operaton jobs. */ - @ConfigItem - public ThreadPoolConfig threadPool; + ThreadPoolConfig threadPool(); - @ConfigGroup - public static class ThreadPoolConfig { + interface ThreadPoolConfig { /** * Sets the maximum number of threads that can be present in the Quarkus-managed * thread pool for the Operaton JobExecutor. The default value is 10. */ - @ConfigItem(defaultValue = "10") - public int maxPoolSize; + @WithDefault("10") + int maxPoolSize(); /** * Sets the size of the Quarkus-managed JobExecutor queue. The default value is 3. */ - @ConfigItem(defaultValue = "3") - public int queueSize; + @WithDefault("3") + int queueSize(); } } \ No newline at end of file diff --git a/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/impl/OperatonEngineRecorder.java b/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/impl/OperatonEngineRecorder.java index 31a8e6200e1..4a07c44cd28 100644 --- a/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/impl/OperatonEngineRecorder.java +++ b/quarkus-extension/engine/runtime/src/main/java/org/operaton/bpm/quarkus/engine/extension/impl/OperatonEngineRecorder.java @@ -59,10 +59,10 @@ public RuntimeValue createProcessEngineConfigura beanContainer); // apply properties from config before any other configuration. - PropertyHelper.applyProperties(configuration, config.genericConfig, PropertyHelper.KEBAB_CASE); + PropertyHelper.applyProperties(configuration, config.genericConfig(), PropertyHelper.KEBAB_CASE); if (configuration.getDataSource() == null) { - String datasource = config.datasource.orElse(DEFAULT_DATASOURCE_NAME); + String datasource = config.datasource().orElse(DEFAULT_DATASOURCE_NAME); configuration.setDataSource(DataSources.fromName(datasource)); } @@ -138,8 +138,8 @@ public void registerShutdownTask(ShutdownContext shutdownContext, protected void configureJobExecutor(ProcessEngineConfigurationImpl configuration, OperatonEngineConfig config) { - int maxPoolSize = config.jobExecutor.threadPool.maxPoolSize; - int queueSize = config.jobExecutor.threadPool.queueSize; + int maxPoolSize = config.jobExecutor().threadPool().maxPoolSize(); + int queueSize = config.jobExecutor().threadPool().queueSize(); // create a non-bean ManagedExecutor instance. This instance // uses it's own Executor/thread pool. @@ -152,7 +152,7 @@ protected void configureJobExecutor(ProcessEngineConfigurationImpl configuration // apply job executor configuration properties PropertyHelper - .applyProperties(quarkusJobExecutor, config.jobExecutor.genericConfig, PropertyHelper.KEBAB_CASE); + .applyProperties(quarkusJobExecutor, config.jobExecutor().genericConfig(), PropertyHelper.KEBAB_CASE); configuration.setJobExecutor(quarkusJobExecutor); } From eaa33aa758c968d0e1fbb1bf9da125ecd0eebdff Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Mon, 4 Nov 2024 23:03:09 +0100 Subject: [PATCH 22/37] feat(engine): add historicProcInsQuery to executeModificationAsync related to: #4620 Backported commit 1b9de30e4c from the camunda-bpm-platform repository. Original author: Gergely Juhasz --- .../bpm/engine/rest/dto/ModificationDto.ftl | 8 + .../bpm/engine/rest/dto/ModificationDto.java | 10 + .../impl/ModificationRestServiceImpl.java | 8 + ...odificationRestServiceInteractionTest.java | 162 +++++++++ .../engine/impl/ModificationBuilderImpl.java | 12 + .../impl/cmd/AbstractModificationCmd.java | 7 + .../engine/runtime/ModificationBuilder.java | 8 + .../ModificationExecutionAsyncTest.java | 308 ++++++++++++++++++ .../ModificationExecutionSyncTest.java | 87 +++++ ...ionTest.syncAfterOneTaskProcess.bpmn20.xml | 17 + 10 files changed, 627 insertions(+) create mode 100644 engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.syncAfterOneTaskProcess.bpmn20.xml diff --git a/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/ModificationDto.ftl b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/ModificationDto.ftl index cdbbb46d552..94d6b54fe5f 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/ModificationDto.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/ModificationDto.ftl @@ -37,6 +37,14 @@ desc = "A process instance query." /> + <@lib.property + name = "historicProcessInstanceQuery" + type = "ref" + dto = "HistoricProcessInstanceQueryDto" + desc = "A historic process instance query. It is advised to include the `unfinished` filter in the + historic process instance query as finished instances cause failures for the modification." + /> + <@lib.property name = "instructions" type = "array" diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/ModificationDto.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/ModificationDto.java index aa41d69bfde..c5ad56679d5 100644 --- a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/ModificationDto.java +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/ModificationDto.java @@ -19,6 +19,8 @@ import java.util.List; import org.operaton.bpm.engine.ProcessEngine; +import org.operaton.bpm.engine.history.HistoricProcessInstanceQuery; +import org.operaton.bpm.engine.rest.dto.history.HistoricProcessInstanceQueryDto; import org.operaton.bpm.engine.rest.dto.runtime.ProcessInstanceQueryDto; import org.operaton.bpm.engine.rest.dto.runtime.modification.ProcessInstanceModificationInstructionDto; import org.operaton.bpm.engine.runtime.ModificationBuilder; @@ -30,6 +32,7 @@ public class ModificationDto { protected List instructions; protected List processInstanceIds; protected ProcessInstanceQueryDto processInstanceQuery; + protected HistoricProcessInstanceQueryDto historicProcessInstanceQuery; protected String processDefinitionId; protected boolean skipIoMappings; protected boolean skipCustomListeners; @@ -99,4 +102,11 @@ public void setAnnotation(String annotation) { this.annotation = annotation; } + public HistoricProcessInstanceQueryDto getHistoricProcessInstanceQuery() { + return historicProcessInstanceQuery; + } + + public void setHistoricProcessInstanceQuery(HistoricProcessInstanceQueryDto historicProcessInstanceQuery) { + this.historicProcessInstanceQuery = historicProcessInstanceQuery; + } } diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/impl/ModificationRestServiceImpl.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/impl/ModificationRestServiceImpl.java index 04ddf71bbc3..9f1188d0b3a 100644 --- a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/impl/ModificationRestServiceImpl.java +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/impl/ModificationRestServiceImpl.java @@ -22,9 +22,11 @@ import org.operaton.bpm.engine.BadUserRequestException; import org.operaton.bpm.engine.batch.Batch; +import org.operaton.bpm.engine.history.HistoricProcessInstanceQuery; import org.operaton.bpm.engine.rest.ModificationRestService; import org.operaton.bpm.engine.rest.dto.ModificationDto; import org.operaton.bpm.engine.rest.dto.batch.BatchDto; +import org.operaton.bpm.engine.rest.dto.history.HistoricProcessInstanceQueryDto; import org.operaton.bpm.engine.rest.dto.runtime.ProcessInstanceQueryDto; import org.operaton.bpm.engine.rest.exception.InvalidRequestException; import org.operaton.bpm.engine.runtime.ModificationBuilder; @@ -74,6 +76,12 @@ private ModificationBuilder createModificationBuilder(ModificationDto dto) { builder.processInstanceQuery(processInstanceQuery); } + HistoricProcessInstanceQueryDto historicProcessInstanceQueryDto = dto.getHistoricProcessInstanceQuery(); + if(historicProcessInstanceQueryDto != null) { + HistoricProcessInstanceQuery historicProcessInstanceQuery = historicProcessInstanceQueryDto.toQuery(getProcessEngine()); + builder.historicProcessInstanceQuery(historicProcessInstanceQuery); + } + if (dto.isSkipCustomListeners()) { builder.skipCustomListeners(); } diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/ModificationRestServiceInteractionTest.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/ModificationRestServiceInteractionTest.java index ec5dc387a94..2399c790475 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/ModificationRestServiceInteractionTest.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/ModificationRestServiceInteractionTest.java @@ -32,9 +32,12 @@ import org.operaton.bpm.engine.AuthorizationException; import org.operaton.bpm.engine.BadUserRequestException; +import org.operaton.bpm.engine.HistoryService; import org.operaton.bpm.engine.RuntimeService; import org.operaton.bpm.engine.batch.Batch; +import org.operaton.bpm.engine.impl.HistoricProcessInstanceQueryImpl; import org.operaton.bpm.engine.impl.ProcessInstanceQueryImpl; +import org.operaton.bpm.engine.rest.dto.history.HistoricProcessInstanceQueryDto; import org.operaton.bpm.engine.rest.dto.runtime.ProcessInstanceQueryDto; import org.operaton.bpm.engine.rest.exception.InvalidRequestException; import org.operaton.bpm.engine.rest.util.ModificationInstructionBuilder; @@ -57,6 +60,7 @@ public class ModificationRestServiceInteractionTest extends AbstractRestServiceT protected static final String EXECUTE_MODIFICATION_ASYNC_URL = PROCESS_INSTANCE_URL + "/executeAsync"; protected RuntimeService runtimeServiceMock; + protected HistoryService historyServiceMock; protected ModificationBuilder modificationBuilderMock; @Before @@ -64,6 +68,9 @@ public void setUpRuntimeData() { runtimeServiceMock = mock(RuntimeService.class); when(processEngine.getRuntimeService()).thenReturn(runtimeServiceMock); + historyServiceMock = mock(HistoryService.class); + when(processEngine.getHistoryService()).thenReturn(historyServiceMock); + modificationBuilderMock = mock(ModificationBuilder.class); when(modificationBuilderMock.cancelAllForActivity(any())).thenReturn(modificationBuilderMock); when(modificationBuilderMock.startAfterActivity(any())).thenReturn(modificationBuilderMock); @@ -299,6 +306,39 @@ public void executeModificationWithValidProcessInstanceQuerySync() { verify(modificationBuilderMock).execute(); } + @Test + public void executeModificationWithValidHistoricProcessInstanceQuerySync() { + + when(historyServiceMock.createHistoricProcessInstanceQuery()).thenReturn(new HistoricProcessInstanceQueryImpl()); + Map json = new HashMap(); + + List> instructions = new ArrayList>(); + instructions.add(ModificationInstructionBuilder.startAfter().activityId("activityId").getJson()); + json.put("processDefinitionId", "processDefinitionId"); + + HistoricProcessInstanceQueryDto historicProcessInstanceQueryDto = new HistoricProcessInstanceQueryDto(); + historicProcessInstanceQueryDto.setProcessInstanceBusinessKey("foo"); + + json.put("historicProcessInstanceQuery", historicProcessInstanceQueryDto); + + json.put("instructions", instructions); + + given() + .contentType(ContentType.JSON) + .body(json) + .then() + .expect() + .statusCode(Status.NO_CONTENT.getStatusCode()) + .when() + .post(EXECUTE_MODIFICATION_SYNC_URL); + + verify(historyServiceMock, times(1)).createHistoricProcessInstanceQuery(); + verify(modificationBuilderMock).startAfterActivity("activityId"); + verify(modificationBuilderMock).historicProcessInstanceQuery(historicProcessInstanceQueryDto.toQuery(processEngine)); + verify(modificationBuilderMock).execute(); + } + + @Test public void executeModificationWithValidProcessInstanceQueryAsync() { @@ -330,6 +370,74 @@ public void executeModificationWithValidProcessInstanceQueryAsync() { verify(modificationBuilderMock).executeAsync(); } + @Test + public void executeModificationWithValidHistoricProcessInstanceQueryAsync() { + when(historyServiceMock.createHistoricProcessInstanceQuery()).thenReturn(new HistoricProcessInstanceQueryImpl()); + Map json = new HashMap(); + + List> instructions = new ArrayList>(); + instructions.add(ModificationInstructionBuilder.startAfter().activityId("activityId").getJson()); + + HistoricProcessInstanceQueryDto historicProcessInstanceQueryDto = new HistoricProcessInstanceQueryDto(); + historicProcessInstanceQueryDto.setProcessInstanceBusinessKey("foo"); + + json.put("historicProcessInstanceQuery", historicProcessInstanceQueryDto); + json.put("instructions", instructions); + json.put("processDefinitionId", "processDefinitionId"); + + given() + .contentType(ContentType.JSON) + .body(json) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .post(EXECUTE_MODIFICATION_ASYNC_URL); + + verify(historyServiceMock, times(1)).createHistoricProcessInstanceQuery(); + verify(modificationBuilderMock).startAfterActivity("activityId"); + verify(modificationBuilderMock).historicProcessInstanceQuery(historicProcessInstanceQueryDto.toQuery(processEngine)); + verify(modificationBuilderMock).executeAsync(); + } + + @Test + public void executeModificationWithBothProcessInstanceQueries() { + when(historyServiceMock.createHistoricProcessInstanceQuery()).thenReturn(new HistoricProcessInstanceQueryImpl()); + when(runtimeServiceMock.createProcessInstanceQuery()).thenReturn(new ProcessInstanceQueryImpl()); + + Map json = new HashMap(); + + List> instructions = new ArrayList>(); + instructions.add(ModificationInstructionBuilder.startAfter().activityId("activityId").getJson()); + + HistoricProcessInstanceQueryDto historicProcessInstanceQueryDto = new HistoricProcessInstanceQueryDto(); + historicProcessInstanceQueryDto.setProcessInstanceBusinessKey("foo"); + + ProcessInstanceQueryDto processInstanceQueryDto = new ProcessInstanceQueryDto(); + processInstanceQueryDto.setBusinessKey("foo"); + + json.put("processInstanceQuery", processInstanceQueryDto); + json.put("historicProcessInstanceQuery", historicProcessInstanceQueryDto); + json.put("instructions", instructions); + json.put("processDefinitionId", "processDefinitionId"); + + given() + .contentType(ContentType.JSON) + .body(json) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .post(EXECUTE_MODIFICATION_ASYNC_URL); + + verify(historyServiceMock, times(1)).createHistoricProcessInstanceQuery(); + verify(modificationBuilderMock).startAfterActivity("activityId"); + verify(modificationBuilderMock).historicProcessInstanceQuery(historicProcessInstanceQueryDto.toQuery(processEngine)); + verify(runtimeServiceMock, times(1)).createProcessInstanceQuery(); + verify(modificationBuilderMock).processInstanceQuery(processInstanceQueryDto.toQuery(processEngine)); + verify(modificationBuilderMock).executeAsync(); + } + @Test public void executeModificationWithInvalidProcessInstanceQuerySync() { @@ -359,6 +467,35 @@ public void executeModificationWithInvalidProcessInstanceQuerySync() { } + @Test + public void executeModificationWithInvalidHistoricProcessInstanceQuerySync() { + when(historyServiceMock.createHistoricProcessInstanceQuery()).thenReturn(new HistoricProcessInstanceQueryImpl()); + + Map json = new HashMap(); + + String message = "Process instance ids is null"; + doThrow(new BadUserRequestException(message)).when(modificationBuilderMock).execute(); + + List> instructions = new ArrayList>(); + instructions.add(ModificationInstructionBuilder.startAfter().activityId("acivityId").getJson()); + + HistoricProcessInstanceQueryDto historicProcessInstanceQueryDto = new HistoricProcessInstanceQueryDto(); + historicProcessInstanceQueryDto.setProcessInstanceBusinessKey("foo"); + + json.put("historicProcessInstanceQuery", historicProcessInstanceQueryDto); + json.put("instructions", instructions); + json.put("processDefinitionId", "processDefinitionId"); + + given() + .contentType(ContentType.JSON) + .body(json) + .then() + .expect() + .statusCode(Status.BAD_REQUEST.getStatusCode()) + .when() + .post(EXECUTE_MODIFICATION_SYNC_URL); + } + @Test public void executeModificationWithInvalidProcessInstanceQueryAsync() { @@ -384,6 +521,31 @@ public void executeModificationWithInvalidProcessInstanceQueryAsync() { .post(EXECUTE_MODIFICATION_ASYNC_URL); } + @Test + public void executeModificationWithInvalidHistoricProcessInstanceQueryAsync() { + when(historyServiceMock.createHistoricProcessInstanceQuery()).thenReturn(new HistoricProcessInstanceQueryImpl()); + Map json = new HashMap(); + + List> instructions = new ArrayList>(); + instructions.add(ModificationInstructionBuilder.startAfter().activityId("acivityId").getJson()); + + HistoricProcessInstanceQueryDto historicProcessInstanceQueryDto = new HistoricProcessInstanceQueryDto(); + historicProcessInstanceQueryDto.setProcessInstanceBusinessKey("foo"); + + json.put("historicProcessInstanceQuery", historicProcessInstanceQueryDto); + json.put("instructions", instructions); + json.put("processDefinitionId", "processDefinitionId"); + + given() + .contentType(ContentType.JSON) + .body(json) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .when() + .post(EXECUTE_MODIFICATION_ASYNC_URL); + } + @Test public void executeModificationWithNullInstructionsSync() { doThrow(new BadUserRequestException("Instructions must be set")).when(modificationBuilderMock).execute(); diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/ModificationBuilderImpl.java b/engine/src/main/java/org/operaton/bpm/engine/impl/ModificationBuilderImpl.java index 14803399f6e..876cbc28c4f 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/ModificationBuilderImpl.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/ModificationBuilderImpl.java @@ -25,6 +25,7 @@ import org.operaton.bpm.engine.batch.Batch; import org.operaton.bpm.engine.exception.NotValidException; +import org.operaton.bpm.engine.history.HistoricProcessInstanceQuery; import org.operaton.bpm.engine.impl.cmd.AbstractProcessInstanceModificationCommand; import org.operaton.bpm.engine.impl.cmd.ActivityAfterInstantiationCmd; import org.operaton.bpm.engine.impl.cmd.ActivityBeforeInstantiationCmd; @@ -40,6 +41,7 @@ public class ModificationBuilderImpl implements ModificationBuilder { protected CommandExecutor commandExecutor; protected ProcessInstanceQuery processInstanceQuery; + protected HistoricProcessInstanceQuery historicProcessInstanceQuery; protected List processInstanceIds; protected List instructions; protected String processDefinitionId; @@ -114,6 +116,12 @@ public ModificationBuilder processInstanceQuery(ProcessInstanceQuery processInst return this; } + @Override + public ModificationBuilder historicProcessInstanceQuery(HistoricProcessInstanceQuery historicProcessInstanceQuery) { + this.historicProcessInstanceQuery = historicProcessInstanceQuery; + return this; + } + @Override public ModificationBuilder skipCustomListeners() { this.skipCustomListeners = true; @@ -153,6 +161,10 @@ public ProcessInstanceQuery getProcessInstanceQuery() { return processInstanceQuery; } + public HistoricProcessInstanceQuery getHistoricProcessInstanceQuery() { + return historicProcessInstanceQuery; + } + public List getProcessInstanceIds() { return processInstanceIds; } diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/AbstractModificationCmd.java b/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/AbstractModificationCmd.java index fd49a930195..e89e060e7fa 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/AbstractModificationCmd.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/cmd/AbstractModificationCmd.java @@ -23,6 +23,7 @@ import java.util.Set; import org.operaton.bpm.engine.history.UserOperationLogEntry; +import org.operaton.bpm.engine.impl.HistoricProcessInstanceQueryImpl; import org.operaton.bpm.engine.impl.ModificationBuilderImpl; import org.operaton.bpm.engine.impl.ProcessInstanceQueryImpl; import org.operaton.bpm.engine.impl.interceptor.Command; @@ -53,6 +54,12 @@ protected Collection collectProcessInstanceIds() { collectedProcessInstanceIds.addAll(processInstanceQuery.listIds()); } + final HistoricProcessInstanceQueryImpl historicProcessInstanceQuery = + (HistoricProcessInstanceQueryImpl) builder.getHistoricProcessInstanceQuery(); + if(historicProcessInstanceQuery != null) { + collectedProcessInstanceIds.addAll(historicProcessInstanceQuery.listIds()); + } + return collectedProcessInstanceIds; } diff --git a/engine/src/main/java/org/operaton/bpm/engine/runtime/ModificationBuilder.java b/engine/src/main/java/org/operaton/bpm/engine/runtime/ModificationBuilder.java index aecb21f13ce..45714e63aa2 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/runtime/ModificationBuilder.java +++ b/engine/src/main/java/org/operaton/bpm/engine/runtime/ModificationBuilder.java @@ -24,6 +24,7 @@ import org.operaton.bpm.engine.authorization.Permissions; import org.operaton.bpm.engine.authorization.Resources; import org.operaton.bpm.engine.batch.Batch; +import org.operaton.bpm.engine.history.HistoricProcessInstanceQuery; public interface ModificationBuilder extends InstantiationBuilder{ @@ -116,5 +117,12 @@ public interface ModificationBuilder extends InstantiationBuilder */ Batch executeAsync(); + + /** + * @param historicProcessInstanceQuery a query which selects the process instances to modify. + * It is advised to include the `unfinished` filter in the historicProcessInstanceQuery as finished instances cause failures for the modification. + * Query results are restricted to process instances for which the user has {@link Permissions#READ_HISTORY} permission. + */ + ModificationBuilder historicProcessInstanceQuery(HistoricProcessInstanceQuery historicProcessInstanceQuery); } diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/ModificationExecutionAsyncTest.java b/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/ModificationExecutionAsyncTest.java index dab148b01a7..3e9cc63d282 100644 --- a/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/ModificationExecutionAsyncTest.java +++ b/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/ModificationExecutionAsyncTest.java @@ -35,12 +35,15 @@ import java.util.List; import org.assertj.core.api.Assertions; +import org.operaton.bpm.engine.HistoryService; import org.operaton.bpm.engine.ProcessEngineConfiguration; import org.operaton.bpm.engine.ProcessEngineException; import org.operaton.bpm.engine.RuntimeService; +import org.operaton.bpm.engine.TaskService; import org.operaton.bpm.engine.batch.Batch; import org.operaton.bpm.engine.batch.history.HistoricBatch; import org.operaton.bpm.engine.delegate.ExecutionListener; +import org.operaton.bpm.engine.history.HistoricProcessInstanceQuery; import org.operaton.bpm.engine.impl.batch.BatchSeedJobHandler; import org.operaton.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl; import org.operaton.bpm.engine.impl.persistence.entity.ExecutionEntity; @@ -55,6 +58,7 @@ import org.operaton.bpm.engine.runtime.ProcessInstanceQuery; import org.operaton.bpm.engine.runtime.VariableInstance; import org.operaton.bpm.engine.task.Task; +import org.operaton.bpm.engine.test.Deployment; import org.operaton.bpm.engine.test.ProcessEngineRule; import org.operaton.bpm.engine.test.RequiredHistoryLevel; import org.operaton.bpm.engine.test.bpmn.multiinstance.DelegateEvent; @@ -86,6 +90,7 @@ public class ModificationExecutionAsyncTest { protected ProcessEngineConfigurationImpl configuration; protected RuntimeService runtimeService; + protected HistoryService historyService; protected BpmnModelInstance instance; @@ -110,6 +115,7 @@ public static Collection scenarios() throws ParseException { @Before public void initServices() { runtimeService = rule.getRuntimeService(); + historyService = rule.getHistoryService(); } @Before @@ -245,6 +251,17 @@ public void testNullProcessInstanceQueryAsync() { } } + @Test + public void testNullHistoricProcessInstanceQueryAsync() { + + try { + runtimeService.createModification("processDefinitionId").startAfterActivity("user1").historicProcessInstanceQuery(null).executeAsync(); + fail("Should not succeed"); + } catch (ProcessEngineException e) { + assertThat(e.getMessage()).contains("Process instance ids is empty"); + } + } + @Test public void createModificationWithNonExistingProcessDefinitionId() { DeploymentWithDefinitions deployment = testRule.deploy(instance); @@ -841,6 +858,114 @@ public void testBatchExecutionFailureWithMissingProcessInstance() { assertThat(failedJob.getExceptionMessage()).contains("Process instance '" + deletedProcessInstanceId + "' cannot be modified"); } + @Test + public void testBatchExecutionFailureWithHistoricQueryThatMatchesDeletedInstance() { + DeploymentWithDefinitions deployment = testRule.deploy(instance); + ProcessDefinition processDefinition = deployment.getDeployedProcessDefinitions().get(0); + + List startedInstances = helper.startInstances("process1", 3); + RuntimeService runtimeService = rule.getRuntimeService(); + + String deletedProcessInstanceId = startedInstances.get(0); + + runtimeService.deleteProcessInstance(deletedProcessInstanceId, "test"); + + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery().processDefinitionId(processDefinition.getId()); + + Batch batch = runtimeService + .createModification(processDefinition.getId()) + .startAfterActivity("user1") + .historicProcessInstanceQuery(historicProcessInstanceQuery) + .executeAsync(); + + helper.completeSeedJobs(batch); + + // when + helper.executeJobs(batch); + + // then the remaining process instance was modified + for (String processInstanceId : startedInstances) { + if (processInstanceId.equals(deletedProcessInstanceId)) { + ActivityInstance updatedTree = runtimeService.getActivityInstance(processInstanceId); + assertNull(updatedTree); + continue; + } + + ActivityInstance updatedTree = runtimeService.getActivityInstance(processInstanceId); + assertNotNull(updatedTree); + assertEquals(processInstanceId, updatedTree.getProcessInstanceId()); + + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree( + processDefinition.getId()) + .activity("user1") + .activity("user2") + .done()); + } + + // and one batch job failed and has 2 retries left + List modificationJobs = helper.getExecutionJobs(batch); + assertEquals(1, modificationJobs.size()); + + Job failedJob = modificationJobs.get(0); + assertEquals(2, failedJob.getRetries()); + assertThat(failedJob.getExceptionMessage()).startsWith("ENGINE-13036"); + assertThat(failedJob.getExceptionMessage()).contains("Process instance '" + deletedProcessInstanceId + "' cannot be modified"); + } + + @Test + @Deployment(resources = { "org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.syncAfterOneTaskProcess.bpmn20.xml" }) + public void testBatchExecutionWithHistoricQueryUnfinished() { + // given + List startedInstances = helper.startInstances("oneTaskProcess", 3); + + TaskService taskService = rule.getTaskService(); + Task task = taskService.createTaskQuery().processInstanceId(startedInstances.get(0)).singleResult(); + String processDefinitionId = task.getProcessDefinitionId(); + String completedProcessInstanceId = task.getProcessInstanceId(); + assertNotNull(task); + taskService.complete(task.getId()); + + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery().unfinished().processDefinitionId(processDefinitionId); + assertEquals(2, historicProcessInstanceQuery.count()); + + // then + Batch batch = runtimeService + .createModification(processDefinitionId) + .startAfterActivity("theStart") + .historicProcessInstanceQuery(historicProcessInstanceQuery) + .executeAsync(); + + helper.completeSeedJobs(batch); + + // when + helper.executeJobs(batch); + + // then the remaining process instance was modified + for (String processInstanceId : startedInstances) { + if (processInstanceId.equals(completedProcessInstanceId)) { + ActivityInstance updatedTree = runtimeService.getActivityInstance(processInstanceId); + assertNull(updatedTree); + continue; + } + + ActivityInstance updatedTree = runtimeService.getActivityInstance(processInstanceId); + assertNotNull(updatedTree); + assertEquals(processInstanceId, updatedTree.getProcessInstanceId()); + + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree( + processDefinitionId) + .activity("theTask") + .activity("theTask") + .done()); + } + + // and one batch job failed and has 2 retries left + List modificationJobs = helper.getExecutionJobs(batch); + assertEquals(0, modificationJobs.size()); + } + @Test public void testBatchCreationWithProcessInstanceQuery() { int processInstanceCount = 15; @@ -862,6 +987,142 @@ public void testBatchCreationWithProcessInstanceQuery() { assertBatchCreated(batch, processInstanceCount); } + @Test + public void testBatchCreationWithHistoricProcessInstanceQuery() { + int processInstanceCount = 15; + DeploymentWithDefinitions deployment = testRule.deploy(instance); + ProcessDefinition processDefinition = deployment.getDeployedProcessDefinitions().get(0); + helper.startInstances("process1", 15); + + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery().processDefinitionId(processDefinition.getId()); + assertEquals(processInstanceCount, historicProcessInstanceQuery.count()); + + // when + Batch batch = runtimeService + .createModification(processDefinition.getId()) + .startAfterActivity("user1") + .historicProcessInstanceQuery(historicProcessInstanceQuery) + .executeAsync(); + + // then a batch is created + assertBatchCreated(batch, processInstanceCount); + } + + @Test + @Deployment(resources = { "org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.syncAfterOneTaskProcess.bpmn20.xml" }) + public void testBatchExecutionFailureWithFinishedInstanceId() { + // given + List startedInstances = helper.startInstances("oneTaskProcess", 3); + + TaskService taskService = rule.getTaskService(); + Task task = taskService.createTaskQuery().processInstanceId(startedInstances.get(0)).singleResult(); + String processDefinitionId = task.getProcessDefinitionId(); + String completedProcessInstanceId = task.getProcessInstanceId(); + assertNotNull(task); + taskService.complete(task.getId()); + + // then + Batch batch = runtimeService + .createModification(processDefinitionId) + .startAfterActivity("theStart") + .processInstanceIds(startedInstances) + .executeAsync(); + + helper.completeSeedJobs(batch); + + // when + helper.executeJobs(batch); + + // then the remaining process instance was modified + for (String processInstanceId : startedInstances) { + if (processInstanceId.equals(completedProcessInstanceId)) { + ActivityInstance updatedTree = runtimeService.getActivityInstance(processInstanceId); + assertNull(updatedTree); + continue; + } + + ActivityInstance updatedTree = runtimeService.getActivityInstance(processInstanceId); + assertNotNull(updatedTree); + assertEquals(processInstanceId, updatedTree.getProcessInstanceId()); + + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree( + processDefinitionId) + .activity("theTask") + .activity("theTask") + .done()); + } + + // and one batch job failed and has 2 retries left + List modificationJobs = helper.getExecutionJobs(batch); + assertEquals(1, modificationJobs.size()); + + Job failedJob = modificationJobs.get(0); + assertEquals(2, failedJob.getRetries()); + assertThat(failedJob.getExceptionMessage()).startsWith("ENGINE-13036"); + assertThat(failedJob.getExceptionMessage()).contains("Process instance '" + completedProcessInstanceId + "' cannot be modified"); + } + + + @Test + @Deployment(resources = { "org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.syncAfterOneTaskProcess.bpmn20.xml" }) + public void testBatchExecutionFailureWithHistoricQueryThatMatchesFinishedInstance() { + // given + List startedInstances = helper.startInstances("oneTaskProcess", 3); + + TaskService taskService = rule.getTaskService(); + Task task = taskService.createTaskQuery().processInstanceId(startedInstances.get(0)).singleResult(); + String processDefinitionId = task.getProcessDefinitionId(); + String completedProcessInstanceId = task.getProcessInstanceId(); + assertNotNull(task); + taskService.complete(task.getId()); + + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery().processDefinitionId(processDefinitionId); + assertEquals(3, historicProcessInstanceQuery.count()); + + // then + Batch batch = runtimeService + .createModification(processDefinitionId) + .startAfterActivity("theStart") + .historicProcessInstanceQuery(historicProcessInstanceQuery) + .executeAsync(); + + helper.completeSeedJobs(batch); + + // when + helper.executeJobs(batch); + + // then the remaining process instance was modified + for (String processInstanceId : startedInstances) { + if (processInstanceId.equals(completedProcessInstanceId)) { + ActivityInstance updatedTree = runtimeService.getActivityInstance(processInstanceId); + assertNull(updatedTree); + continue; + } + + ActivityInstance updatedTree = runtimeService.getActivityInstance(processInstanceId); + assertNotNull(updatedTree); + assertEquals(processInstanceId, updatedTree.getProcessInstanceId()); + + assertThat(updatedTree).hasStructure( + describeActivityInstanceTree( + processDefinitionId) + .activity("theTask") + .activity("theTask") + .done()); + } + + // and one batch job failed and has 2 retries left + List modificationJobs = helper.getExecutionJobs(batch); + assertEquals(1, modificationJobs.size()); + + Job failedJob = modificationJobs.get(0); + assertEquals(2, failedJob.getRetries()); + assertThat(failedJob.getExceptionMessage()).startsWith("ENGINE-13036"); + assertThat(failedJob.getExceptionMessage()).contains("Process instance '" + completedProcessInstanceId + "' cannot be modified"); + } + + @Test public void testBatchCreationWithOverlappingProcessInstanceIdsAndQuery() { int processInstanceCount = 15; @@ -884,6 +1145,53 @@ public void testBatchCreationWithOverlappingProcessInstanceIdsAndQuery() { assertBatchCreated(batch, processInstanceCount); } + @Test + public void testBatchCreationWithOverlappingProcessInstanceIdsAndHistoricQuery() { + int processInstanceCount = 15; + DeploymentWithDefinitions deployment = testRule.deploy(instance); + ProcessDefinition processDefinition = deployment.getDeployedProcessDefinitions().get(0); + List processInstanceIds = helper.startInstances("process1", 15); + + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery().processDefinitionId(processDefinition.getId()); + assertEquals(processInstanceCount, historicProcessInstanceQuery.count()); + + // when + Batch batch = runtimeService + .createModification(processDefinition.getId()) + .startTransition("seq") + .processInstanceIds(processInstanceIds) + .historicProcessInstanceQuery(historicProcessInstanceQuery) + .executeAsync(); + + // then a batch is created + assertBatchCreated(batch, processInstanceCount); + } + + @Test + public void testBatchCreationWithOverlappingHistoricQueryAndQuery() { + // given + int processInstanceCount = 15; + DeploymentWithDefinitions deployment = testRule.deploy(instance); + ProcessDefinition processDefinition = deployment.getDeployedProcessDefinitions().get(0); + helper.startInstances("process1", processInstanceCount); + + ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery().processDefinitionId(processDefinition.getId()); + assertEquals(processInstanceCount, processInstanceQuery.count()); + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery().processDefinitionId(processDefinition.getId()); + assertEquals(processInstanceCount, historicProcessInstanceQuery.count()); + + // when + Batch batch = runtimeService + .createModification(processDefinition.getId()) + .startTransition("seq") + .processInstanceQuery(processInstanceQuery) + .historicProcessInstanceQuery(historicProcessInstanceQuery) + .executeAsync(); + + // then a batch is created + assertBatchCreated(batch, processInstanceCount); + } + @Test public void testListenerInvocation() { // given diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/ModificationExecutionSyncTest.java b/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/ModificationExecutionSyncTest.java index 2e5abccefe9..aa08975f4fb 100644 --- a/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/ModificationExecutionSyncTest.java +++ b/engine/src/test/java/org/operaton/bpm/engine/test/api/runtime/ModificationExecutionSyncTest.java @@ -29,13 +29,16 @@ import java.util.Collections; import java.util.List; +import org.operaton.bpm.engine.HistoryService; import org.operaton.bpm.engine.ProcessEngineException; import org.operaton.bpm.engine.RuntimeService; +import org.operaton.bpm.engine.history.HistoricProcessInstanceQuery; import org.operaton.bpm.engine.impl.persistence.entity.ExecutionEntity; import org.operaton.bpm.engine.repository.DeploymentWithDefinitions; import org.operaton.bpm.engine.repository.ProcessDefinition; import org.operaton.bpm.engine.runtime.ActivityInstance; import org.operaton.bpm.engine.runtime.Execution; +import org.operaton.bpm.engine.runtime.ProcessInstanceQuery; import org.operaton.bpm.engine.task.Task; import org.operaton.bpm.engine.test.ProcessEngineRule; import org.operaton.bpm.engine.test.util.ProcessEngineTestRule; @@ -59,6 +62,7 @@ public class ModificationExecutionSyncTest { public RuleChain ruleChain = RuleChain.outerRule(rule).around(testRule); protected RuntimeService runtimeService; + protected HistoryService historyService; protected BpmnModelInstance instance; @Before @@ -76,6 +80,7 @@ public void createBpmnModelInstance() { @Before public void initServices() { runtimeService = rule.getRuntimeService(); + historyService = rule.getHistoryService(); } @After @@ -97,6 +102,78 @@ public void createSimpleModificationPlan() { } } + @Test + public void createSimpleModificationPlanWithHistoricQuery() { + ProcessDefinition processDefinition = testRule.deployAndGetDefinition(instance); + List instances = helper.startInstances("process1", 2); + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery(); + historicProcessInstanceQuery.processDefinitionId(processDefinition.getId()); + + runtimeService.createModification(processDefinition.getId()).startBeforeActivity("user2") + .cancelAllForActivity("user1").historicProcessInstanceQuery(historicProcessInstanceQuery).execute(); + + for (String instanceId : instances) { + List activeActivityIds = runtimeService.getActiveActivityIds(instanceId); + assertEquals(1, activeActivityIds.size()); + assertEquals(activeActivityIds.iterator().next(), "user2"); + } + } + + @Test + public void createSimpleModificationPlanWithIdenticalRuntimeAndHistoryQuery() { + ProcessDefinition processDefinition = testRule.deployAndGetDefinition(instance); + List instances = helper.startInstances("process1", 2); + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery(); + historicProcessInstanceQuery.processDefinitionId(processDefinition.getId()); + ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery(); + processInstanceQuery.processDefinitionId(processDefinition.getId()); + + runtimeService.createModification(processDefinition.getId()).startBeforeActivity("user2") + .cancelAllForActivity("user1").historicProcessInstanceQuery(historicProcessInstanceQuery).processInstanceQuery(processInstanceQuery).execute(); + + for (String instanceId : instances) { + List activeActivityIds = runtimeService.getActiveActivityIds(instanceId); + assertEquals(1, activeActivityIds.size()); + assertEquals(activeActivityIds.iterator().next(), "user2"); + } + } + + @Test + public void createSimpleModificationPlanWithComplementaryRuntimeAndHistoryQueries() { + ProcessDefinition processDefinition = testRule.deployAndGetDefinition(instance); + List instances = helper.startInstances("process1", 2); + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery(); + historicProcessInstanceQuery.processInstanceId(instances.get(0)); + ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery(); + processInstanceQuery.processInstanceId(instances.get(1)); + + runtimeService.createModification(processDefinition.getId()).startBeforeActivity("user2") + .cancelAllForActivity("user1").historicProcessInstanceQuery(historicProcessInstanceQuery).processInstanceQuery(processInstanceQuery).execute(); + + for (String instanceId : instances) { + List activeActivityIds = runtimeService.getActiveActivityIds(instanceId); + assertEquals(1, activeActivityIds.size()); + assertEquals(activeActivityIds.iterator().next(), "user2"); + } + } + + @Test + public void createSimpleModificationPlanWithHistoricQueryUnfinished() { + ProcessDefinition processDefinition = testRule.deployAndGetDefinition(instance); + List instances = helper.startInstances("process1", 2); + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery(); + historicProcessInstanceQuery.processDefinitionId(processDefinition.getId()).unfinished(); + + runtimeService.deleteProcessInstance(instances.get(0), "test"); + + runtimeService.createModification(processDefinition.getId()).startBeforeActivity("user2") + .cancelAllForActivity("user1").historicProcessInstanceQuery(historicProcessInstanceQuery).execute(); + + List activeActivityIds = runtimeService.getActiveActivityIds(instances.get(1)); + assertEquals(1, activeActivityIds.size()); + assertEquals(activeActivityIds.iterator().next(), "user2"); + } + @Test public void createModificationWithNullProcessInstanceIdsList() { @@ -174,6 +251,16 @@ public void testNullProcessInstanceQuery() { } } + @Test + public void testNullHistoricProcessInstanceQuery() { + try { + runtimeService.createModification("processDefinitionId").startAfterActivity("user1").historicProcessInstanceQuery(null).execute(); + fail("Should not succeed"); + } catch (ProcessEngineException e) { + assertThat(e.getMessage()).contains("Process instance ids is empty"); + } + } + @Test public void createModificationWithNotMatchingProcessDefinitionId() { DeploymentWithDefinitions deployment = testRule.deploy(instance); diff --git a/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.syncAfterOneTaskProcess.bpmn20.xml b/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.syncAfterOneTaskProcess.bpmn20.xml new file mode 100644 index 00000000000..562df9d6e34 --- /dev/null +++ b/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.syncAfterOneTaskProcess.bpmn20.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + From fb051bf69312dab7fc3a5c898b4adbbfba735ff9 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Wed, 6 Nov 2024 23:22:20 +0100 Subject: [PATCH 23/37] =?UTF-8?q?fix(mssql):=20replace=20or=20with=20union?= =?UTF-8?q?=20in=20external=20task=20to=20improve=20perform=E2=80=A6=20(#1?= =?UTF-8?q?39)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(mssql): replace or with union in external task to improve performance Backported commit 3151c40896c from the camunda-bpm-platform repository. Original author: Joaquín <165814090+joaquinfelici@users.noreply.github.com> * Update import in ExternalTaskQueryAuthorizationTest Replaced 'org.camunda.commons.testing.ProcessEngineLoggingRule' with 'org.operaton.commons.testing.ProcessEngineLoggingRule'. This change ensures consistency with the naming convention used across the project. --- .../cfg/ProcessEngineConfigurationImpl.java | 1 + .../impl/db/sql/DbSqlSessionFactory.java | 3 + .../impl/mapping/entity/Authorization.xml | 34 ++++++++++- .../ExternalTaskQueryAuthorizationTest.java | 59 +++++++++++++++++++ 4 files changed, 94 insertions(+), 3 deletions(-) diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/cfg/ProcessEngineConfigurationImpl.java b/engine/src/main/java/org/operaton/bpm/engine/impl/cfg/ProcessEngineConfigurationImpl.java index 25c5d3f454b..355e6150d7d 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/cfg/ProcessEngineConfigurationImpl.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/cfg/ProcessEngineConfigurationImpl.java @@ -1943,6 +1943,7 @@ public static void initSqlSessionFactoryProperties(Properties properties, String properties.put("authJoin1Separator", DbSqlSessionFactory.databaseSpecificAuth1JoinSeparator.get(databaseType)); properties.put("extractTimeUnitFromDate", DbSqlSessionFactory.databaseSpecificExtractTimeUnitFromDate.get(databaseType)); + properties.put("authCheckMethodSuffix", DbSqlSessionFactory.databaseSpecificAuthCheckMethodSuffix.getOrDefault(databaseType, "")); Map constants = DbSqlSessionFactory.dbSpecificConstants.get(databaseType); for (Entry entry : constants.entrySet()) { diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/db/sql/DbSqlSessionFactory.java b/engine/src/main/java/org/operaton/bpm/engine/impl/db/sql/DbSqlSessionFactory.java index 3d41397bf96..79365091770 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/db/sql/DbSqlSessionFactory.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/db/sql/DbSqlSessionFactory.java @@ -106,6 +106,8 @@ public class DbSqlSessionFactory implements SessionFactory { public static final Map databaseSpecificAuth1JoinSeparator = new HashMap<>(); public static final Map databaseSpecificExtractTimeUnitFromDate = new HashMap<>(); + public static final Map databaseSpecificAuthCheckMethodSuffix = new HashMap<>(); + /* * On SQL server, the overall maximum number of parameters in a prepared statement @@ -729,6 +731,7 @@ public class DbSqlSessionFactory implements SessionFactory { databaseSpecificAuthJoinStart.put(MSSQL, defaultAuthOnStart); databaseSpecificAuthJoinEnd.put(MSSQL, defaultAuthOnEnd); databaseSpecificAuthJoinSeparator.put(MSSQL, defaultAuthOnSeparator); + databaseSpecificAuthCheckMethodSuffix.put(MSSQL, "_mssql"); databaseSpecificAuth1JoinStart.put(MSSQL, defaultAuthOnStart); databaseSpecificAuth1JoinEnd.put(MSSQL, defaultAuthOnEnd); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/Authorization.xml b/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/Authorization.xml index 3b4f8b7e12b..70bca14a0ef 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/Authorization.xml +++ b/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/Authorization.xml @@ -844,7 +844,8 @@ - + + @@ -861,6 +862,34 @@ OR A.GROUP_ID_ IN #{item} ) + + ) + + + + + left join + inner join + + ( + SELECT A.* + FROM ${prefix}ACT_RU_AUTHORIZATION A + WHERE A.TYPE_ < 2 + AND A.USER_ID_ in ( #{authCheck.authUserId, jdbcType=VARCHAR}, '*') + + + UNION ( + SELECT A.* + FROM ${prefix}ACT_RU_AUTHORIZATION A + WHERE A.TYPE_ < 2 + AND A.GROUP_ID_ IN #{item} + + ) + + ) + + + AND ( @@ -874,8 +903,7 @@ ) - - ) + + + or + + + I.GROUP_ID_ LIKE #{candidateGroupLike} + ) diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/api/filter/FilterTaskQueryTest.java b/engine/src/test/java/org/operaton/bpm/engine/test/api/filter/FilterTaskQueryTest.java index 4d752a026a4..d9b2dacaa69 100644 --- a/engine/src/test/java/org/operaton/bpm/engine/test/api/filter/FilterTaskQueryTest.java +++ b/engine/src/test/java/org/operaton/bpm/engine/test/api/filter/FilterTaskQueryTest.java @@ -185,6 +185,7 @@ public void testTaskQuery() { query.taskUnassigned(); query.taskAssigned(); query.taskDelegationState(testDelegationState); + query.taskCandidateGroupLike(testString); query.taskCandidateGroupIn(testCandidateGroups); query.taskCandidateGroupInExpression(testString); query.withCandidateGroups(); @@ -290,6 +291,7 @@ public void testTaskQuery() { assertTrue(query.isUnassigned()); assertTrue(query.isAssigned()); assertEquals(testDelegationState, query.getDelegationState()); + assertEquals(testString, query.getCandidateGroupLike()); assertEquals(testCandidateGroups, query.getCandidateGroups()); assertTrue(query.isWithCandidateGroups()); assertTrue(query.isWithoutCandidateGroups()); @@ -657,6 +659,21 @@ public void testTaskQueryCandidateGroup() { assertEquals(testGroup.getId(), query.getExpressions().get("taskCandidateGroup")); } + @Test + public void testTaskQueryCandidateGroupLike() { + // given + TaskQueryImpl query = new TaskQueryImpl(); + query.taskCandidateGroupLike(testGroup.getId()); + + saveQuery(query); + + // when + query = filter.getQuery(); + + // then + assertEquals(testGroup.getId(), query.getCandidateGroupLike()); + } + @Test public void testTaskQueryCandidateUserIncludeAssignedTasks() { TaskQueryImpl query = new TaskQueryImpl(); @@ -709,6 +726,23 @@ public void testTaskQueryCandidateGroupExpressionIncludeAssignedTasks() { assertTrue(query.isIncludeAssignedTasks()); } + @Test + public void testTaskQueryCandidateGroupLikeIncludeAssignedTasks() { + // given + TaskQueryImpl query = new TaskQueryImpl(); + query.taskCandidateGroupLike(testGroup.getId()); + query.includeAssignedTasks(); + + saveQuery(query); + + // when + query = filter.getQuery(); + + // then + assertEquals(testGroup.getId(), query.getCandidateGroupLike()); + assertTrue(query.isIncludeAssignedTasks()); + } + @Test public void testTaskQueryCandidateGroupsIncludeAssignedTasks() { TaskQueryImpl query = new TaskQueryImpl(); @@ -823,6 +857,56 @@ public void testExtendingTaskQueryWithAssigneeNotIn() { assertEquals(0, extendingQueryTasks.size()); } + @Test + public void testExtendingEmptyTaskQueryWithCandidateGroupLike() { + // given 3 test tasks created during setup + TaskQuery query = taskService.createTaskQuery(); + saveQuery(query); + List tasks = filterService.list(filter.getId()); + assertEquals(3, tasks.size()); + + // when extending the query with a "candidate group like" + TaskQuery extendingQuery = taskService.createTaskQuery(); + extendingQuery.taskCandidateGroupLike("%count%"); + + // then there is 1 unassigned task with the candidate group "accounting" + tasks = filterService.list(filter.getId(), extendingQuery); + assertEquals(1, tasks.size()); + } + + @Test + public void testExtendingCandidateGroupLikeTaskQueryWithEmpty() { + // given 3 existing tasks but only 1 unassigned task that matches the initial filter + TaskQuery query = taskService.createTaskQuery().taskCandidateGroupLike("%count%"); + saveQuery(query); + List tasks = filterService.list(filter.getId()); + assertEquals(1, tasks.size()); + + // when extending the query with an empty query + TaskQuery extendingQuery = taskService.createTaskQuery(); + + // then the empty query should be ignored in favor of the existing value for "candidate group like" + tasks = filterService.list(filter.getId(), extendingQuery); + assertEquals(1, tasks.size()); + } + + @Test + public void testExtendingCandidateGroupLikeTaskQueryWithCandidateGroupLike() { + // given 3 existing tasks but zero match the initial filter + TaskQuery query = taskService.createTaskQuery().taskCandidateGroupLike("HR"); + saveQuery(query); + List tasks = filterService.list(filter.getId()); + assertTrue(tasks.isEmpty()); + + // when extending the query with a "candidate groups like" query + TaskQuery extendingQuery = taskService.createTaskQuery(); + extendingQuery.taskCandidateGroupLike("acc%"); + + // then the query should be return result of task matching the new filter + tasks = filterService.list(filter.getId(), extendingQuery); + assertEquals(1, tasks.size()); + } + @Test public void testExtendingTaskQueryListWithCandidateGroups() { TaskQuery query = taskService.createTaskQuery(); diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/api/task/TaskQueryTest.java b/engine/src/test/java/org/operaton/bpm/engine/test/api/task/TaskQueryTest.java index 57d089c2100..1214a2f5498 100644 --- a/engine/src/test/java/org/operaton/bpm/engine/test/api/task/TaskQueryTest.java +++ b/engine/src/test/java/org/operaton/bpm/engine/test/api/task/TaskQueryTest.java @@ -36,6 +36,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -613,6 +614,70 @@ public void testQueryByIncludeAssignedTasksWithMissingCandidateUserOrGroup() { } } + @Test + public void testQueryByIncludeAssignedTasksWithoutMissingCandidateUserOrGroup() { + // We expect no exceptions when the there is at least 1 candidate user or group present + try { + taskService.createTaskQuery().taskCandidateUser("user").includeAssignedTasks(); + } catch (ProcessEngineException e) { + fail("We expect no exceptions when a taskCandidateUser is present"); + } + + try { + taskService.createTaskQuery().taskCandidateGroupLike("%group%").includeAssignedTasks(); + } catch (ProcessEngineException e) { + fail("We expect no exceptions when a candidateGroupLike is present"); + } + + try { + taskService.createTaskQuery().taskCandidateGroupIn(List.of("group")).includeAssignedTasks(); + } catch (ProcessEngineException e) { + fail("We expect no exceptions when a taskCandidateGroupIn is present"); + } + + try { + taskService.createTaskQuery().withCandidateGroups().includeAssignedTasks(); + } catch (ProcessEngineException e) { + fail("We expect no exceptions when a withCandidateGroups is present"); + } + + try { + taskService.createTaskQuery().withoutCandidateGroups().includeAssignedTasks(); + } catch (ProcessEngineException e) { + fail("We expect no exceptions when a withoutCandidateGroups is present"); + } + + try { + taskService.createTaskQuery().withCandidateUsers().includeAssignedTasks(); + } catch (ProcessEngineException e) { + fail("We expect no exceptions when a withCandidateUsers is present"); + } + + try { + taskService.createTaskQuery().withoutCandidateUsers().includeAssignedTasks(); + } catch (ProcessEngineException e) { + fail("We expect no exceptions when a withoutCandidateUsers is present"); + } + + try { + taskService.createTaskQuery().taskCandidateUserExpression("expression").includeAssignedTasks(); + } catch (ProcessEngineException e) { + fail("We expect no exceptions when a taskCandidateUserExpression is present"); + } + + try { + taskService.createTaskQuery().taskCandidateGroupExpression("expression").includeAssignedTasks(); + } catch (ProcessEngineException e) { + fail("We expect no exceptions when a taskCandidateGroupExpression is present"); + } + + try { + taskService.createTaskQuery().taskCandidateGroupInExpression("expression").includeAssignedTasks(); + } catch (ProcessEngineException e) { + fail("We expect no exceptions when a taskCandidateGroupInExpression is present"); + } + } + @Test public void testQueryByCandidateGroup() { // management group is candidate for 3 tasks, one of them is already assigned @@ -653,6 +718,58 @@ public void testQueryByCandidateGroup() { assertEquals(0, query.list().size()); } + @Test + public void testQueryByCandidateGroupLike() { + // management group is candidate for 3 tasks, one of them is already assigned + TaskQuery query = taskService.createTaskQuery().taskCandidateGroupLike("management"); + assertEquals(2, query.count()); + assertEquals(2, query.list().size()); + assertThrows(ProcessEngineException.class, query::singleResult); + + // test with "shortened" group name for like query + query = taskService.createTaskQuery().taskCandidateGroupLike("mana%"); + assertEquals(2, query.count()); + assertEquals(2, query.list().size()); + assertThrows(ProcessEngineException.class, query::singleResult); + + // test with "shortened" group name for like query (different part) + query = taskService.createTaskQuery().taskCandidateGroupLike("%ment"); + assertEquals(2, query.count()); + assertEquals(2, query.list().size()); + assertThrows(ProcessEngineException.class, query::singleResult); + + // test management candidates group with assigned tasks included + query = taskService.createTaskQuery().taskCandidateGroupLike("management").includeAssignedTasks(); + assertEquals(3, query.count()); + assertEquals(3, query.list().size()); + assertThrows(ProcessEngineException.class, query::singleResult); + + // test with "shortened" group name for like query (assigned tasks included) + query = taskService.createTaskQuery().taskCandidateGroupLike("mana%").includeAssignedTasks(); + assertEquals(3, query.count()); + assertEquals(3, query.list().size()); + assertThrows(ProcessEngineException.class, query::singleResult); + + // test with "shortened" group name for like query (different part, assigned tasks included) + query = taskService.createTaskQuery().taskCandidateGroupLike("%ment").includeAssignedTasks(); + assertEquals(3, query.count()); + assertEquals(3, query.list().size()); + assertThrows(ProcessEngineException.class, query::singleResult); + + // test query that matches tasks with the "management" the "accountancy" candidate groups + // accountancy group is candidate for 3 tasks, one of them is already assigned + query = taskService.createTaskQuery().taskCandidateGroupLike("%an%"); + assertEquals(4, query.count()); + assertEquals(4, query.list().size()); + assertThrows(ProcessEngineException.class, query::singleResult); + + // test query that matches tasks with the "management" the "accountancy" candidate groups (assigned tasks included) + query = taskService.createTaskQuery().taskCandidateGroupLike("%an%").includeAssignedTasks(); + assertEquals(5, query.count()); + assertEquals(5, query.list().size()); + assertThrows(ProcessEngineException.class, query::singleResult); + } + @Test public void testQueryWithCandidateGroups() { // test withCandidateGroups From 1bca5f9afc853c3b057036051820f215702acd99 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Tue, 5 Nov 2024 16:29:47 +0100 Subject: [PATCH 29/37] chore: Remove Swagger References - CONTRIBUTING.md Related-to: https://github.com/camunda/camunda-bpm-platform/issues/4467 Backported commit 233c9820eb from the camunda-bpm-platform repository. Original author: psavidis <69160690+psavidis@users.noreply.github.com> --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8a742bc5fa7..ae6a8ceb889 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,8 +69,8 @@ An entire repository can be built by running `mvn clean install` in the root dir This will build all sub modules and execute unit tests. Furthermore, you can restrict the build to just the module you are changing by running the same command in the corresponding directory. Check the repository's or module's README for additional module-specific instructions. -The `webapps` and `swagger-ui` modules requires NodeJS. -You can exclude building them by running `mvn clean install -pl '!webapps,!webapps/assembly,!webapps/assembly-jakarta,!org.operaton.bpm.run:operaton-bpm-run-modules-swaggerui'`. +The `webapps` module requires NodeJS. +You can exclude building them by running `mvn clean install -pl '!webapps,!webapps/assembly,!webapps/assembly-jakarta'`. Integration tests (e.g. tests that run in an actual application server) are usually not part of the default Maven profiles. If you think they are relevant to your contribution, please ask us in the ticket, on the forum or in your pull request for how to run them. Smaller contributions usually do not need this. From 5134ed5d397bf57e027e5d965e3eb1b4c7885ff9 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Thu, 7 Nov 2024 11:40:01 +0100 Subject: [PATCH 30/37] chore(release): update German translation Related to https://github.com/camunda/camunda-bpm-platform/issues/4266#event-14411902807 Backported commit 818d03cd25 from the camunda-bpm-platform repository. Original author: Miklas Boskamp " --- webapps/frontend/public/app/admin/locales/de.json | 6 +++++- webapps/frontend/public/app/cockpit/locales/de.json | 6 +++++- webapps/frontend/public/app/tasklist/locales/de.json | 6 +++++- webapps/frontend/public/app/welcome/locales/de.json | 6 +++++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/webapps/frontend/public/app/admin/locales/de.json b/webapps/frontend/public/app/admin/locales/de.json index 69a4e2aa944..959bf21953b 100644 --- a/webapps/frontend/public/app/admin/locales/de.json +++ b/webapps/frontend/public/app/admin/locales/de.json @@ -659,6 +659,10 @@ "USER_MEMBERSHIP_TENANT_SELECT_TENANTS": "Mandanten auswählen", "USER_MEMBERSHIP_TENANT_TENANT_ID": "Mandanten-ID", "USER_MEMBERSHIP_TENANT_TENANT_NAME": "Mandanten-Name", - "VALUE": "Wert" + "VALUE": "Wert", + "SEARCH_LESS_THAN": "<", + "SEARCH_LESS_THAN_EQUALS": "<=", + "SEARCH_GREATER_THAN": ">", + "SEARCH_GREATER_THAN_EQUALS": ">=" } } diff --git a/webapps/frontend/public/app/cockpit/locales/de.json b/webapps/frontend/public/app/cockpit/locales/de.json index ed179e7f02b..ab2cdbe8465 100644 --- a/webapps/frontend/public/app/cockpit/locales/de.json +++ b/webapps/frontend/public/app/cockpit/locales/de.json @@ -2539,6 +2539,10 @@ "VARIABLE_UPLOAD_PROGRESS": "Fortschritt: {{progress}}%", "VARIABLE_UPLOAD_SELECT_FILE": "Wähle die Datei, die den binären Inhalt für die Variable beinhaltet", "VARIABLE_UPLOAD_UPLOAD": "Hochladen", - "WITHOUT_DUE_DATE": "Ohne Fälligkeitsdatum" + "WITHOUT_DUE_DATE": "Ohne Fälligkeitsdatum", + "SEARCH_LESS_THAN": "<", + "SEARCH_LESS_THAN_EQUALS": "<=", + "SEARCH_GREATER_THAN": ">", + "SEARCH_GREATER_THAN_EQUALS": ">=" } } diff --git a/webapps/frontend/public/app/tasklist/locales/de.json b/webapps/frontend/public/app/tasklist/locales/de.json index d439cfa2290..374c3420ca1 100644 --- a/webapps/frontend/public/app/tasklist/locales/de.json +++ b/webapps/frontend/public/app/tasklist/locales/de.json @@ -497,6 +497,10 @@ "name": "Name", "owner": "Besitzer", "parentTask": "Übergeordnete Aufgabe", - "priority": "Priorität" + "priority": "Priorität", + "SEARCH_LESS_THAN": "<", + "SEARCH_LESS_THAN_EQUALS": "<=", + "SEARCH_GREATER_THAN": ">", + "SEARCH_GREATER_THAN_EQUALS": ">=" } } diff --git a/webapps/frontend/public/app/welcome/locales/de.json b/webapps/frontend/public/app/welcome/locales/de.json index df76a24b41b..03a439045ae 100644 --- a/webapps/frontend/public/app/welcome/locales/de.json +++ b/webapps/frontend/public/app/welcome/locales/de.json @@ -166,6 +166,10 @@ "TOGGLE_NAVIGATION": "Navigation umschalten", "UPDATE": "Aktualisieren", "USERNAME": "Benutzername", - "USERNAME_FOR_AUTHENTICATION": "Benutzername für Authentifizierung: {{username}}" + "USERNAME_FOR_AUTHENTICATION": "Benutzername für Authentifizierung: {{username}}", + "SEARCH_LESS_THAN": "<", + "SEARCH_LESS_THAN_EQUALS": "<=", + "SEARCH_GREATER_THAN": ">", + "SEARCH_GREATER_THAN_EQUALS": ">=" } } From d39044c141760729ce1962df00cab544e4df87c6 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Thu, 7 Nov 2024 11:41:50 +0100 Subject: [PATCH 31/37] fix(de.json): Add a missing space --- webapps/frontend/public/app/cockpit/locales/de.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/webapps/frontend/public/app/cockpit/locales/de.json b/webapps/frontend/public/app/cockpit/locales/de.json index ab2cdbe8465..acc00dfb7fb 100644 --- a/webapps/frontend/public/app/cockpit/locales/de.json +++ b/webapps/frontend/public/app/cockpit/locales/de.json @@ -1665,7 +1665,7 @@ "PLGN_SEAR_PI_VARIABLE": "Prozessinstanz : Variable", "PLGN_SEAR_PI_WITHOUT_TENANT_ID": "Prozessinstanz : ohne Mandanten Id", "PLGN_SEAR_PI_WITH_INCIDENTS_ONLY": "Prozessinstanz : Nur mit Zwischenfällen", - "PLGN_SEAR_PI_WITH_ROOT_INCIDENTS_ONLY": "Prozessinstanz: Nur mit verursachenden Zwischenfällen", + "PLGN_SEAR_PI_WITH_ROOT_INCIDENTS_ONLY": "Prozessinstanz : Nur mit verursachenden Zwischenfällen", "PLGN_SEAR_PROCESS_DEFINITION_ID": "Prozessdefinitions-ID", "PLGN_SEAR_PROCESS_INSTANCE": "Prozessinstanz", "PLGN_SEAR_PROCINST_ID": "Prozessinstanz-ID", From 66019b96dcb6f4b3d1e40f9d66f2effb6d898d22 Mon Sep 17 00:00:00 2001 From: Karsten Thoms Date: Thu, 7 Nov 2024 03:06:57 +0100 Subject: [PATCH 32/37] chore(deps-dev): Ensure that everywhere the same JUnit 5 version is used (#155) --- internal-dependencies/pom.xml | 4 ---- parent/pom.xml | 1 + quarkus-extension/pom.xml | 7 +++++++ spring-boot-starter/pom.xml | 7 +++++++ test-utils/assert/pom.xml | 7 +++++++ 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/internal-dependencies/pom.xml b/internal-dependencies/pom.xml index 8a38f11fdda..b30ae29500a 100644 --- a/internal-dependencies/pom.xml +++ b/internal-dependencies/pom.xml @@ -15,10 +15,6 @@ Operaton core internal bill of material for dependencies - - 5.11.3 - - diff --git a/parent/pom.xml b/parent/pom.xml index d84a3048343..02e8630b2cd 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -77,6 +77,7 @@ 20.14.0 10.7.0 + 5.11.3 diff --git a/quarkus-extension/pom.xml b/quarkus-extension/pom.xml index f253fcdec17..98387496432 100644 --- a/quarkus-extension/pom.xml +++ b/quarkus-extension/pom.xml @@ -18,6 +18,13 @@ + + org.junit + junit-bom + ${version.junit5} + pom + import + io.quarkus quarkus-bom diff --git a/spring-boot-starter/pom.xml b/spring-boot-starter/pom.xml index ee63de16841..d1539c57697 100644 --- a/spring-boot-starter/pom.xml +++ b/spring-boot-starter/pom.xml @@ -16,6 +16,13 @@ + + org.junit + junit-bom + ${version.junit5} + pom + import + org.springframework.boot diff --git a/test-utils/assert/pom.xml b/test-utils/assert/pom.xml index 4b38999ff00..b2cf693a91f 100644 --- a/test-utils/assert/pom.xml +++ b/test-utils/assert/pom.xml @@ -14,6 +14,13 @@ + + org.junit + junit-bom + ${version.junit5} + pom + import + @@ -634,6 +643,21 @@ ) + + ${queryType} ( + ( + HAI.END_TIME_ IS NULL + AND HAI.ACT_ID_ IN + + #{activityId} + + ) OR INCACT.ACTIVITY_ID_ IN + + #{activityId} + + ) + + ${queryType} ( HAI.END_TIME_ IS NOT NULL diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.java b/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.java index 5503e655285..18c52f1aaca 100644 --- a/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.java +++ b/engine/src/test/java/org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.java @@ -36,9 +36,11 @@ import java.util.Date; import java.util.GregorianCalendar; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.lang3.time.DateUtils; import org.operaton.bpm.engine.BadUserRequestException; @@ -58,17 +60,22 @@ import org.operaton.bpm.engine.history.HistoricVariableInstance; import org.operaton.bpm.engine.impl.history.HistoryLevel; import org.operaton.bpm.engine.impl.history.event.HistoricProcessInstanceEventEntity; +import org.operaton.bpm.engine.impl.persistence.entity.JobEntity; import org.operaton.bpm.engine.impl.util.ClockUtil; import org.operaton.bpm.engine.repository.ProcessDefinition; import org.operaton.bpm.engine.runtime.Incident; import org.operaton.bpm.engine.runtime.Job; import org.operaton.bpm.engine.runtime.ProcessInstance; +import org.operaton.bpm.engine.runtime.ProcessInstanceQuery; import org.operaton.bpm.engine.task.Task; import org.operaton.bpm.engine.test.Deployment; import org.operaton.bpm.engine.test.ProcessEngineRule; import org.operaton.bpm.engine.test.RequiredHistoryLevel; +import org.operaton.bpm.engine.test.api.mgmt.FailingDelegate; import org.operaton.bpm.engine.test.api.runtime.migration.models.CallActivityModels; +import org.operaton.bpm.engine.test.api.runtime.migration.models.CompensationModels; import org.operaton.bpm.engine.test.api.runtime.migration.models.ProcessModels; +import org.operaton.bpm.engine.test.api.runtime.util.ChangeVariablesDelegate; import org.operaton.bpm.engine.test.util.ProcessEngineTestRule; import org.operaton.bpm.engine.test.util.ProvidedProcessEngineRule; import org.operaton.bpm.engine.variable.Variables; @@ -89,6 +96,23 @@ public class HistoricProcessInstanceTest { public ProcessEngineRule engineRule = new ProvidedProcessEngineRule(); public ProcessEngineTestRule testHelper = new ProcessEngineTestRule(engineRule); + public static final BpmnModelInstance FORK_JOIN_SUB_PROCESS_MODEL = ProcessModels.newModel() + .startEvent() + .subProcess("subProcess") + .embeddedSubProcess() + .startEvent() + .parallelGateway("fork") + .userTask("userTask1") + .name("completeMe") + .parallelGateway("join") + .endEvent() + .moveToNode("fork") + .userTask("userTask2") + .connectTo("join") + .subProcessDone() + .endEvent() + .done(); + @Rule public RuleChain chain = RuleChain.outerRule(engineRule).around(testHelper); @@ -1548,6 +1572,556 @@ public void testHistoricProcInstQueryWithActiveActivityIds() { assertEquals(result.get(0).getId(), processInstance.getId()); } + @Test + public void testQueryByNullActivityId() { + try { + historyService.createHistoricProcessInstanceQuery().activeActivityIdIn((String[]) null).list(); + fail("exception expected"); + } + catch (BadUserRequestException e) { + assertThat(e.getMessage()).contains("activity ids is null"); + } + } + + @Test + public void testQueryByNullActivityIds() { + try { + historyService.createHistoricProcessInstanceQuery() + .activityIdIn((String[]) null); + fail("exception expected"); + } + catch (BadUserRequestException e) { + assertThat(e.getMessage()).contains("activity ids is null"); + } + } + + @Test + public void testQueryByUnknownActivityId() { + HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery() + .activityIdIn("unknown"); + + assertEquals(0, query.count()); + assertEquals(0, query.list().size()); + } + + @Test + public void testQueryByLeafActivityId() { + // given + ProcessDefinition oneTaskDefinition = testHelper.deployAndGetDefinition(ProcessModels.ONE_TASK_PROCESS); + ProcessDefinition gatewaySubProcessDefinition = testHelper.deployAndGetDefinition(FORK_JOIN_SUB_PROCESS_MODEL); + + // when + ProcessInstance oneTaskInstance1 = runtimeService.startProcessInstanceById(oneTaskDefinition.getId()); + ProcessInstance oneTaskInstance2 = runtimeService.startProcessInstanceById(oneTaskDefinition.getId()); + ProcessInstance gatewaySubProcessInstance1 = runtimeService.startProcessInstanceById(gatewaySubProcessDefinition.getId()); + ProcessInstance gatewaySubProcessInstance2 = runtimeService.startProcessInstanceById(gatewaySubProcessDefinition.getId()); + + Task task = engineRule.getTaskService().createTaskQuery() + .processInstanceId(gatewaySubProcessInstance2.getId()) + .taskName("completeMe") + .singleResult(); + engineRule.getTaskService().complete(task.getId()); + + // then + HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery().activityIdIn("userTask"); + assertReturnedProcessInstances(query, oneTaskInstance1, oneTaskInstance2); + + query = historyService.createHistoricProcessInstanceQuery().activityIdIn("userTask1", "userTask2"); + assertReturnedProcessInstances(query, gatewaySubProcessInstance1, gatewaySubProcessInstance2); + + query = historyService.createHistoricProcessInstanceQuery().activityIdIn("userTask", "userTask1"); + assertReturnedProcessInstances(query, oneTaskInstance1, oneTaskInstance2, gatewaySubProcessInstance1); + + query = historyService.createHistoricProcessInstanceQuery().activityIdIn("userTask", "userTask1", "userTask2"); + assertReturnedProcessInstances(query, oneTaskInstance1, oneTaskInstance2, gatewaySubProcessInstance1, gatewaySubProcessInstance2); + + query = historyService.createHistoricProcessInstanceQuery().activityIdIn("join"); + assertReturnedProcessInstances(query, gatewaySubProcessInstance2); + } + + @Test + public void testQueryByNonLeafActivityId() { + // given + ProcessDefinition processDefinition = testHelper.deployAndGetDefinition(FORK_JOIN_SUB_PROCESS_MODEL); + + // when + runtimeService.startProcessInstanceById(processDefinition.getId()); + + // then + ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery().activityIdIn("subProcess", "fork"); + + assertEquals(0, query.count()); + assertEquals(0, query.list().size()); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + public void testQueryByAsyncBeforeActivityId() { + // For a historic instance when AsyncBefore is used the historic activity is only created when the execution is scheduled + // For process instances that have a token just before a AsyncBefore activity + // In the runtimeInstanceQuery activityIdIn filter returns instances that are not scheduled yet + // In historicInstanceQuery activityIdIn filter does not return instances that are not scheduled yet + + // given + ProcessDefinition testProcess = testHelper.deployAndGetDefinition(ProcessModels.newModel() + .startEvent("start").operatonAsyncBefore() + .subProcess("subProcess").operatonAsyncBefore() + .embeddedSubProcess() + .startEvent() + .serviceTask("task").operatonAsyncBefore().operatonExpression("${true}") + .endEvent() + .subProcessDone() + .endEvent("end").operatonAsyncBefore() + .done() + ); + + // when + ProcessInstance instanceBeforeStart = runtimeService.startProcessInstanceById(testProcess.getId()); + ProcessInstance instanceBeforeSubProcess = runtimeService.startProcessInstanceById(testProcess.getId()); + executeJobForProcessInstance(instanceBeforeSubProcess); + ProcessInstance instanceBeforeTask = runtimeService.startProcessInstanceById(testProcess.getId()); + executeJobForProcessInstance(instanceBeforeTask); + executeJobForProcessInstance(instanceBeforeTask); + ProcessInstance instanceBeforeEnd = runtimeService.startProcessInstanceById(testProcess.getId()); + executeJobForProcessInstance(instanceBeforeEnd); + executeJobForProcessInstance(instanceBeforeEnd); + executeJobForProcessInstance(instanceBeforeEnd); + + // then + HistoricProcessInstanceQuery historicQuery = historyService.createHistoricProcessInstanceQuery().activityIdIn("start"); + assertNull(historicQuery.singleResult()); + ProcessInstanceQuery runtimeQuery = runtimeService.createProcessInstanceQuery().activityIdIn("start"); + assertEquals(instanceBeforeStart.getId(), runtimeQuery.singleResult().getProcessInstanceId()); + + historicQuery = historyService.createHistoricProcessInstanceQuery().activityIdIn("subProcess"); + assertReturnedProcessInstances(historicQuery, instanceBeforeTask); + runtimeQuery = runtimeService.createProcessInstanceQuery().activityIdIn("subProcess"); + assertEquals(instanceBeforeSubProcess.getId(), runtimeQuery.singleResult().getProcessInstanceId()); + + historicQuery = historyService.createHistoricProcessInstanceQuery().activityIdIn("task"); + assertNull(historicQuery.singleResult()); + runtimeQuery = runtimeService.createProcessInstanceQuery().activityIdIn("task"); + assertEquals(instanceBeforeTask.getId(), runtimeQuery.singleResult().getProcessInstanceId()); + + historicQuery = historyService.createHistoricProcessInstanceQuery().activityIdIn("end"); + assertNull(historicQuery.singleResult()); + runtimeQuery = runtimeService.createProcessInstanceQuery().activityIdIn("end"); + assertEquals(instanceBeforeEnd.getId(), runtimeQuery.singleResult().getProcessInstanceId()); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + public void testQueryByAsyncAfterActivityId() { + // For a historic activity the end time is set after it is executed => the activity is not considered active anymore, + // this is not changed if AsyncAfter is used + // if the task is a subprocess end time will only be set after the subprocess is terminated + // For the runtime query the execution is still visible if AsyncAfter is used (I assume we delete the execution when scheduling next activity) + + // given + ProcessDefinition testProcess = testHelper.deployAndGetDefinition(ProcessModels.newModel() + .startEvent("start").operatonAsyncAfter() + .subProcess("subProcess").operatonAsyncAfter() + .embeddedSubProcess() + .startEvent() + .serviceTask("task").operatonAsyncAfter().operatonExpression("${true}") + .endEvent() + .subProcessDone() + .endEvent("end").operatonAsyncAfter() + .done() + ); + + // when + ProcessInstance instanceAfterStart = runtimeService.startProcessInstanceById(testProcess.getId()); + ProcessInstance instanceAfterTask = runtimeService.startProcessInstanceById(testProcess.getId()); + executeJobForProcessInstance(instanceAfterTask); + ProcessInstance instanceAfterSubProcess = runtimeService.startProcessInstanceById(testProcess.getId()); + executeJobForProcessInstance(instanceAfterSubProcess); + executeJobForProcessInstance(instanceAfterSubProcess); + ProcessInstance instanceAfterEnd = runtimeService.startProcessInstanceById(testProcess.getId()); + executeJobForProcessInstance(instanceAfterEnd); + executeJobForProcessInstance(instanceAfterEnd); + executeJobForProcessInstance(instanceAfterEnd); + + HistoricProcessInstanceQuery historicQuery = historyService.createHistoricProcessInstanceQuery().activityIdIn("start"); + assertNull(historicQuery.singleResult()); + ProcessInstanceQuery runtimeQuery = runtimeService.createProcessInstanceQuery().activityIdIn("start"); + assertEquals(instanceAfterStart.getId(), runtimeQuery.singleResult().getProcessInstanceId()); + + historicQuery = historyService.createHistoricProcessInstanceQuery().activityIdIn("task"); + assertNull(historicQuery.singleResult()); + runtimeQuery = runtimeService.createProcessInstanceQuery().activityIdIn("task"); + assertEquals(instanceAfterTask.getId(), runtimeQuery.singleResult().getProcessInstanceId()); + + historicQuery = historyService.createHistoricProcessInstanceQuery().activityIdIn("subProcess"); + assertReturnedProcessInstances(historicQuery, instanceAfterTask); + runtimeQuery = runtimeService.createProcessInstanceQuery().activityIdIn("subProcess"); + assertEquals(instanceAfterSubProcess.getId(), runtimeQuery.singleResult().getProcessInstanceId()); + + historicQuery = historyService.createHistoricProcessInstanceQuery().activityIdIn("end"); + assertNull(historicQuery.singleResult()); + runtimeQuery = runtimeService.createProcessInstanceQuery().activityIdIn("end"); + assertEquals(instanceAfterEnd.getId(), runtimeQuery.singleResult().getProcessInstanceId()); + } + + @Test + public void testQueryByActivityIdBeforeCompensation() { + // given + ProcessDefinition testProcess = testHelper.deployAndGetDefinition(CompensationModels.COMPENSATION_ONE_TASK_SUBPROCESS_MODEL); + + // when + runtimeService.startProcessInstanceById(testProcess.getId()); + testHelper.completeTask("userTask1"); + + // then + ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery().activityIdIn("subProcess"); + + assertEquals(0, query.count()); + assertEquals(0, query.list().size()); } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + public void testQueryByActivityIdDuringCompensation() { + // After completing user task we are expecting "subProcess", "compensationEvent", "compensationHandler" to have an activity + // Based on historic data only "compensationEvent", "compensationHandler" have active events + + // given + ProcessDefinition testProcess = testHelper.deployAndGetDefinition(CompensationModels.COMPENSATION_ONE_TASK_SUBPROCESS_MODEL); + + // when + ProcessInstance processInstance = runtimeService.startProcessInstanceById(testProcess.getId()); + testHelper.completeTask("userTask1"); + testHelper.completeTask("userTask2"); + + // then + HistoricProcessInstanceQuery historicQuery = historyService.createHistoricProcessInstanceQuery().activityIdIn("subProcess"); + assertNull(historicQuery.singleResult()); + ProcessInstanceQuery runtimeQuery = runtimeService.createProcessInstanceQuery().activityIdIn("subProcess"); + assertEquals(processInstance.getId(), runtimeQuery.singleResult().getProcessInstanceId()); + + historicQuery = historyService.createHistoricProcessInstanceQuery().activityIdIn("compensationEvent"); + assertReturnedProcessInstances(historicQuery, processInstance); + runtimeQuery = runtimeService.createProcessInstanceQuery().activityIdIn("compensationEvent"); + assertEquals(processInstance.getId(), runtimeQuery.singleResult().getProcessInstanceId()); + + historicQuery = historyService.createHistoricProcessInstanceQuery().activityIdIn("compensationHandler"); + assertReturnedProcessInstances(historicQuery, processInstance); + runtimeQuery = runtimeService.createProcessInstanceQuery().activityIdIn("compensationEvent"); + assertEquals(processInstance.getId(), runtimeQuery.singleResult().getProcessInstanceId()); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + public void testHistoricProcInstQueryWithActivityIdsWithOneId() { + // given + String USER_TASK_1 = "userTask1"; + deployment(ProcessModels.TWO_TASKS_PROCESS); + runtimeService.startProcessInstanceByKey("Process"); + runtimeService.startProcessInstanceByKey("Process"); + + List tasks = taskService.createTaskQuery().list(); + assertEquals(2, tasks.size()); + taskService.complete(tasks.get(0).getId()); + + // when + List result = historyService + .createHistoricProcessInstanceQuery() + .activityIdIn(USER_TASK_1) + .list(); + + // then + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals(result.get(0).getId(), tasks.get(1).getProcessInstanceId()); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + public void testHistoricProcInstQueryWithActivityIdsWithMultipleIds() { + // given + String USER_TASK_1 = "userTask1"; + String USER_TASK_2 = "userTask2"; + deployment(ProcessModels.TWO_TASKS_PROCESS); + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("Process"); + ProcessInstance processInstance2 = runtimeService.startProcessInstanceByKey("Process"); + + List tasks = taskService.createTaskQuery().list(); + assertEquals(2, tasks.size()); + taskService.complete(tasks.get(0).getId()); + + // when + List result = historyService + .createHistoricProcessInstanceQuery() + .activityIdIn(USER_TASK_1, USER_TASK_2) + .list(); + + // then + assertNotNull(result); + assertEquals(2, result.size()); + assertThat(result.stream().map(HistoricProcessInstance::getId).collect(Collectors.toList())) + .containsExactlyInAnyOrder(processInstance.getId(),processInstance2.getId()); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + public void testHistoricProcInstQueryWithActivityIdsWhenDeletedCompetedInstancesExist() { + // given + String USER_TASK_1 = "userTask1"; + String USER_TASK_2 = "userTask2"; + deployment(ProcessModels.TWO_TASKS_PROCESS); + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("Process"); + ProcessInstance processInstance2 = runtimeService.startProcessInstanceByKey("Process"); + + List tasks = taskService.createTaskQuery().list(); + assertEquals(2, tasks.size()); + taskService.complete(tasks.get(0).getId()); + + ProcessInstance completedProcessInstance = runtimeService.startProcessInstanceByKey("Process"); + Task task = taskService.createTaskQuery().processInstanceId(completedProcessInstance.getId()).singleResult(); + taskService.complete(task.getId()); + task = taskService.createTaskQuery().processInstanceId(completedProcessInstance.getId()).singleResult(); + taskService.complete(task.getId()); + + + ProcessInstance deletedProcessInstance = runtimeService.startProcessInstanceByKey("Process"); + runtimeService.deleteProcessInstance(deletedProcessInstance.getId(), "Testing"); + + // when + List result = historyService + .createHistoricProcessInstanceQuery() + .activityIdIn(USER_TASK_1, USER_TASK_2) + .list(); + + // then + assertNotNull(result); + assertEquals(2, result.size()); + assertThat(result.stream().map(HistoricProcessInstance::getId).collect(Collectors.toList())) + .containsExactlyInAnyOrder(processInstance.getId(), processInstance2.getId()); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + @Deployment(resources = {"org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.testHistoricProcessInstanceQueryActivityIdInWithIncident.bpmn"}) + public void testHistoricProcInstQueryWithActivityIdsWithFailingActivity() { + // given + runtimeService.startProcessInstanceByKey("failingProcess"); + testHelper.executeAvailableJobs(); + + runtimeService.startProcessInstanceByKey("failingProcess"); + + // assume + assertEquals(2, historyService.createHistoricProcessInstanceQuery().count()); + assertEquals(2, historyService.createHistoricProcessInstanceQuery().list().size()); + + assertEquals(1, historyService.createHistoricProcessInstanceQuery().withIncidents().count()); + assertEquals(1, historyService.createHistoricProcessInstanceQuery().withIncidents().list().size()); + HistoricProcessInstance failingInstance = historyService.createHistoricProcessInstanceQuery().withIncidents().singleResult(); + + // when + List result = historyService + .createHistoricProcessInstanceQuery() + .activityIdIn("serviceTask") + .list(); + + // then + assertNotNull(result); + assertEquals(1, result.size()); + assertEquals(result.get(0).getId(), failingInstance.getId()); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + @Deployment(resources={"org/operaton/bpm/engine/test/api/runtime/failingSubProcessCreateOneIncident.bpmn20.xml"}) + public void shouldQueryByActivityIdInWithActivityIdOfFailingSubprocess() { + // given + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("failingSubProcess"); + + testHelper.executeAvailableJobs(); + + // when + HistoricProcessInstance historicPI = + historyService.createHistoricProcessInstanceQuery().activityIdIn("subProcess").singleResult(); + + // then + assertThat(historicPI).isNotNull(); + assertThat(historicPI.getId()).isEqualTo(processInstance.getId()); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + @Deployment(resources={"org/operaton/bpm/engine/test/api/runtime/failingSubProcessCreateOneIncident.bpmn20.xml"}) + public void shouldQueryByActivityIdInWithActivityIdOfFailingSubServiceTask() { + // given + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("failingSubProcess"); + + testHelper.executeAvailableJobs(); + + // when + HistoricProcessInstance historicPI = + historyService.createHistoricProcessInstanceQuery().activityIdIn("serviceTask").singleResult(); + + // then + assertThat(historicPI).isNotNull(); + assertThat(historicPI.getId()).isEqualTo(processInstance.getId()); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + @Deployment(resources={"org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.subprocess.bpmn20.xml"}) + public void shouldQueryByActivityIdInWithActivityIdOfSubprocess() { + // given + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("subprocess"); + + TaskService taskService = engineRule.getTaskService(); + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); + assertNotNull(task); + taskService.complete(task.getId()); + // when + HistoricProcessInstance historicPI = + historyService.createHistoricProcessInstanceQuery().activityIdIn("subProcess").singleResult(); + + // then + assertThat(historicPI).isNotNull(); + assertThat(historicPI.getId()).isEqualTo(processInstance.getId()); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + @Deployment(resources={"org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.subprocess.bpmn20.xml"}) + public void shouldQueryByActivityIdInWithActivityIdOfSubServiceTask() { + // given + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("subprocess"); + + TaskService taskService = engineRule.getTaskService(); + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); + assertNotNull(task); + taskService.complete(task.getId()); + // when + HistoricProcessInstance historicPI = + historyService.createHistoricProcessInstanceQuery().activityIdIn("innerTask").singleResult(); + + // then + assertThat(historicPI).isNotNull(); + assertThat(historicPI.getId()).isEqualTo(processInstance.getId()); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + @Deployment(resources={"org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.failingSubprocessWithAsyncBeforeTask.bpmn20.xml"}) + public void shouldQueryByActivityIdInWithMultipleScopeAndIncident() { + // given + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("failingSubProcess"); + ProcessInstance processInstance2 = runtimeService.startProcessInstanceByKey("failingSubProcess"); + + TaskService taskService = engineRule.getTaskService(); + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); + taskService.complete(task.getId()); + + testHelper.executeAvailableJobs(); + + // when + List queryByInnerServiceActivityId = + historyService.createHistoricProcessInstanceQuery().activityIdIn("innerServiceTask").list(); + List queryBySubProcessActivityId = + historyService.createHistoricProcessInstanceQuery().activityIdIn("subProcess").list(); + List queryByOuterProcessActivityId = + historyService.createHistoricProcessInstanceQuery().activityIdIn("outerTask").list(); + List queryByOuterAndInnedActivityId = + historyService.createHistoricProcessInstanceQuery().activityIdIn("innerServiceTask", "outerTask").list(); + + // then + assertThat(queryByInnerServiceActivityId.size()).isEqualTo(1); + assertThat(queryByInnerServiceActivityId.get(0).getId()).isEqualTo(processInstance.getId()); + + assertThat(queryBySubProcessActivityId.size()).isEqualTo(1); + assertThat(queryBySubProcessActivityId.get(0).getId()).isEqualTo(processInstance.getId()); + + assertThat(queryByOuterProcessActivityId.size()).isEqualTo(1); + assertThat(queryByOuterProcessActivityId.get(0).getId()).isEqualTo(processInstance2.getId()); + + assertThat(queryByOuterAndInnedActivityId.size()).isEqualTo(2); + assertThat(queryByOuterAndInnedActivityId.stream() + .map(HistoricProcessInstance::getId) + .collect(Collectors.toList())) + .containsExactlyInAnyOrderElementsOf(Arrays.asList(processInstance.getId(), processInstance2.getId())); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + @Deployment(resources={"org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.subprocessWithAsyncBeforeTask.bpmn20.xml"}) + public void shouldQueryByActivityIdInWithMultipleScope() { + // given + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("failingSubProcess"); + ProcessInstance processInstance2 = runtimeService.startProcessInstanceByKey("failingSubProcess"); + + TaskService taskService = engineRule.getTaskService(); + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult(); + taskService.complete(task.getId()); + + // when + List queryByInnerServiceActivityId = + historyService.createHistoricProcessInstanceQuery().activityIdIn("innerTask").list(); + List queryBySubProcessActivityId = + historyService.createHistoricProcessInstanceQuery().activityIdIn("subProcess").list(); + List queryByOuterProcessActivityId = + historyService.createHistoricProcessInstanceQuery().activityIdIn("outerTask").list(); + List queryByOuterAndInnedActivityId = + historyService.createHistoricProcessInstanceQuery().activityIdIn("innerTask", "outerTask").list(); + + // then + assertThat(queryByInnerServiceActivityId.size()).isEqualTo(1); + assertThat(queryByInnerServiceActivityId.get(0).getId()).isEqualTo(processInstance.getId()); + + assertThat(queryBySubProcessActivityId.size()).isEqualTo(1); + assertThat(queryBySubProcessActivityId.get(0).getId()).isEqualTo(processInstance.getId()); + + assertThat(queryByOuterProcessActivityId.size()).isEqualTo(1); + assertThat(queryByOuterProcessActivityId.get(0).getId()).isEqualTo(processInstance2.getId()); + + assertThat(queryByOuterAndInnedActivityId.size()).isEqualTo(2); + assertThat(queryByOuterAndInnedActivityId.stream() + .map(HistoricProcessInstance::getId) + .collect(Collectors.toList())) + .containsExactlyInAnyOrderElementsOf(Arrays.asList(processInstance.getId(), processInstance2.getId())); + } + + @Test + @RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL) + public void shouldQueryByActivityIdWhereIncidentOccurred() { + // given + testHelper.deploy(Bpmn.createExecutableProcess("process") + .startEvent() + .serviceTask("theTask") + .operatonAsyncBefore() + .operatonClass(ChangeVariablesDelegate.class) + .serviceTask("theTask2").operatonClass(ChangeVariablesDelegate.class) + .serviceTask("theTask3").operatonClass(FailingDelegate.class) + .endEvent() + .done()); + + runtimeService.startProcessInstanceByKey("process", Variables.createVariables().putValue("fail", true)); + JobEntity job = (JobEntity) managementService.createJobQuery().singleResult(); + + // when: incident is raised + for(int i = 0; i<3; i++) { + try { + managementService.executeJob(job.getId()); + fail("Exception expected"); + } catch (Exception e) { + // exception expected + } + } + + // then + HistoricProcessInstance theTask = historyService.createHistoricProcessInstanceQuery() + .activityIdIn("theTask") + .singleResult(); + assertThat(theTask).isNotNull(); + HistoricProcessInstance theTask3 = historyService.createHistoricProcessInstanceQuery() + .activityIdIn("theTask3") + .singleResult(); + assertThat(theTask3).isNull(); + } + @Test public void testHistoricProcInstQueryWithActiveActivityIdsNull() { try { @@ -2105,4 +2679,39 @@ protected void executeJob(Job job) { } } + + protected void assertReturnedProcessInstances(HistoricProcessInstanceQuery query, ProcessInstance... processInstances) { + int expectedSize = processInstances.length; + assertEquals(expectedSize, query.count()); + assertEquals(expectedSize, query.list().size()); + + verifyResultContainsExactly(query.list(), collectProcessInstanceIds(Arrays.asList(processInstances))); + } + + protected void verifyResultContainsExactly(List instances, Set processInstanceIds) { + Set retrievedInstanceIds = collectHistoricProcessInstanceIds(instances); + assertEquals(processInstanceIds, retrievedInstanceIds); + } + + protected Set collectProcessInstanceIds(List instances) { + Set retrievedInstanceIds = new HashSet<>(); + for (ProcessInstance instance : instances) { + retrievedInstanceIds.add(instance.getId()); + } + return retrievedInstanceIds; + } + + protected Set collectHistoricProcessInstanceIds(List instances) { + Set retrievedInstanceIds = new HashSet<>(); + for (HistoricProcessInstance instance : instances) { + retrievedInstanceIds.add(instance.getId()); + } + return retrievedInstanceIds; + } + + protected void executeJobForProcessInstance(ProcessInstance processInstance) { + Job job = managementService.createJobQuery().processInstanceId(processInstance.getId()).singleResult(); + managementService.executeJob(job.getId()); + } + } diff --git a/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.failingSubprocessWithAsyncBeforeTask.bpmn20.xml b/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.failingSubprocessWithAsyncBeforeTask.bpmn20.xml new file mode 100644 index 00000000000..d2ddbd75867 --- /dev/null +++ b/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.failingSubprocessWithAsyncBeforeTask.bpmn20.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.subprocessWithAsyncBeforeTask.bpmn20.xml b/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.subprocessWithAsyncBeforeTask.bpmn20.xml new file mode 100644 index 00000000000..ad48668b6f5 --- /dev/null +++ b/engine/src/test/resources/org/operaton/bpm/engine/test/api/runtime/ProcessInstanceModificationTest.subprocessWithAsyncBeforeTask.bpmn20.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/src/test/resources/org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.testHistoricProcessInstanceQueryActivityIdInWithIncident.bpmn b/engine/src/test/resources/org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.testHistoricProcessInstanceQueryActivityIdInWithIncident.bpmn new file mode 100644 index 00000000000..4114fb0b108 --- /dev/null +++ b/engine/src/test/resources/org/operaton/bpm/engine/test/history/HistoricProcessInstanceTest.testHistoricProcessInstanceQueryActivityIdInWithIncident.bpmn @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + \ No newline at end of file From 07e28c4a9d7ac5ffd2e2fa90bf94198f1c5d5cb6 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Thu, 7 Nov 2024 10:42:15 +0100 Subject: [PATCH 35/37] fix(client) don't expose executionId to public API (#4611) related to: camunda/camunda-bpm-platform#4523 Co-authored-by: Tassilo Weidner <3015690+tasso94@users.noreply.github.com> Backported commit 30ece1819d from the camunda-bpm-platform repository. Original author: Gergely Juhasz " --- .../client/variable/FileSerializationIT.java | 85 ++++++++++++++++++- .../client/task/impl/ExternalTaskImpl.java | 9 -- .../bpm/client/variable/impl/TypedValues.java | 4 +- .../client/variable/impl/VariableValue.java | 10 +-- .../impl/value/DeferredFileValueImpl.java | 11 +-- .../variable/value/DeferredFileValue.java | 16 ---- .../bpm/client/task/ExternalTaskImplTest.java | 12 +-- 7 files changed, 99 insertions(+), 48 deletions(-) diff --git a/clients/java/client/src/it/java/org/operaton/bpm/client/variable/FileSerializationIT.java b/clients/java/client/src/it/java/org/operaton/bpm/client/variable/FileSerializationIT.java index fa1f4444c33..5d00f4b8529 100644 --- a/clients/java/client/src/it/java/org/operaton/bpm/client/variable/FileSerializationIT.java +++ b/clients/java/client/src/it/java/org/operaton/bpm/client/variable/FileSerializationIT.java @@ -32,10 +32,12 @@ import org.operaton.bpm.client.util.RecordingExternalTaskHandler; import org.operaton.bpm.client.util.RecordingInvocationHandler; import org.operaton.bpm.client.util.RecordingInvocationHandler.RecordedInvocation; +import org.operaton.bpm.client.variable.impl.value.DeferredFileValueImpl; import org.operaton.bpm.client.variable.value.DeferredFileValue; import org.operaton.bpm.engine.variable.Variables; import org.operaton.bpm.engine.variable.value.FileValue; import org.operaton.bpm.engine.variable.value.TypedValue; +import org.operaton.bpm.model.bpmn.Bpmn; import org.operaton.bpm.model.bpmn.BpmnModelInstance; import org.operaton.commons.utils.IoUtil; @@ -64,6 +66,8 @@ public class FileSerializationIT { protected static final String VARIABLE_NAME_FILE = "fileVariable"; protected static final String VARIABLE_VALUE_FILE_NAME = "aFileName.txt"; protected static final byte[] VARIABLE_VALUE_FILE_VALUE = "ABC".getBytes(); + protected static final String LOCAL_VARIABLE_NAME_FILE = "localFileName.txt"; + protected static final String VARIABLE_VALUE_FILE_ENCODING = "UTF-8"; protected static final String VARIABLE_VALUE_FILE_MIME_TYPE = "text/plain"; @@ -114,6 +118,41 @@ public void shouldGet() { .isEqualTo(new String(VARIABLE_VALUE_FILE_VALUE)); } + @Test + public void shouldGetLocalAndGlobalVariables() { + // given + ProcessDefinitionDto processDefinitionDto = engineRule.deploy( + Bpmn.createExecutableProcess("process") + .startEvent("startEvent") + .serviceTask("serviceTaskFoo") + .operatonExternalTask(EXTERNAL_TASK_TOPIC_FOO) + // create the local file variable with the same content but different name + .operatonInputParameter(LOCAL_VARIABLE_NAME_FILE, "${execution.getVariableTyped('fileVariable')}") + .serviceTask("serviceTaskBar") + .operatonExternalTask(EXTERNAL_TASK_TOPIC_BAR) + .endEvent("endEvent") + .done() + ).get(0); + + engineRule.startProcessInstance(processDefinitionDto.getId(), VARIABLE_NAME_FILE, VARIABLE_VALUE_FILE); + + // when + client.subscribe(EXTERNAL_TASK_TOPIC_FOO) + .handler(handler) + .open(); + + clientRule.waitForFetchAndLockUntil(() -> !handler.getHandledTasks().isEmpty()); + + ExternalTask task = handler.getHandledTasks().get(0); + + // then + assertThat(task.getAllVariables().size()).isEqualTo(2); + assertThat(IoUtil.inputStreamAsString(task.getVariable(VARIABLE_NAME_FILE))) + .isEqualTo(new String(VARIABLE_VALUE_FILE_VALUE)); + assertThat(IoUtil.inputStreamAsString(task.getVariable(LOCAL_VARIABLE_NAME_FILE))) + .isEqualTo(new String(VARIABLE_VALUE_FILE_VALUE)); + } + @Test public void shouldGetAll() { // given @@ -142,7 +181,9 @@ public void shouldGetAll() { @Test public void shouldGetTyped_Deferred() { // given - engineRule.startProcessInstance(processDefinition.getId(), VARIABLE_NAME_FILE, VARIABLE_VALUE_FILE); + ProcessInstanceDto processInstanceDto = engineRule.startProcessInstance(processDefinition.getId(), + VARIABLE_NAME_FILE, + VARIABLE_VALUE_FILE); client.subscribe(EXTERNAL_TASK_TOPIC_FOO) .handler(handler) @@ -160,6 +201,48 @@ public void shouldGetTyped_Deferred() { assertThat(typedValue.isLoaded()).isFalse(); assertThat(typedValue.getEncoding()).isNull(); assertThat(typedValue.getMimeType()).isNull(); + + DeferredFileValueImpl typedValueImpl = (DeferredFileValueImpl) typedValue; + assertThat(typedValueImpl.getExecutionId()).isEqualTo(task.getExecutionId()); + } + + @Test + public void shouldGetVariableTypedForLocalVariable() { + // given + ProcessDefinitionDto processDefinitionDto = engineRule.deploy( + Bpmn.createExecutableProcess("process") + .startEvent("startEvent") + .serviceTask("serviceTaskFoo") + .operatonExternalTask(EXTERNAL_TASK_TOPIC_FOO) + // create the local file variable with the same content but different name + .operatonInputParameter(LOCAL_VARIABLE_NAME_FILE, "${execution.getVariableTyped('fileVariable')}") + .serviceTask("serviceTaskBar") + .operatonExternalTask(EXTERNAL_TASK_TOPIC_BAR) + .endEvent("endEvent") + .done() + ).get(0); + + engineRule.startProcessInstance(processDefinitionDto.getId(), VARIABLE_NAME_FILE, VARIABLE_VALUE_FILE); + + // when + client.subscribe(EXTERNAL_TASK_TOPIC_FOO) + .handler(handler) + .open(); + + clientRule.waitForFetchAndLockUntil(() -> !handler.getHandledTasks().isEmpty()); + + ExternalTask task = handler.getHandledTasks().get(0); + + // then + DeferredFileValue typedValue = task.getVariableTyped(LOCAL_VARIABLE_NAME_FILE); + assertThat(typedValue.getFilename()).isEqualTo(VARIABLE_VALUE_FILE_NAME); + assertThat(typedValue.getType()).isEqualTo(FILE); + assertThat(typedValue.isLoaded()).isFalse(); + assertThat(typedValue.getEncoding()).isNull(); + assertThat(typedValue.getMimeType()).isNull(); + + InputStream value = typedValue.getValue(); + assertThat(IoUtil.inputStreamAsString(value)).isEqualTo(new String(VARIABLE_VALUE_FILE_VALUE)); } @Test diff --git a/clients/java/client/src/main/java/org/operaton/bpm/client/task/impl/ExternalTaskImpl.java b/clients/java/client/src/main/java/org/operaton/bpm/client/task/impl/ExternalTaskImpl.java index 171debec1fa..efa9ea7d64f 100644 --- a/clients/java/client/src/main/java/org/operaton/bpm/client/task/impl/ExternalTaskImpl.java +++ b/clients/java/client/src/main/java/org/operaton/bpm/client/task/impl/ExternalTaskImpl.java @@ -25,7 +25,6 @@ import org.operaton.bpm.client.task.ExternalTask; import org.operaton.bpm.client.variable.impl.TypedValueField; import org.operaton.bpm.client.variable.impl.VariableValue; -import org.operaton.bpm.client.variable.value.DeferredFileValue; import org.operaton.bpm.engine.variable.VariableMap; import org.operaton.bpm.engine.variable.Variables; import org.operaton.bpm.engine.variable.value.TypedValue; @@ -258,10 +257,6 @@ public T getVariable(String variableName) { VariableValue variableValue = receivedVariableMap.get(variableName); if (variableValue != null) { - if(variableValue.getTypedValue() instanceof DeferredFileValue) { - DeferredFileValue deferredFileValue = (DeferredFileValue) variableValue.getTypedValue(); - deferredFileValue.setExecutionId(this.executionId); - } value = (T) variableValue.getValue(); } @@ -300,10 +295,6 @@ public T getVariableTyped(String variableName, boolean de VariableValue variableValue = receivedVariableMap.get(variableName); if (variableValue != null) { typedValue = variableValue.getTypedValue(deserializeObjectValues); - if(typedValue instanceof DeferredFileValue) { - DeferredFileValue deferredFileValue = (DeferredFileValue) typedValue; - deferredFileValue.setExecutionId(this.executionId); - } } return (T) typedValue; diff --git a/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/TypedValues.java b/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/TypedValues.java index 4310c29cb1a..fa7de42fe16 100644 --- a/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/TypedValues.java +++ b/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/TypedValues.java @@ -69,7 +69,7 @@ public Map serializeVariables(Map varia @SuppressWarnings("rawtypes") public Map wrapVariables(ExternalTask externalTask, Map variables) { - String processInstanceId = externalTask.getProcessInstanceId(); + String executionId = externalTask.getExecutionId(); Map result = new HashMap<>(); @@ -80,7 +80,7 @@ public Map wrapVariables(ExternalTask externalTask, Map { - protected String processInstanceId; + protected String executionId; protected String variableName; protected TypedValueField typedValueField; protected ValueMappers mappers; @@ -30,8 +30,8 @@ public class VariableValue { protected ValueMapper serializer; protected T cachedValue; - public VariableValue(String processInstanceId, String variableName, TypedValueField typedValueField, ValueMappers mappers) { - this.processInstanceId = processInstanceId; + public VariableValue(String executionId, String variableName, TypedValueField typedValueField, ValueMappers mappers) { + this.executionId = executionId; this.variableName = variableName; this.typedValueField = typedValueField; this.mappers = mappers; @@ -63,7 +63,7 @@ public T getTypedValue(boolean deserializeValue) { if (cachedValue instanceof DeferredFileValueImpl) { DeferredFileValueImpl fileValue = (DeferredFileValueImpl) cachedValue; - fileValue.setProcessInstanceId(processInstanceId); + fileValue.setExecutionId(executionId); fileValue.setVariableName(variableName); } } @@ -83,7 +83,7 @@ public ValueMapper getSerializer() { public String toString() { return "VariableValue [" + "cachedValue=" + cachedValue + ", " - + "processInstanceId=" + processInstanceId + ", " + + "executionId=" + executionId + ", " + "variableName=" + variableName + ", " + "typedValueField=" + typedValueField + "]"; } diff --git a/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/value/DeferredFileValueImpl.java b/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/value/DeferredFileValueImpl.java index 80510842f79..a9c7ac4f6f9 100644 --- a/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/value/DeferredFileValueImpl.java +++ b/clients/java/client/src/main/java/org/operaton/bpm/client/variable/impl/value/DeferredFileValueImpl.java @@ -37,9 +37,8 @@ public class DeferredFileValueImpl extends FileValueImpl implements DeferredFile protected boolean isLoaded = false; protected String variableName; - protected String processInstanceId; + protected String executionId; protected EngineClient engineClient; - protected String executionId = null; public DeferredFileValueImpl(String filename, EngineClient engineClient) { super(PrimitiveValueType.FILE, filename); @@ -72,20 +71,14 @@ public InputStream getValue() { return super.getValue(); } - public void setProcessInstanceId(String processInstanceId) { - this.processInstanceId = processInstanceId; - } - public void setVariableName(String variableName) { this.variableName = variableName; } - @Override public void setExecutionId(String executionId){ this.executionId = executionId; }; - @Override public String getExecutionId() { return executionId; } @@ -93,7 +86,7 @@ public String getExecutionId() { @Override public String toString() { return "DeferredFileValueImpl [mimeType=" + mimeType + ", filename=" + filename + ", type=" + type + ", " - + "isTransient=" + isTransient + ", isLoaded=" + isLoaded + ", processInstanceId" + processInstanceId + ", executionId" + executionId + "]"; + + "isTransient=" + isTransient + ", isLoaded=" + isLoaded + "]"; } } diff --git a/clients/java/client/src/main/java/org/operaton/bpm/client/variable/value/DeferredFileValue.java b/clients/java/client/src/main/java/org/operaton/bpm/client/variable/value/DeferredFileValue.java index a7bfc82e9dc..fdc1a924b6e 100644 --- a/clients/java/client/src/main/java/org/operaton/bpm/client/variable/value/DeferredFileValue.java +++ b/clients/java/client/src/main/java/org/operaton/bpm/client/variable/value/DeferredFileValue.java @@ -39,20 +39,4 @@ public interface DeferredFileValue extends FileValue { */ boolean isLoaded(); - /** - * Sets the executionId, which defines the scope of the DeferredFileValue. - * This identifier ensures that the correct scope is applied when loading the file value. - * - * @param executionId defines the scope of the DeferredFileValue - */ - void setExecutionId(String executionId); - - /** - * Returns the executionId, which specifies the scope of the DeferredFileValue. - * This identifier ensures that the correct scope is applied when loading the file value. - * - * @return the executionId which defines the scope of the DeferredFileValue - */ - String getExecutionId(); - } diff --git a/clients/java/client/src/test/java/org/operaton/bpm/client/task/ExternalTaskImplTest.java b/clients/java/client/src/test/java/org/operaton/bpm/client/task/ExternalTaskImplTest.java index a9a5b3beafb..1c8025207e6 100644 --- a/clients/java/client/src/test/java/org/operaton/bpm/client/task/ExternalTaskImplTest.java +++ b/clients/java/client/src/test/java/org/operaton/bpm/client/task/ExternalTaskImplTest.java @@ -139,8 +139,8 @@ void shouldDisplayAttributesIncludingMapsInToString() { task.setWorkerId("wi"); Map receivedVariables = new LinkedHashMap<>(); - receivedVariables.put("rv1", generateVariableValue("pii", "variable1", ValueType.STRING.getName(), "value1", 42, "vi2")); - receivedVariables.put("rv2", generateVariableValue("pii", "variable2", ValueType.INTEGER.getName(), 99, 42, "vi2", 87L)); + receivedVariables.put("rv1", generateVariableValue(task.getExecutionId(), "variable1", ValueType.STRING.getName(), "value1", 42, "vi2")); + receivedVariables.put("rv2", generateVariableValue(task.getExecutionId(), "variable2", ValueType.INTEGER.getName(), 99, 42, "vi2", 87L)); task.setReceivedVariableMap(receivedVariables); Map variables = new LinkedHashMap<>(); @@ -163,9 +163,9 @@ void shouldDisplayAttributesIncludingMapsInToString() { + "processDefinitionVersionTag=versionTag, " + "processInstanceId=pii, " + "receivedVariableMap={" - + "rv1=VariableValue [cachedValue=null, processInstanceId=pii, variableName=variable1, typedValueField=" + + "rv1=VariableValue [cachedValue=null, executionId=ei, variableName=variable1, typedValueField=" + "TypedValueField [type=string, value=value1, valueInfo={vi1=42, vi2=vi2}]], " - + "rv2=VariableValue [cachedValue=null, processInstanceId=pii, variableName=variable2, typedValueField=" + + "rv2=VariableValue [cachedValue=null, executionId=ei, variableName=variable2, typedValueField=" + "TypedValueField [type=integer, value=99, valueInfo={vi1=42, vi2=vi2, vi3=87}]]" + "}, " + "retries=34, " @@ -184,10 +184,10 @@ void shouldDisplayAttributesIncludingMapsInToString() { private static final ValueMappers DEFAULT_MAPPERS = new DefaultValueMappers(Variables.SerializationDataFormats.JSON.getName()); @SuppressWarnings("rawtypes") - private static VariableValue generateVariableValue(String processInstanceId, String variableName, + private static VariableValue generateVariableValue(String executionId, String variableName, final String typeI, final Object valueI, Object... valueInfos) { TypedValueField typedValueField = generateTypedValueField(typeI, valueI, valueInfos); - return new VariableValue(processInstanceId, variableName, typedValueField, DEFAULT_MAPPERS); + return new VariableValue(executionId, variableName, typedValueField, DEFAULT_MAPPERS); } private static TypedValueField generateTypedValueField(final String typeI, final Object valueI, Object... valueInfos) { From ac1eefee9b70253c034c296dfc886e1486681720 Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Thu, 7 Nov 2024 10:47:04 +0100 Subject: [PATCH 36/37] chore(engine): add batchId for job and jobLog (#4625) Related to https://github.com/camunda/camunda-bpm-platform/issues/4206 Backported commit 0188c9eb20 from the camunda-bpm-platform repository. Original author: Miklas Boskamp <20189772+mboskamp@users.noreply.github.com>" --- .../rest/dto/history/HistoricJobLogDto.ftl | 12 +- .../bpm/engine/rest/dto/runtime/JobDto.ftl | 10 + .../templates/paths/history/job-log/get.ftl | 1 + .../templates/paths/history/job-log/post.ftl | 1 + .../paths/history/job-log/{id}/get.ftl | 1 + .../src/main/templates/paths/job/get.ftl | 6 +- .../src/main/templates/paths/job/post.ftl | 6 +- .../src/main/templates/paths/job/{id}/get.ftl | 3 +- .../rest/dto/history/HistoricJobLogDto.java | 6 + .../bpm/engine/rest/dto/runtime/JobDto.java | 6 + .../rest/JobRestServiceInteractionTest.java | 2 + .../engine/rest/JobRestServiceQueryTest.java | 2 + .../engine/rest/helper/MockJobBuilder.java | 7 + .../bpm/engine/rest/helper/MockProvider.java | 4 +- ...toricJobLogRestServiceInteractionTest.java | 1 + .../bpm/engine/history/HistoricJobLog.java | 6 + .../history/event/HistoricJobLogEvent.java | 9 + .../producer/DefaultHistoryEventProducer.java | 1 + .../impl/jobexecutor/JobDeclaration.java | 12 +- .../impl/persistence/entity/JobEntity.java | 11 + .../org/operaton/bpm/engine/runtime/Job.java | 11 + .../db/create/activiti.db2.create.engine.sql | 1 + .../db/create/activiti.db2.create.history.sql | 1 + .../db/create/activiti.h2.create.engine.sql | 1 + .../db/create/activiti.h2.create.history.sql | 1 + .../create/activiti.mariadb.create.engine.sql | 1 + .../activiti.mariadb.create.history.sql | 1 + .../create/activiti.mssql.create.engine.sql | 1 + .../create/activiti.mssql.create.history.sql | 1 + .../create/activiti.mysql.create.engine.sql | 1 + .../create/activiti.mysql.create.history.sql | 1 + .../create/activiti.oracle.create.engine.sql | 1 + .../create/activiti.oracle.create.history.sql | 1 + .../activiti.postgres.create.engine.sql | 1 + .../activiti.postgres.create.history.sql | 1 + .../db/upgrade/db2_engine_7.21_to_7.22.sql | 4 +- .../db/upgrade/h2_engine_7.21_to_7.22.sql | 3 + .../upgrade/mariadb_engine_7.21_to_7.22.sql | 3 + .../db/upgrade/mssql_engine_7.21_to_7.22.sql | 3 + .../db/upgrade/mysql_engine_7.21_to_7.22.sql | 3 + .../db/upgrade/oracle_engine_7.21_to_7.22.sql | 3 + .../upgrade/postgres_engine_7.21_to_7.22.sql | 3 + .../impl/mapping/entity/HistoricJobLog.xml | 7 +- .../bpm/engine/impl/mapping/entity/Job.xml | 16 +- .../JobEntityAndJobLogBatchIdTest.java | 469 ++++++++++++++++++ .../bpm/engine/test/util/BatchRule.java | 43 +- 46 files changed, 664 insertions(+), 25 deletions(-) create mode 100644 engine/src/test/java/org/operaton/bpm/engine/test/history/JobEntityAndJobLogBatchIdTest.java diff --git a/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/history/HistoricJobLogDto.ftl b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/history/HistoricJobLogDto.ftl index 067f3393b38..8a74373c63b 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/history/HistoricJobLogDto.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/history/HistoricJobLogDto.ftl @@ -140,7 +140,17 @@ The name of the host of the Process Engine where the job of this historic job log entry was executed." /> - + + <@lib.property + name = "batchId" + type = "string" + desc = "The ID of the batch associated with this job. `null` if no batch is associated with this job. The + following jobs are associated with batches: + * Seed Jobs + * Monitor Jobs + * Batch Execution Jobs" + /> + <@lib.property name = "creationLog" type = "boolean" diff --git a/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/runtime/JobDto.ftl b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/runtime/JobDto.ftl index 8c998351497..aead833b674 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/runtime/JobDto.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/models/org/operaton/bpm/engine/rest/dto/runtime/JobDto.ftl @@ -90,6 +90,16 @@ type = "string" format = "date-time" desc = "The date on which this job has been created." + /> + + <@lib.property + name = "batchId" + type = "string" + desc = "The ID of the batch associated with this job. `null` if no batch is associated with this job. The + following jobs are associated with batches: + * Seed Jobs + * Monitor Jobs + * Batch Execution Jobs" last = true /> diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/get.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/get.ftl index c8bccee0981..46704735371 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/get.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/get.ftl @@ -58,6 +58,7 @@ "rootProcessInstanceId": "aRootProcessInstanceId", "tenantId": null, "hostname": "aHostname", + "batchId": "aBatchId", "creationLog": true, "failureLog": false, "successLog": false, diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/post.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/post.ftl index 89474fb00c7..f257c2fcb0b 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/post.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/post.ftl @@ -63,6 +63,7 @@ "rootProcessInstanceId": "aRootProcessInstanceId", "tenantId": null, "hostname": "aHostname", + "batchId": "aBatchId", "creationLog": true, "failureLog": false, "successLog": false, diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/{id}/get.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/{id}/get.ftl index 982b19cb195..b1499c48b3b 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/{id}/get.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/history/job-log/{id}/get.ftl @@ -52,6 +52,7 @@ "rootProcessInstanceId": "aRootProcessInstanceId", "tenantId": null, "hostname": "aHostname", + "batchId": "aBatchId", "creationLog": true, "failureLog": false, "successLog": false, diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/job/get.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/job/get.ftl index 9cb9597513a..bebe599a910 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/job/get.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/job/get.ftl @@ -49,7 +49,8 @@ "suspended": false, "priority": 10, "tenantId": null, - "createTime": "2018-05-05T17:00:00+0200" + "createTime": "2018-05-05T17:00:00+0200", + "batchId": "aBatchId" }, { "id": "anotherJobId", @@ -65,7 +66,8 @@ "suspended": true, "priority": 8, "tenantId": null, - "createTime": "2018-05-05T17:00:00+0200" + "createTime": "2018-05-05T17:00:00+0200", + "batchId": null } ] }'] diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/job/post.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/job/post.ftl index d612bf17b6f..71846fd10a7 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/job/post.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/job/post.ftl @@ -82,7 +82,8 @@ "suspended": false, "priority": 10, "tenantId": null, - "createTime": "2018-05-05T17:00:00+0200" + "createTime": "2018-05-05T17:00:00+0200", + "batchId": "aBatchId" }, { "id": "anotherJobId", @@ -98,7 +99,8 @@ "suspended": true, "priority": 8, "tenantId": null, - "createTime": "2018-05-05T17:00:00+0200" + "createTime": "2018-05-05T17:00:00+0200", + "batchId": null } ] }'] diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/job/{id}/get.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/job/{id}/get.ftl index 51327ed2413..2b94543fa2a 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/job/{id}/get.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/job/{id}/get.ftl @@ -43,7 +43,8 @@ "suspended": false, "priority": 10, "tenantId": null, - "createTime": "2018-05-05T17:00:00+0200" + "createTime": "2018-05-05T17:00:00+0200", + "batchId": "aBatchId" } }'] /> diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricJobLogDto.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricJobLogDto.java index 6e84b3aa8e2..efffcb8c932 100644 --- a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricJobLogDto.java +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/history/HistoricJobLogDto.java @@ -50,6 +50,7 @@ public class HistoricJobLogDto { protected String tenantId; protected String hostname; protected String rootProcessInstanceId; + protected String batchId; protected boolean creationLog; protected boolean failureLog; @@ -140,6 +141,10 @@ public String getRootProcessInstanceId() { return rootProcessInstanceId; } + public String getBatchId() { + return batchId; + } + public boolean isCreationLog() { return creationLog; } @@ -183,6 +188,7 @@ public static HistoricJobLogDto fromHistoricJobLog(HistoricJobLog historicJobLog result.tenantId = historicJobLog.getTenantId(); result.hostname = historicJobLog.getHostname(); result.rootProcessInstanceId = historicJobLog.getRootProcessInstanceId(); + result.batchId = historicJobLog.getBatchId(); result.creationLog = historicJobLog.isCreationLog(); result.failureLog = historicJobLog.isFailureLog(); diff --git a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/runtime/JobDto.java b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/runtime/JobDto.java index 14ff09e3b1d..0a1c451c9c9 100644 --- a/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/runtime/JobDto.java +++ b/engine-rest/engine-rest/src/main/java/org/operaton/bpm/engine/rest/dto/runtime/JobDto.java @@ -36,6 +36,7 @@ public class JobDto { protected long priority; protected String tenantId; protected Date createTime; + protected String batchId; public static JobDto fromJob(Job job) { JobDto dto = new JobDto(); @@ -53,6 +54,7 @@ public static JobDto fromJob(Job job) { dto.priority = job.getPriority(); dto.tenantId = job.getTenantId(); dto.createTime = job.getCreateTime(); + dto.batchId = job.getBatchId(); return dto; } @@ -113,4 +115,8 @@ public Date getCreateTime() { return createTime; } + public String getBatchId() { + return batchId; + } + } diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/JobRestServiceInteractionTest.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/JobRestServiceInteractionTest.java index 197d8a67b4b..5356d023e27 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/JobRestServiceInteractionTest.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/JobRestServiceInteractionTest.java @@ -117,6 +117,7 @@ public void setUpRuntimeData() { .jobDefinitionId(MockProvider.EXAMPLE_JOB_DEFINITION_ID) .tenantId(MockProvider.EXAMPLE_TENANT_ID) .createTime(DateTimeUtil.parseDate(MockProvider.EXAMPLE_JOB_CREATE_TIME)) + .batchId(MockProvider.EXAMPLE_BATCH_ID) .build(); when(mockQuery.singleResult()).thenReturn(mockedJob); @@ -294,6 +295,7 @@ public void testSimpleJobGet() { .body("jobDefinitionId", equalTo(MockProvider.EXAMPLE_JOB_DEFINITION_ID)) .body("tenantId", equalTo(MockProvider.EXAMPLE_TENANT_ID)) .body("createTime", equalTo(MockProvider.EXAMPLE_JOB_CREATE_TIME)) + .body("batchId", equalTo(MockProvider.EXAMPLE_BATCH_ID)) .when() .get(SINGLE_JOB_RESOURCE_URL); diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/JobRestServiceQueryTest.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/JobRestServiceQueryTest.java index c3d2ab9be4b..70aad2071f6 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/JobRestServiceQueryTest.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/JobRestServiceQueryTest.java @@ -164,6 +164,7 @@ public void testSimpleJobQuery() { String returnedJobDefinitionId= from(content).getString("[0].jobDefinitionId"); String returnedTenantId = from(content).getString("[0].tenantId"); String returnedCreateTime = from(content).getString("[0].createTime"); + String returnedBatchId = from(content).getString("[0].batchId"); Assert.assertEquals(MockProvider.EXAMPLE_JOB_ID, returnedJobId); Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_ID, returnedProcessInstanceId); @@ -179,6 +180,7 @@ public void testSimpleJobQuery() { Assert.assertEquals(MockProvider.EXAMPLE_JOB_DEFINITION_ID, returnedJobDefinitionId); Assert.assertEquals(MockProvider.EXAMPLE_TENANT_ID, returnedTenantId); Assert.assertEquals(MockProvider.EXAMPLE_JOB_CREATE_TIME, returnedCreateTime); + Assert.assertEquals(MockProvider.EXAMPLE_BATCH_ID, returnedBatchId); } private interface DateParameters { diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockJobBuilder.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockJobBuilder.java index c2969c8f8ed..21686316fd0 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockJobBuilder.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockJobBuilder.java @@ -39,6 +39,7 @@ public class MockJobBuilder { protected String tenantId; protected Date createTime; protected String failedActivityId; + protected String batchId; public MockJobBuilder id(String id) { this.id = id; @@ -110,6 +111,11 @@ public MockJobBuilder failedActivityId(String failedActivityId) { return this; } + public MockJobBuilder batchId(String batchId) { + this.batchId = batchId; + return this; + } + public Job build() { Job mockJob = mock(Job.class); when(mockJob.getId()).thenReturn(id); @@ -126,6 +132,7 @@ public Job build() { when(mockJob.getTenantId()).thenReturn(tenantId); when(mockJob.getCreateTime()).thenReturn(createTime); when(mockJob.getFailedActivityId()).thenReturn(failedActivityId); + when(mockJob.getBatchId()).thenReturn(batchId); return mockJob; } diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java index c953b0729bc..15934942e23 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/helper/MockProvider.java @@ -1868,7 +1868,8 @@ public static MockJobBuilder mockJob() { .priority(EXAMPLE_JOB_PRIORITY) .jobDefinitionId(EXAMPLE_JOB_DEFINITION_ID) .createTime(DateTimeUtil.parseDate(EXAMPLE_JOB_CREATE_TIME)) - .failedActivityId(EXAMPLE_JOB_FAILED_ACTIVITY_ID); + .failedActivityId(EXAMPLE_JOB_FAILED_ACTIVITY_ID) + .batchId(EXAMPLE_BATCH_ID); } public static List createMockJobs() { @@ -2985,6 +2986,7 @@ public static HistoricJobLog createMockHistoricJobLog(String tenantId) { when(mock.getTenantId()).thenReturn(tenantId); when(mock.getRootProcessInstanceId()).thenReturn(EXAMPLE_HISTORIC_JOB_LOG_ROOT_PROC_INST_ID); when(mock.getHostname()).thenReturn(EXAMPLE_HISTORIC_JOB_LOG_HOSTNAME); + when(mock.getBatchId()).thenReturn(EXAMPLE_BATCH_ID); when(mock.isCreationLog()).thenReturn(EXAMPLE_HISTORIC_JOB_LOG_IS_CREATION_LOG); when(mock.isFailureLog()).thenReturn(EXAMPLE_HISTORIC_JOB_LOG_IS_FAILURE_LOG); diff --git a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricJobLogRestServiceInteractionTest.java b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricJobLogRestServiceInteractionTest.java index 42339da7666..ddac95bc9ac 100644 --- a/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricJobLogRestServiceInteractionTest.java +++ b/engine-rest/engine-rest/src/test/java/org/operaton/bpm/engine/rest/history/HistoricJobLogRestServiceInteractionTest.java @@ -106,6 +106,7 @@ public void testSimpleHistoricJobLogGet() { .body("tenantId", equalTo(MockProvider.EXAMPLE_TENANT_ID)) .body("hostname", equalTo(MockProvider.EXAMPLE_HISTORIC_JOB_LOG_HOSTNAME)) .body("rootProcessInstanceId", equalTo(MockProvider.EXAMPLE_HISTORIC_JOB_LOG_ROOT_PROC_INST_ID)) + .body("batchId", equalTo(MockProvider.EXAMPLE_BATCH_ID)) .body("creationLog", equalTo(MockProvider.EXAMPLE_HISTORIC_JOB_LOG_IS_CREATION_LOG)) .body("failureLog", equalTo(MockProvider.EXAMPLE_HISTORIC_JOB_LOG_IS_FAILURE_LOG)) .body("successLog", equalTo(MockProvider.EXAMPLE_HISTORIC_JOB_LOG_IS_SUCCESS_LOG)) diff --git a/engine/src/main/java/org/operaton/bpm/engine/history/HistoricJobLog.java b/engine/src/main/java/org/operaton/bpm/engine/history/HistoricJobLog.java index 7fece9fe197..e928463464a 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/history/HistoricJobLog.java +++ b/engine/src/main/java/org/operaton/bpm/engine/history/HistoricJobLog.java @@ -176,4 +176,10 @@ public interface HistoricJobLog { /** The time the historic job log will be removed. */ Date getRemovalTime(); + /** + * Returns the ID of the batch associated with the job or {@code null} if no batch is associated with the job. + * @return the ID of the batch associated with the job + */ + String getBatchId(); + } diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/history/event/HistoricJobLogEvent.java b/engine/src/main/java/org/operaton/bpm/engine/impl/history/event/HistoricJobLogEvent.java index 486b5f2bdc0..d963e3d2840 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/history/event/HistoricJobLogEvent.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/history/event/HistoricJobLogEvent.java @@ -63,6 +63,8 @@ public class HistoricJobLogEvent extends HistoryEvent { protected String hostname; + protected String batchId; + public Date getTimestamp() { return timestamp; } @@ -235,4 +237,11 @@ public void setFailedActivityId(String failedActivityId) { this.failedActivityId = failedActivityId; } + public String getBatchId() { + return batchId; + } + + public void setBatchId(String batchId) { + this.batchId = batchId; + } } diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java b/engine/src/main/java/org/operaton/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java index 38e3128262d..fad33d4caf6 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/history/producer/DefaultHistoryEventProducer.java @@ -1125,6 +1125,7 @@ protected void initHistoricJobLogEvent(HistoricJobLogEventEntity evt, Job job, H JobEntity jobEntity = (JobEntity) job; evt.setJobId(jobEntity.getId()); + evt.setBatchId(jobEntity.getBatchId()); evt.setJobDueDate(jobEntity.getDuedate()); evt.setJobRetries(jobEntity.getRetries()); evt.setJobPriority(jobEntity.getPriority()); diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/jobexecutor/JobDeclaration.java b/engine/src/main/java/org/operaton/bpm/engine/impl/jobexecutor/JobDeclaration.java index 3f5ed8e145f..956aaefc531 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/jobexecutor/JobDeclaration.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/jobexecutor/JobDeclaration.java @@ -20,8 +20,9 @@ import java.io.Serializable; import java.util.Date; - import org.operaton.bpm.engine.ProcessEngineConfiguration; +import org.operaton.bpm.engine.impl.batch.BatchEntity; +import org.operaton.bpm.engine.impl.batch.BatchJobContext; import org.operaton.bpm.engine.impl.context.Context; import org.operaton.bpm.engine.impl.core.variable.mapping.value.ParameterValueProvider; import org.operaton.bpm.engine.impl.persistence.entity.ExecutionEntity; @@ -77,6 +78,15 @@ public T createJobInstance(S context) { String jobDefinitionId = resolveJobDefinitionId(context); job.setJobDefinitionId(jobDefinitionId); + //set batch id for monitor and seed jobs (BatchEntity) and batch execution jobs (BatchJobContext) + if (context instanceof BatchEntity) { + BatchEntity batch = ((BatchEntity) context); + job.setBatchId(batch.getId()); + } else if (context instanceof BatchJobContext) { + BatchJobContext batchJobContext = (BatchJobContext) context; + job.setBatchId(batchJobContext.getBatch().getId()); + } + if(jobDefinitionId != null) { JobDefinitionEntity jobDefinition = Context.getCommandContext() diff --git a/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/JobEntity.java b/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/JobEntity.java index 9a6db0586ac..fa061d82a93 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/JobEntity.java +++ b/engine/src/main/java/org/operaton/bpm/engine/impl/persistence/entity/JobEntity.java @@ -114,6 +114,8 @@ public abstract class JobEntity extends AcquirableJobEntity protected Map persistedDependentEntities; + protected String batchId; + public void execute(CommandContext commandContext) { if (executionId != null) { ExecutionEntity execution = getExecution(); @@ -705,6 +707,14 @@ public void setFailedActivityId(String failedActivityId) { this.failedActivityId = failedActivityId; } + public String getBatchId() { + return batchId; + } + + public void setBatchId(String batchId) { + this.batchId = batchId; + } + @Override public String toString() { return this.getClass().getSimpleName() @@ -726,6 +736,7 @@ public String toString() { + ", deploymentId=" + deploymentId + ", priority=" + priority + ", tenantId=" + tenantId + + ", batchId=" + batchId + "]"; } diff --git a/engine/src/main/java/org/operaton/bpm/engine/runtime/Job.java b/engine/src/main/java/org/operaton/bpm/engine/runtime/Job.java index bb1ebc37273..a443927a02b 100644 --- a/engine/src/main/java/org/operaton/bpm/engine/runtime/Job.java +++ b/engine/src/main/java/org/operaton/bpm/engine/runtime/Job.java @@ -119,4 +119,15 @@ public interface Job { /** The date/time when this job has been created */ Date getCreateTime(); + /** + * The ID of the batch associated with this job. null if no batch is associated with this job. + * The following jobs are associated with batches: + *
    + *
  • Seed Jobs
  • + *
  • Monitor Jobs
  • + *
  • Batch Execution Jobs
  • + *
+ * @return The ID of the batch associated to the Job. + */ + String getBatchId(); } diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.engine.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.engine.sql index b3989a1857c..c007171ede6 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.engine.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.engine.sql @@ -130,6 +130,7 @@ create table ACT_RU_JOB ( TENANT_ID_ varchar(64), CREATE_TIME_ timestamp, LAST_FAILURE_LOG_ID_ varchar(64), + BATCH_ID_ varchar(64), primary key (ID_) ); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.history.sql index e4090b67ed8..29445d439dc 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.db2.create.history.sql @@ -289,6 +289,7 @@ create table ACT_HI_JOB_LOG ( TENANT_ID_ varchar(64), HOSTNAME_ varchar(255), REMOVAL_TIME_ timestamp, + BATCH_ID_ varchar(64), primary key (ID_) ); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.engine.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.engine.sql index 7c7c64ea59a..1af710fbdfc 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.engine.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.engine.sql @@ -130,6 +130,7 @@ create table ACT_RU_JOB ( TENANT_ID_ varchar(64), CREATE_TIME_ timestamp, LAST_FAILURE_LOG_ID_ varchar(64), + BATCH_ID_ varchar(64), primary key (ID_) ); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.history.sql index ad8c4dd42e6..1edf441710d 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.h2.create.history.sql @@ -288,6 +288,7 @@ create table ACT_HI_JOB_LOG ( TENANT_ID_ varchar(64), HOSTNAME_ varchar(255), REMOVAL_TIME_ timestamp, + BATCH_ID_ varchar(64), primary key (ID_) ); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.engine.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.engine.sql index 522ae0e1c5a..f24ca14d222 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.engine.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.engine.sql @@ -130,6 +130,7 @@ create table ACT_RU_JOB ( TENANT_ID_ varchar(64), CREATE_TIME_ datetime(3), LAST_FAILURE_LOG_ID_ varchar(64), + BATCH_ID_ varchar(64), primary key (ID_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.history.sql index e9c95f12f81..228b264ff75 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mariadb.create.history.sql @@ -288,6 +288,7 @@ create table ACT_HI_JOB_LOG ( TENANT_ID_ varchar(64), HOSTNAME_ varchar(255), REMOVAL_TIME_ datetime(3), + BATCH_ID_ varchar(64), primary key (ID_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.engine.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.engine.sql index f214c3a2547..4a2abbe0a20 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.engine.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.engine.sql @@ -130,6 +130,7 @@ create table ACT_RU_JOB ( TENANT_ID_ nvarchar(64), CREATE_TIME_ datetime2, LAST_FAILURE_LOG_ID_ nvarchar(64), + BATCH_ID_ nvarchar(64), primary key (ID_) ); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.history.sql index 27a26b37212..076516d4c12 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mssql.create.history.sql @@ -287,6 +287,7 @@ create table ACT_HI_JOB_LOG ( TENANT_ID_ nvarchar(64), HOSTNAME_ nvarchar(255), REMOVAL_TIME_ datetime2, + BATCH_ID_ nvarchar(64), primary key (ID_) ); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.engine.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.engine.sql index 49a5962aea2..4d60e888494 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.engine.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.engine.sql @@ -130,6 +130,7 @@ create table ACT_RU_JOB ( TENANT_ID_ varchar(64), CREATE_TIME_ datetime, LAST_FAILURE_LOG_ID_ varchar(64), + BATCH_ID_ varchar(64), primary key (ID_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.history.sql index 4c8d0720f44..4559ad612b8 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.mysql.create.history.sql @@ -288,6 +288,7 @@ create table ACT_HI_JOB_LOG ( TENANT_ID_ varchar(64), HOSTNAME_ varchar(255), REMOVAL_TIME_ datetime, + BATCH_ID_ varchar(64), primary key (ID_) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.engine.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.engine.sql index 05a6fddf78a..814e48459d3 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.engine.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.engine.sql @@ -130,6 +130,7 @@ create table ACT_RU_JOB ( TENANT_ID_ NVARCHAR2(64), CREATE_TIME_ TIMESTAMP(6), LAST_FAILURE_LOG_ID_ NVARCHAR2(64), + BATCH_ID_ NVARCHAR2(64), primary key (ID_) ); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.history.sql index ffe27b569ff..e28095b8416 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.oracle.create.history.sql @@ -288,6 +288,7 @@ create table ACT_HI_JOB_LOG ( TENANT_ID_ NVARCHAR2(64), HOSTNAME_ NVARCHAR2(255), REMOVAL_TIME_ TIMESTAMP(6), + BATCH_ID_ NVARCHAR2(64), primary key (ID_) ); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.engine.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.engine.sql index e05f02d7214..e45f8533f0f 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.engine.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.engine.sql @@ -130,6 +130,7 @@ create table ACT_RU_JOB ( TENANT_ID_ varchar(64), CREATE_TIME_ timestamp, LAST_FAILURE_LOG_ID_ varchar(64), + BATCH_ID_ varchar(64), primary key (ID_) ); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.history.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.history.sql index aa111103f25..c95743b5187 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.history.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/create/activiti.postgres.create.history.sql @@ -288,6 +288,7 @@ create table ACT_HI_JOB_LOG ( TENANT_ID_ varchar(64), HOSTNAME_ varchar(255), REMOVAL_TIME_ timestamp, + BATCH_ID_ varchar(64), primary key (ID_) ); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/db2_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/db2_engine_7.21_to_7.22.sql index 566033c3f1a..55583c6f431 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/db2_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/db2_engine_7.21_to_7.22.sql @@ -22,6 +22,8 @@ alter table ACT_RU_TASK add column TASK_STATE_ varchar(64); alter table ACT_HI_TASKINST add column TASK_STATE_ varchar(64); +alter table ACT_RU_JOB add column BATCH_ID_ varchar(64); +alter table ACT_HI_JOB_LOG add column BATCH_ID_ varchar(64); alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ varchar(64); -create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); \ No newline at end of file +create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/h2_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/h2_engine_7.21_to_7.22.sql index 8918a9bdc81..55583c6f431 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/h2_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/h2_engine_7.21_to_7.22.sql @@ -22,5 +22,8 @@ alter table ACT_RU_TASK add column TASK_STATE_ varchar(64); alter table ACT_HI_TASKINST add column TASK_STATE_ varchar(64); +alter table ACT_RU_JOB add column BATCH_ID_ varchar(64); +alter table ACT_HI_JOB_LOG add column BATCH_ID_ varchar(64); + alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ varchar(64); create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mariadb_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mariadb_engine_7.21_to_7.22.sql index 8918a9bdc81..55583c6f431 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mariadb_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mariadb_engine_7.21_to_7.22.sql @@ -22,5 +22,8 @@ alter table ACT_RU_TASK add column TASK_STATE_ varchar(64); alter table ACT_HI_TASKINST add column TASK_STATE_ varchar(64); +alter table ACT_RU_JOB add column BATCH_ID_ varchar(64); +alter table ACT_HI_JOB_LOG add column BATCH_ID_ varchar(64); + alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ varchar(64); create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mssql_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mssql_engine_7.21_to_7.22.sql index 4e884d3918e..66ea5d03d6d 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mssql_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mssql_engine_7.21_to_7.22.sql @@ -22,5 +22,8 @@ alter table ACT_RU_TASK add TASK_STATE_ nvarchar(64); alter table ACT_HI_TASKINST add TASK_STATE_ nvarchar(64); +alter table ACT_RU_JOB add BATCH_ID_ nvarchar(64); +alter table ACT_HI_JOB_LOG add BATCH_ID_ nvarchar(64); + alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ nvarchar(64); create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mysql_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mysql_engine_7.21_to_7.22.sql index 8918a9bdc81..55583c6f431 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mysql_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/mysql_engine_7.21_to_7.22.sql @@ -22,5 +22,8 @@ alter table ACT_RU_TASK add column TASK_STATE_ varchar(64); alter table ACT_HI_TASKINST add column TASK_STATE_ varchar(64); +alter table ACT_RU_JOB add column BATCH_ID_ varchar(64); +alter table ACT_HI_JOB_LOG add column BATCH_ID_ varchar(64); + alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ varchar(64); create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/oracle_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/oracle_engine_7.21_to_7.22.sql index 235e7284d10..afe6e9d3f09 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/oracle_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/oracle_engine_7.21_to_7.22.sql @@ -22,5 +22,8 @@ alter table ACT_RU_TASK add TASK_STATE_ NVARCHAR2(64); alter table ACT_HI_TASKINST add TASK_STATE_ NVARCHAR2(64); +alter table ACT_RU_JOB add BATCH_ID_ NVARCHAR2(64); +alter table ACT_HI_JOB_LOG add BATCH_ID_ NVARCHAR2(64); + alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ NVARCHAR2(64); create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/postgres_engine_7.21_to_7.22.sql b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/postgres_engine_7.21_to_7.22.sql index 8918a9bdc81..55583c6f431 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/postgres_engine_7.21_to_7.22.sql +++ b/engine/src/main/resources/org/operaton/bpm/engine/db/upgrade/postgres_engine_7.21_to_7.22.sql @@ -22,5 +22,8 @@ alter table ACT_RU_TASK add column TASK_STATE_ varchar(64); alter table ACT_HI_TASKINST add column TASK_STATE_ varchar(64); +alter table ACT_RU_JOB add column BATCH_ID_ varchar(64); +alter table ACT_HI_JOB_LOG add column BATCH_ID_ varchar(64); + alter table ACT_HI_PROCINST add RESTARTED_PROC_INST_ID_ varchar(64); create index ACT_IDX_HI_PRO_RST_PRO_INST_ID on ACT_HI_PROCINST(RESTARTED_PROC_INST_ID_); diff --git a/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/HistoricJobLog.xml b/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/HistoricJobLog.xml index 0bf27c8043a..9282abd28e4 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/HistoricJobLog.xml +++ b/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/HistoricJobLog.xml @@ -48,7 +48,8 @@ TENANT_ID_, HOSTNAME_, SEQUENCE_COUNTER_, - REMOVAL_TIME_ + REMOVAL_TIME_, + BATCH_ID_ ) values (#{id, jdbcType=VARCHAR}, #{timestamp, jdbcType=TIMESTAMP}, @@ -73,7 +74,8 @@ #{tenantId, jdbcType=VARCHAR}, #{hostname, jdbcType=VARCHAR}, #{sequenceCounter, jdbcType=BIGINT}, - #{removalTime, jdbcType=TIMESTAMP} + #{removalTime, jdbcType=TIMESTAMP}, + #{batchId, jdbcType=VARCHAR} ) @@ -366,6 +368,7 @@ + diff --git a/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/Job.xml b/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/Job.xml index 49a924ac40b..f22101cdfb4 100644 --- a/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/Job.xml +++ b/engine/src/main/resources/org/operaton/bpm/engine/impl/mapping/entity/Job.xml @@ -137,6 +137,7 @@ + @@ -491,6 +492,7 @@ SEQUENCE_COUNTER_, TENANT_ID_, CREATE_TIME_, + BATCH_ID_, REV_ ) values (#{id, jdbcType=VARCHAR}, @@ -519,6 +521,7 @@ #{sequenceCounter, jdbcType=BIGINT}, #{tenantId, jdbcType=VARCHAR}, #{createTime, jdbcType=TIMESTAMP}, + #{batchId, jdbcType=VARCHAR}, 1 ) @@ -547,7 +550,8 @@ HANDLER_CFG_ = #{jobHandlerConfigurationRaw, jdbcType=VARCHAR}, PRIORITY_ = #{priority, jdbcType=BIGINT}, SEQUENCE_COUNTER_ = #{sequenceCounter, jdbcType=BIGINT}, - LAST_FAILURE_LOG_ID_ = #{lastFailureLogId, jdbcType=VARCHAR} + LAST_FAILURE_LOG_ID_ = #{lastFailureLogId, jdbcType=VARCHAR}, + BATCH_ID_ = #{batchId, jdbcType=VARCHAR} where ID_= #{id, jdbcType=VARCHAR} and REV_ = #{revision, jdbcType=INTEGER} @@ -602,6 +606,7 @@ SEQUENCE_COUNTER_, TENANT_ID_, CREATE_TIME_, + BATCH_ID_, REV_ ) values (#{id, jdbcType=VARCHAR}, @@ -628,6 +633,7 @@ #{sequenceCounter, jdbcType=BIGINT}, #{tenantId, jdbcType=VARCHAR}, #{createTime, jdbcType=TIMESTAMP}, + #{batchId, jdbcType=VARCHAR}, 1 ) @@ -653,7 +659,8 @@ HANDLER_CFG_ = #{jobHandlerConfigurationRaw, jdbcType=VARCHAR}, PRIORITY_ = #{priority, jdbcType=BIGINT}, SEQUENCE_COUNTER_ = #{sequenceCounter, jdbcType=BIGINT}, - LAST_FAILURE_LOG_ID_ = #{lastFailureLogId, jdbcType=VARCHAR} + LAST_FAILURE_LOG_ID_ = #{lastFailureLogId, jdbcType=VARCHAR}, + BATCH_ID_ = #{batchId, jdbcType=VARCHAR} where ID_= #{id, jdbcType=VARCHAR} and REV_ = #{revision, jdbcType=INTEGER} @@ -685,6 +692,7 @@ SEQUENCE_COUNTER_, TENANT_ID_, CREATE_TIME_, + BATCH_ID_, REV_ ) values (#{id, jdbcType=VARCHAR}, @@ -711,6 +719,7 @@ #{sequenceCounter, jdbcType=BIGINT}, #{tenantId, jdbcType=VARCHAR}, #{createTime, jdbcType=TIMESTAMP}, + #{batchId, jdbcType=VARCHAR}, 1 ) @@ -736,7 +745,8 @@ HANDLER_CFG_ = #{jobHandlerConfigurationRaw, jdbcType=VARCHAR}, PRIORITY_ = #{priority, jdbcType=BIGINT}, SEQUENCE_COUNTER_ = #{sequenceCounter, jdbcType=BIGINT}, - LAST_FAILURE_LOG_ID_ = #{lastFailureLogId, jdbcType=VARCHAR} + LAST_FAILURE_LOG_ID_ = #{lastFailureLogId, jdbcType=VARCHAR}, + BATCH_ID_ = #{batchId, jdbcType=VARCHAR} where ID_= #{id, jdbcType=VARCHAR} and REV_ = #{revision, jdbcType=INTEGER} diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/history/JobEntityAndJobLogBatchIdTest.java b/engine/src/test/java/org/operaton/bpm/engine/test/history/JobEntityAndJobLogBatchIdTest.java new file mode 100644 index 00000000000..3e4ee05e7b4 --- /dev/null +++ b/engine/src/test/java/org/operaton/bpm/engine/test/history/JobEntityAndJobLogBatchIdTest.java @@ -0,0 +1,469 @@ +/* + * Copyright Camunda Services GmbH and/or licensed to Camunda Services GmbH + * under one or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information regarding copyright + * ownership. Camunda licenses this file to you under the Apache License, + * Version 2.0; you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.operaton.bpm.engine.test.history; + +import static org.assertj.core.api.Assertions.assertThat; + +import java.util.List; +import java.util.Map; +import org.operaton.bpm.engine.DecisionService; +import org.operaton.bpm.engine.ExternalTaskService; +import org.operaton.bpm.engine.HistoryService; +import org.operaton.bpm.engine.ManagementService; +import org.operaton.bpm.engine.RuntimeService; +import org.operaton.bpm.engine.batch.Batch; +import org.operaton.bpm.engine.externaltask.ExternalTask; +import org.operaton.bpm.engine.history.HistoricDecisionInstanceQuery; +import org.operaton.bpm.engine.history.HistoricJobLog; +import org.operaton.bpm.engine.history.HistoricProcessInstanceQuery; +import org.operaton.bpm.engine.impl.batch.BatchMonitorJobHandler; +import org.operaton.bpm.engine.impl.batch.BatchSeedJobHandler; +import org.operaton.bpm.engine.migration.MigrationPlan; +import org.operaton.bpm.engine.repository.ProcessDefinition; +import org.operaton.bpm.engine.runtime.ActivityInstance; +import org.operaton.bpm.engine.runtime.Job; +import org.operaton.bpm.engine.runtime.ProcessInstance; +import org.operaton.bpm.engine.test.Deployment; +import org.operaton.bpm.engine.test.ProcessEngineRule; +import org.operaton.bpm.engine.test.api.history.removaltime.batch.helper.BatchSetRemovalTimeRule; +import org.operaton.bpm.engine.test.util.BatchRule; +import org.operaton.bpm.engine.test.util.ProcessEngineTestRule; +import org.operaton.bpm.engine.test.util.ProvidedProcessEngineRule; +import org.operaton.bpm.engine.variable.Variables; +import org.operaton.bpm.model.bpmn.Bpmn; +import org.operaton.bpm.model.bpmn.BpmnModelInstance; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.RuleChain; + +public class JobEntityAndJobLogBatchIdTest { + + protected ProcessEngineRule engineRule = new ProvidedProcessEngineRule(); + protected ProcessEngineTestRule testRule = new ProcessEngineTestRule(engineRule); + protected BatchRule batchRule = new BatchRule(engineRule, testRule); + protected BatchSetRemovalTimeRule batchRemovalTimeRule = new BatchSetRemovalTimeRule(engineRule, testRule); + + @Rule + public RuleChain ruleChain = RuleChain + .outerRule(engineRule) + .around(testRule) + .around(batchRule) + .around(batchRemovalTimeRule); + + protected RuntimeService runtimeService; + protected HistoryService historyService; + protected ManagementService managementService; + protected DecisionService decisionService; + protected ExternalTaskService externalTaskService; + + @Before + public void init() { + runtimeService = engineRule.getRuntimeService(); + historyService = engineRule.getHistoryService(); + managementService = engineRule.getManagementService(); + decisionService = engineRule.getDecisionService(); + externalTaskService = engineRule.getExternalTaskService(); + } + + private BpmnModelInstance getUserTaskProcess() { + return Bpmn.createExecutableProcess("process") + .startEvent() + .userTask("task1") + .endEvent() + .done(); + } + + private BpmnModelInstance getTwoUserTasksProcess() { + return Bpmn.createExecutableProcess("process") + .startEvent() + .userTask("task1") + .userTask("task2") + .endEvent() + .done(); + } + + private BpmnModelInstance getTimerProcess() { + return Bpmn.createExecutableProcess("process") + .startEvent() + .timerWithDuration("PT5H") + .endEvent() + .done(); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_SetHistoricBatchRemovalTime() { + // given + testRule.deploy(getUserTaskProcess()); + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("process"); + + // create historic Batch + Batch setVariablesBatch = runtimeService.setVariablesAsync(List.of(processInstance.getId()), + Variables.createVariables().putValue("foo", "bar")); + batchRule.syncExec(setVariablesBatch); + + // set historic batch removal time + Batch setRemovalTimeBatch = historyService.setRemovalTimeToHistoricBatches() + .absoluteRemovalTime(batchRemovalTimeRule.REMOVAL_TIME) + .byQuery(historyService.createHistoricBatchQuery()) + .executeAsync(); + + // when + Map> processedJobs = batchRule.syncExec(setRemovalTimeBatch); + + // then + assertProcessedJobs(setRemovalTimeBatch, processedJobs); + /* + * there is no way to filter for the historic job log of only the set historic batch removal time batch + * as a workaround: check that the historic job log contains the corresponding batch id for seed and + * monitor jobs from both batches. + */ + assertThat(setVariablesBatch.getId()).isNotNull(); + assertThat(setRemovalTimeBatch.getId()).isNotNull(); + List batchSeedJobLogs = historyService.createHistoricJobLogQuery() + .successLog() + .jobDefinitionType(BatchSeedJobHandler.TYPE) + .list(); + assertThat(batchSeedJobLogs).extracting("batchId") + .containsExactlyInAnyOrder(setVariablesBatch.getId(), setRemovalTimeBatch.getId()); + List batchMonitorJobLogs = historyService.createHistoricJobLogQuery() + .successLog() + .jobDefinitionType(BatchMonitorJobHandler.TYPE) + .list(); + assertThat(batchMonitorJobLogs).extracting("batchId") + .containsExactlyInAnyOrder(setVariablesBatch.getId(), setRemovalTimeBatch.getId()); + List batchExecutionJobLogs = historyService.createHistoricJobLogQuery() + .successLog() + .jobDefinitionType(Batch.TYPE_BATCH_SET_REMOVAL_TIME) + .list(); + assertThat(batchExecutionJobLogs).extracting("batchId").containsOnly(setRemovalTimeBatch.getId()); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_SetVariables() { + // given + testRule.deploy(getUserTaskProcess()); + ProcessInstance process = runtimeService.startProcessInstanceByKey("process"); + + Batch batch = runtimeService.setVariablesAsync(List.of(process.getId()), Variables.createVariables().putValue("foo", "bar")); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_SET_VARIABLES); + } + + @Test + @Deployment(resources = { + "org/operaton/bpm/engine/test/dmn/deployment/drdDish.dmn11.xml" + }) + public void shouldSetBatchIdOnJobAndJobLog_DecisionSetRemovalTime() { + // given + decisionService.evaluateDecisionByKey("dish-decision") + .variables( + Variables.createVariables() + .putValue("temperature", 32) + .putValue("dayType", "Weekend") + ).evaluate(); + + Batch batch = historyService.setRemovalTimeToHistoricDecisionInstances() + .absoluteRemovalTime(batchRemovalTimeRule.REMOVAL_TIME) + .byQuery(historyService.createHistoricDecisionInstanceQuery()) + .executeAsync(); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + // we expect three execution jobs, all should have the batch id + assertHistoricJobLogs(batch, Batch.TYPE_DECISION_SET_REMOVAL_TIME); + } + + @Test + @Deployment(resources = { + "org/operaton/bpm/engine/test/dmn/deployment/drdDish.dmn11.xml" + }) + public void shouldSetBatchIdOnJobAndJobLog_DeleteHistoricDecisionInstances() { + // given + decisionService.evaluateDecisionByKey("dish-decision") + .variables( + Variables.createVariables() + .putValue("temperature", 32) + .putValue("dayType", "Weekend") + ).evaluate(); + + HistoricDecisionInstanceQuery query = historyService.createHistoricDecisionInstanceQuery() + .decisionDefinitionKey("dish-decision"); + + Batch batch = historyService.deleteHistoricDecisionInstancesAsync(query, null); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_HISTORIC_DECISION_INSTANCE_DELETION); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_DeleteHistoricProcessInstances() { + // given + testRule.deploy(Bpmn.createExecutableProcess("process") + .startEvent() + .endEvent() + .done()); + runtimeService.startProcessInstanceByKey("process"); + + HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery() + .processDefinitionKey("process"); + + Batch batch = historyService.deleteHistoricProcessInstancesAsync(query, null); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_HISTORIC_PROCESS_INSTANCE_DELETION); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_DeleteProcessInstances() { + // given + testRule.deploy(getUserTaskProcess()); + ProcessInstance process = runtimeService.startProcessInstanceByKey("process"); + + Batch batch = runtimeService.deleteProcessInstancesAsync(List.of(process.getId()), null); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_PROCESS_INSTANCE_DELETION); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_MessageCorrelation() { + // given + testRule.deploy(Bpmn.createExecutableProcess("process") + .startEvent() + .intermediateCatchEvent().message("message") + .userTask() + .endEvent() + .done()); + ProcessInstance process = runtimeService.startProcessInstanceByKey("process"); + + Batch batch = runtimeService.createMessageCorrelationAsync("message") + .processInstanceIds(List.of(process.getId())) + .correlateAllAsync(); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_CORRELATE_MESSAGE); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_Migration() { + // given + ProcessDefinition sourceProcessDefinition = testRule.deployAndGetDefinition(getUserTaskProcess()); + ProcessInstance process = runtimeService.startProcessInstanceByKey("process"); + ProcessDefinition targetProcessDefinition = testRule.deployAndGetDefinition(getTwoUserTasksProcess()); + + MigrationPlan migrationPlan = runtimeService.createMigrationPlan(sourceProcessDefinition.getId(), targetProcessDefinition.getId()) + .mapEqualActivities() + .build(); + + Batch batch = runtimeService.newMigration(migrationPlan).processInstanceIds(List.of(process.getId())).executeAsync(); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_PROCESS_INSTANCE_MIGRATION); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_Modification() { + // given + testRule.deploy(getTwoUserTasksProcess()); + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("process"); + + ActivityInstance tree = runtimeService.getActivityInstance(processInstance.getId()); + + // when + Batch batch = runtimeService.createProcessInstanceModification(processInstance.getId()) + .cancelActivityInstance(tree.getActivityInstances("task1")[0].getId()) + .startBeforeActivity("task2") + .executeAsync(); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_PROCESS_INSTANCE_MODIFICATION); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_ProcessSetRemovalTime() { + // given + testRule.deploy(getTwoUserTasksProcess()); + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("process"); + + Batch batch = historyService.setRemovalTimeToHistoricProcessInstances() + .absoluteRemovalTime(batchRemovalTimeRule.REMOVAL_TIME) + .byIds(processInstance.getId()) + .executeAsync(); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_PROCESS_SET_REMOVAL_TIME); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_RestartProcessInstance() { + // given + testRule.deploy(getUserTaskProcess()); + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("process"); + runtimeService.deleteProcessInstance(processInstance.getId(), null); + + Batch batch = runtimeService.restartProcessInstances(processInstance.getProcessDefinitionId()) + .processInstanceIds(processInstance.getId()) + .startBeforeActivity("task1") + .executeAsync(); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_PROCESS_INSTANCE_RESTART); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_SetExternalTaskRetries() { + // given + testRule.deploy(Bpmn.createExecutableProcess("process") + .startEvent() + .serviceTask().operatonExternalTask("topic") + .endEvent() + .done()); + runtimeService.startProcessInstanceByKey("process"); + + ExternalTask externalTask = externalTaskService.createExternalTaskQuery().singleResult(); + + Batch batch = externalTaskService.setRetriesAsync(List.of(externalTask.getId()), null, 5); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_SET_EXTERNAL_TASK_RETRIES); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_SetJobRetries() { + // given + testRule.deploy(getTimerProcess()); + runtimeService.startProcessInstanceByKey("process"); + + Job timerJob = managementService.createJobQuery().singleResult(); + + Batch batch = managementService.setJobRetriesAsync(List.of(timerJob.getId()), 5); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_SET_JOB_RETRIES); + } + + @Test + public void shouldSetBatchIdOnJobAndJobLog_UpdateProcessInstancesSuspendState() { + // given + testRule.deploy(getUserTaskProcess()); + ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("process"); + + Batch batch = runtimeService.updateProcessInstanceSuspensionState() + .byProcessInstanceIds(List.of(processInstance.getId())) + .suspendAsync(); + + // when + Map> processedJobs = batchRule.syncExec(batch); + + // then + assertProcessedJobs(batch, processedJobs); + assertHistoricJobLogs(batch, Batch.TYPE_PROCESS_INSTANCE_UPDATE_SUSPENSION_STATE); + } + + @Test + public void shouldNotSetBatchIdOnJobOrJobLog_nonBatchJob() { + // given + testRule.deploy(getTimerProcess()); + runtimeService.startProcessInstanceByKey("process"); + + Job timerJob = managementService.createJobQuery().singleResult(); + + // when + managementService.executeJob(timerJob.getId()); + + // then + List historicJobLogs = historyService.createHistoricJobLogQuery().list(); + assertThat(historicJobLogs).hasSize(2); + assertThat(historicJobLogs).extracting("batchId").containsOnlyNulls(); + } + + // HELPER + + private void assertProcessedJobs(Batch batch, Map> processedJobs) { + assertThat(processedJobs.get(BatchRule.SEED_JOB)).extracting("batchId").containsOnly(batch.getId()); + assertThat(processedJobs.get(BatchRule.EXECUTION_JOBS)).extracting("batchId").containsOnly(batch.getId()); + assertThat(processedJobs.get(BatchRule.MONITOR_JOB)).extracting("batchId").containsOnly(batch.getId()); + } + + private void assertHistoricJobLogs(Batch batch, String expectedBatchType) { + assertThat(batch.getId()).isNotNull(); + List batchSeedJobLogs = historyService.createHistoricJobLogQuery() + .successLog() + .jobDefinitionType(BatchSeedJobHandler.TYPE) + .list(); + assertThat(batchSeedJobLogs).extracting("batchId").containsOnly(batch.getId()); + List batchMonitorJobLogs = historyService.createHistoricJobLogQuery() + .successLog() + .jobDefinitionType(BatchMonitorJobHandler.TYPE) + .list(); + assertThat(batchMonitorJobLogs).extracting("batchId").containsOnly(batch.getId()); + List batchExecutionJobLogs = historyService.createHistoricJobLogQuery() + .successLog() + .jobDefinitionType(expectedBatchType) + .list(); + assertThat(batchExecutionJobLogs).extracting("batchId").containsOnly(batch.getId()); + } +} \ No newline at end of file diff --git a/engine/src/test/java/org/operaton/bpm/engine/test/util/BatchRule.java b/engine/src/test/java/org/operaton/bpm/engine/test/util/BatchRule.java index 5eaf8b332fa..02a4f9f643c 100644 --- a/engine/src/test/java/org/operaton/bpm/engine/test/util/BatchRule.java +++ b/engine/src/test/java/org/operaton/bpm/engine/test/util/BatchRule.java @@ -19,7 +19,9 @@ import static org.operaton.bpm.engine.impl.cfg.ProcessEngineConfigurationImpl.DEFAULT_INVOCATIONS_PER_BATCH_JOB; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import org.operaton.bpm.engine.batch.Batch; import org.operaton.bpm.engine.batch.history.HistoricBatch; import org.operaton.bpm.engine.impl.util.ClockUtil; @@ -30,6 +32,10 @@ public class BatchRule extends TestWatcher { + public static final String SEED_JOB = "seed-job"; + public static final String MONITOR_JOB = "monitor-job"; + public static final String EXECUTION_JOBS = "execution-job"; + protected ProcessEngineRule engineRule; protected ProcessEngineTestRule engineTestRule; @@ -68,40 +74,55 @@ public void clearDatabase() { } } - public void syncExec(Batch batch) { - syncExec(batch, true); + public Map> syncExec(Batch batch) { + return syncExec(batch, true); } - public void syncExec(Batch batch, boolean isClear) { + public Map> syncExec(Batch batch, boolean isClear) { + Map> processedJobs = new HashMap<>(); + List processedSeedJobs = new ArrayList<>(); if (isClear) { batchIds.add(batch.getId()); } - executeSeedJobs(batch); + processedSeedJobs.addAll(executeSeedJobs(batch)); + processedJobs.put(SEED_JOB, processedSeedJobs); + List processedExecutionJobs = new ArrayList<>(); List jobs = getExecutionJobs(batch); while (!jobs.isEmpty()) { for (Job job : jobs) { engineRule.getManagementService().executeJob(job.getId()); + processedExecutionJobs.add(job); } jobs = getExecutionJobs(batch); } - - engineRule.getManagementService().executeJob( - getJobForDefinition(batch.getMonitorJobDefinitionId()).getId()); + processedJobs.put(EXECUTION_JOBS, processedExecutionJobs); + + List processedMonitorJobs = new ArrayList<>(); + Job monitorJob = getJobForDefinition(batch.getMonitorJobDefinitionId()); + engineRule.getManagementService().executeJob(monitorJob.getId()); + processedMonitorJobs.add(monitorJob); + processedJobs.put(MONITOR_JOB, processedMonitorJobs); + + return processedJobs; } - public void executeSeedJobs(Batch batch) { - executeSeedJobs(batch, false); + public List executeSeedJobs(Batch batch) { + return executeSeedJobs(batch, false); } - public void executeSeedJobs(Batch batch, boolean cleanUp) { + public List executeSeedJobs(Batch batch, boolean cleanUp) { + List processedJobs = new ArrayList<>(); if (cleanUp) { batchIds.add(batch.getId()); } while (getSeedJob(batch) != null) { - engineRule.getManagementService().executeJob(getSeedJob(batch).getId()); + Job seedJob = getSeedJob(batch); + engineRule.getManagementService().executeJob(seedJob.getId()); + processedJobs.add(seedJob); } + return processedJobs; } public Job getSeedJob(Batch batch) { From f452b5cc4d7795e43d8bbeb5ede1c5a04a709bac Mon Sep 17 00:00:00 2001 From: Julian Haupt Date: Thu, 7 Nov 2024 10:49:16 +0100 Subject: [PATCH 37/37] fix(openapi): fix incorrect schema for metrics param (#4555) related to https://github.com/camunda/camunda-bpm-platform/issues/4554 Backported commit b1c8dd36919 from the camunda-bpm-platform repository. Original author: Timo Kramer <4785848+TimoKramer@users.noreply.github.com>" --- .../src/main/templates/paths/metrics/get.ftl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/engine-rest/engine-rest-openapi/src/main/templates/paths/metrics/get.ftl b/engine-rest/engine-rest-openapi/src/main/templates/paths/metrics/get.ftl index 064b12ee410..7540c5c8e4f 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/paths/metrics/get.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/paths/metrics/get.ftl @@ -59,7 +59,8 @@ <@lib.parameter name = "interval" location = "query" - type = "string" + type = "integer" + format = "int64" defaultValue = "900" desc = "The interval for which the metrics should be aggregated. Time unit is seconds. Default: The interval is set to 15 minutes (900 seconds)." />