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 8f82a166a42..aeea2140b02 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 @@ -108,6 +108,11 @@ "desc": "Restrict the query to all process instances that are top level process instances." }, + "rootProcessInstanceId": { + "type": "string", + "desc": "Filter by root process instance id." + }, + "finished": { "type": "boolean", "desc": "Only include finished process instances. This flag includes all process instances diff --git a/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/process-instance-query-params.ftl b/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/process-instance-query-params.ftl index abb304cc1c5..a68be9f01aa 100644 --- a/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/process-instance-query-params.ftl +++ b/engine-rest/engine-rest-openapi/src/main/templates/lib/commons/process-instance-query-params.ftl @@ -141,6 +141,11 @@ defaultValue = 'false' desc = "Restrict the query to all process instances that are top level process instances."/> + <@lib.parameter name = "rootProcessInstanceId" + location = "query" + type = "string" + desc = "Filter by root process instance id."/> + <@lib.parameter name = "leafProcessInstances" location = "query" type = "boolean" diff --git a/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/history/HistoricProcessInstanceQueryDto.java b/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/history/HistoricProcessInstanceQueryDto.java index 7648342e268..c9bbca59617 100644 --- a/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/history/HistoricProcessInstanceQueryDto.java +++ b/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/history/HistoricProcessInstanceQueryDto.java @@ -74,6 +74,7 @@ public class HistoricProcessInstanceQueryDto extends AbstractQueryDto processInstanceIds; private List processInstanceIdNotIn; + private String rootProcessInstanceId; private String processDefinitionId; private String processDefinitionKey; private List processDefinitionKeys; @@ -152,6 +153,15 @@ public void setProcessInstanceIdNotIn(List processInstanceIdNotIn) { this.processInstanceIdNotIn = processInstanceIdNotIn; } + public String getRootProcessInstanceId() { + return rootProcessInstanceId; + } + + @CamundaQueryParam("rootProcessInstanceId") + public void setRootProcessInstanceId(String rootProcessInstanceId) { + this.rootProcessInstanceId = rootProcessInstanceId; + } + public String getProcessDefinitionId() { return processDefinitionId; } @@ -428,6 +438,9 @@ protected void applyFilters(HistoricProcessInstanceQuery query) { if (processInstanceIdNotIn != null && !processInstanceIdNotIn.isEmpty()) { query.processInstanceIdNotIn(processInstanceIdNotIn.toArray(new String[0])); } + if (rootProcessInstanceId != null) { + query.rootProcessInstanceId(rootProcessInstanceId); + } if (processDefinitionId != null) { query.processDefinitionId(processDefinitionId); } diff --git a/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/runtime/ProcessInstanceQueryDto.java b/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/runtime/ProcessInstanceQueryDto.java index bd2db10c76d..9e575582a5b 100644 --- a/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/runtime/ProcessInstanceQueryDto.java +++ b/engine-rest/engine-rest/src/main/java/org/camunda/bpm/engine/rest/dto/runtime/ProcessInstanceQueryDto.java @@ -75,6 +75,7 @@ public class ProcessInstanceQueryDto extends AbstractQueryDto processInstanceIds; private Boolean withIncident; private String incidentId; + private String rootProcessInstanceId; private String incidentType; private String incidentMessage; private String incidentMessageLike; @@ -285,6 +286,15 @@ public void setIncidentId(String incidentId) { this.incidentId = incidentId; } + public String getRootProcessInstanceId() { + return rootProcessInstanceId; + } + + @CamundaQueryParam("rootProcessInstanceId") + public void setRootProcessInstanceId(String rootProcessInstanceId) { + this.rootProcessInstanceId = rootProcessInstanceId; + } + public String getIncidentType() { return incidentType; } @@ -442,6 +452,9 @@ protected void applyFilters(ProcessInstanceQuery query) { if (incidentId != null) { query.incidentId(incidentId); } + if (rootProcessInstanceId != null) { + query.rootProcessInstanceId(rootProcessInstanceId); + } if (incidentType != null) { query.incidentType(incidentType); } diff --git a/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ProcessInstanceRestServiceQueryTest.java b/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ProcessInstanceRestServiceQueryTest.java index 83112080dd9..ee047680a00 100644 --- a/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ProcessInstanceRestServiceQueryTest.java +++ b/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/ProcessInstanceRestServiceQueryTest.java @@ -242,6 +242,7 @@ public void testAdditionalParametersExcludingVariables() { verify(mockedQuery).incidentMessage(queryParameters.get("incidentMessage")); verify(mockedQuery).incidentMessageLike(queryParameters.get("incidentMessageLike")); verify(mockedQuery).incidentType(queryParameters.get("incidentType")); + verify(mockedQuery).rootProcessInstanceId(queryParameters.get("rootProcessInstanceId")); verify(mockedQuery).list(); } @@ -264,6 +265,7 @@ private Map getCompleteQueryParameters() { parameters.put("incidentMessageLike", "incMessageLike"); parameters.put("incidentType", "incType"); parameters.put("caseInstanceId", "aCaseInstanceId"); + parameters.put("rootProcessInstanceId", "aRootProcessInstanceId"); return parameters; } @@ -917,9 +919,44 @@ public void testCompletePostParameters() { verify(mockedQuery).incidentMessage(queryParameters.get("incidentMessage")); verify(mockedQuery).incidentMessageLike(queryParameters.get("incidentMessageLike")); verify(mockedQuery).incidentType(queryParameters.get("incidentType")); + verify(mockedQuery).rootProcessInstanceId(queryParameters.get("rootProcessInstanceId")); verify(mockedQuery).list(); } + @Test + public void testGetProcessInstancesForRootProcessInstanceId() { + Response response = given().queryParam("rootProcessInstanceId", MockProvider.EXAMPLE_ROOT_PROCESS_INSTANCE_ID) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .contentType(ContentType.JSON) + .when() + .get(PROCESS_INSTANCE_QUERY_URL); + + verify(mockedQuery).list(); + + String content = response.asString(); + List instances = from(content).getList(""); + assertThat(instances).size().isGreaterThan(0); + + String returnedProcessInstanceId = from(content).getString("[0].id"); + String returnedProcessDefinitionId = from(content).getString("[0].definitionId"); + String returnedProcessInstanceBusinessKey = from(content).getString("[0].businessKey"); + String returnedCaseInstanceId = from(content).getString("[0].caseInstanceId"); + Boolean returnedIsEnded = from(content).getBoolean("[0].ended"); + Boolean returnedIsSuspended = from(content).getBoolean("[0].suspended"); + String returnedTenantId = from(content).getString("[0].tenantId"); + + Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_ID, returnedProcessInstanceId); + Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_DEFINITION_ID, returnedProcessDefinitionId); + Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_BUSINESS_KEY, returnedProcessInstanceBusinessKey); + Assert.assertEquals(MockProvider.EXAMPLE_CASE_INSTANCE_ID, returnedCaseInstanceId); + Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_IS_ENDED, returnedIsEnded); + Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_IS_SUSPENDED, returnedIsSuspended); + Assert.assertEquals(MockProvider.EXAMPLE_TENANT_ID, returnedTenantId); + } + @Test public void testTenantIdListParameter() { mockedQuery = setUpMockInstanceQuery(createMockProcessInstancesTwoTenants()); diff --git a/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/helper/MockProvider.java b/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/helper/MockProvider.java index 99df67cfe0c..7516e1791e5 100644 --- a/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/helper/MockProvider.java +++ b/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/helper/MockProvider.java @@ -247,6 +247,7 @@ public abstract class MockProvider { public static final String EXAMPLE_PROCESS_INSTANCE_BUSINESS_KEY = "aKey"; public static final String EXAMPLE_PROCESS_INSTANCE_BUSINESS_KEY_LIKE = "aKeyLike"; public static final String EXAMPLE_PROCESS_INSTANCE_ID = "aProcInstId"; + public static final String EXAMPLE_ROOT_PROCESS_INSTANCE_ID = "aRootProcessInstanceId"; public static final String EXAMPLE_ROOT_HISTORIC_PROCESS_INSTANCE_ID = "aRootProcInstId"; public static final String ANOTHER_EXAMPLE_PROCESS_INSTANCE_ID = "anotherId"; public static final boolean EXAMPLE_PROCESS_INSTANCE_IS_SUSPENDED = false; diff --git a/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java b/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java index 9741ce4c5fa..51bb16a5bcd 100644 --- a/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java +++ b/engine-rest/engine-rest/src/test/java/org/camunda/bpm/engine/rest/history/HistoricProcessInstanceRestServiceQueryTest.java @@ -455,6 +455,70 @@ public void testSimpleHistoricProcessQuery() { Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_INSTANCE_ID, restartedProcessInstanceId); } + @Test + public void testGetHistoryProcessInstancesForRootProcessInstanceId() { + Response response = given().queryParam("rootProcessInstanceId", + MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_ROOT_PROCESS_INSTANCE_ID) + .header("accept", MediaType.APPLICATION_JSON) + .then() + .expect() + .statusCode(Status.OK.getStatusCode()) + .contentType(ContentType.JSON) + .when() + .get(HISTORIC_PROCESS_INSTANCE_RESOURCE_URL); + + verify(mockedQuery).list(); + + String content = response.asString(); + List instances = from(content).getList(""); + assertThat(instances).size().isGreaterThan(0); + + String returnedProcessInstanceId = from(content).getString("[0].id"); + String returnedProcessInstanceBusinessKey = from(content).getString("[0].businessKey"); + String returnedProcessDefinitionId = from(content).getString("[0].processDefinitionId"); + String returnedProcessDefinitionKey = from(content).getString("[0].processDefinitionKey"); + String returnedProcessDefinitionName = from(content).getString("[0].processDefinitionName"); + int returnedProcessDefinitionVersion = from(content).getInt("[0].processDefinitionVersion"); + String returnedStartTime = from(content).getString("[0].startTime"); + String returnedEndTime = from(content).getString("[0].endTime"); + String returnedRemovalTime = from(content).getString("[0].removalTime"); + long returnedDurationInMillis = from(content).getLong("[0].durationInMillis"); + String returnedStartUserId = from(content).getString("[0].startUserId"); + String returnedStartActivityId = from(content).getString("[0].startActivityId"); + String returnedDeleteReason = from(content).getString("[0].deleteReason"); + String returnedRootProcessInstanceId = from(content).getString("[0].rootProcessInstanceId"); + String returnedSuperProcessInstanceId = from(content).getString("[0].superProcessInstanceId"); + String returnedSuperCaseInstanceId = from(content).getString("[0].superCaseInstanceId"); + 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); + Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_DEFINITION_ID, returnedProcessDefinitionId); + Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_DEFINITION_KEY, returnedProcessDefinitionKey); + Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_DEFINITION_NAME, returnedProcessDefinitionName); + Assert.assertEquals(MockProvider.EXAMPLE_PROCESS_DEFINITION_VERSION, returnedProcessDefinitionVersion); + Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_START_TIME, returnedStartTime); + Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_END_TIME, returnedEndTime); + Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_REMOVAL_TIME, returnedRemovalTime); + Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_DURATION_MILLIS, returnedDurationInMillis); + Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_START_USER_ID, returnedStartUserId); + Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_START_ACTIVITY_ID, returnedStartActivityId); + Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_DELETE_REASON, returnedDeleteReason); + Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_ROOT_PROCESS_INSTANCE_ID, + returnedRootProcessInstanceId); + Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_SUPER_PROCESS_INSTANCE_ID, + returnedSuperProcessInstanceId); + Assert.assertEquals(MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_SUPER_CASE_INSTANCE_ID, + returnedSuperCaseInstanceId); + 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 public void testAdditionalParametersExcludingProcesses() { Map stringQueryParameters = getCompleteStringQueryParameters(); @@ -504,6 +568,7 @@ private Map getCompleteStringQueryParameters() { parameters.put("caseInstanceId", MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_CASE_INSTANCE_ID); parameters.put("state", MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_STATE); parameters.put("incidentType", MockProvider.EXAMPLE_INCIDENT_TYPE); + parameters.put("rootProcessInstanceId", MockProvider.EXAMPLE_HISTORIC_PROCESS_INSTANCE_ROOT_PROCESS_INSTANCE_ID); return parameters; } @@ -525,6 +590,7 @@ private void verifyStringParameterQueryInvocations() { verify(mockedQuery).subCaseInstanceId(stringQueryParameters.get("subCaseInstanceId")); verify(mockedQuery).caseInstanceId(stringQueryParameters.get("caseInstanceId")); verify(mockedQuery).incidentType(stringQueryParameters.get("incidentType")); + verify(mockedQuery).rootProcessInstanceId(stringQueryParameters.get("rootProcessInstanceId")); verify(mockedQuery).list(); } diff --git a/engine/src/main/java/org/camunda/bpm/engine/history/HistoricProcessInstanceQuery.java b/engine/src/main/java/org/camunda/bpm/engine/history/HistoricProcessInstanceQuery.java index 4ffb8326282..2d0d7edca7a 100644 --- a/engine/src/main/java/org/camunda/bpm/engine/history/HistoricProcessInstanceQuery.java +++ b/engine/src/main/java/org/camunda/bpm/engine/history/HistoricProcessInstanceQuery.java @@ -54,6 +54,11 @@ public interface HistoricProcessInstanceQuery extends Query getProcessInstanceIds() { return processInstanceIds; } diff --git a/engine/src/main/java/org/camunda/bpm/engine/impl/ProcessInstanceQueryImpl.java b/engine/src/main/java/org/camunda/bpm/engine/impl/ProcessInstanceQueryImpl.java index 07ce1a4f650..a4f700f68f0 100644 --- a/engine/src/main/java/org/camunda/bpm/engine/impl/ProcessInstanceQueryImpl.java +++ b/engine/src/main/java/org/camunda/bpm/engine/impl/ProcessInstanceQueryImpl.java @@ -48,6 +48,7 @@ public class ProcessInstanceQueryImpl extends AbstractVariableQueryImpl processInstanceIds) { ensureNotEmpty("Set of process instance ids", processInstanceIds); this.processInstanceIds = processInstanceIds; @@ -370,6 +377,10 @@ public String getProcessInstanceId() { return processInstanceId; } + public String getRootProcessInstanceId() { + return rootProcessInstanceId; + } + public Set getProcessInstanceIds() { return processInstanceIds; } diff --git a/engine/src/main/java/org/camunda/bpm/engine/runtime/ProcessInstanceQuery.java b/engine/src/main/java/org/camunda/bpm/engine/runtime/ProcessInstanceQuery.java index 09b6f9252af..141505bcc75 100644 --- a/engine/src/main/java/org/camunda/bpm/engine/runtime/ProcessInstanceQuery.java +++ b/engine/src/main/java/org/camunda/bpm/engine/runtime/ProcessInstanceQuery.java @@ -42,6 +42,11 @@ public interface ProcessInstanceQuery extends Query processInstanceIds); + /** + * Select process instances for the given root process instance id + */ + ProcessInstanceQuery rootProcessInstanceId(String rootProcessInstanceId); + /** * Select process instances with the given business key */ diff --git a/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/Execution.xml b/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/Execution.xml index 728804e5e29..2cd4ecca986 100644 --- a/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/Execution.xml +++ b/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/Execution.xml @@ -306,6 +306,9 @@ ${queryType} RES.PROC_INST_ID_ = #{query.processInstanceId} + + ${queryType} RES.ROOT_PROC_INST_ID_ = #{query.rootProcessInstanceId} + ${queryType} diff --git a/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/HistoricProcessInstance.xml b/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/HistoricProcessInstance.xml index 7ce6117dd3a..b0c4530e5d4 100644 --- a/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/HistoricProcessInstance.xml +++ b/engine/src/main/resources/org/camunda/bpm/engine/impl/mapping/entity/HistoricProcessInstance.xml @@ -465,6 +465,9 @@ ${queryType} SELF.PROC_INST_ID_ = #{query.processInstanceId} + + ${queryType} SELF.ROOT_PROC_INST_ID_ = #{query.rootProcessInstanceId} + ${queryType} diff --git a/engine/src/test/java/org/camunda/bpm/engine/test/api/runtime/ProcessInstanceQueryTest.java b/engine/src/test/java/org/camunda/bpm/engine/test/api/runtime/ProcessInstanceQueryTest.java index 64fddca85c5..9afd8addbab 100644 --- a/engine/src/test/java/org/camunda/bpm/engine/test/api/runtime/ProcessInstanceQueryTest.java +++ b/engine/src/test/java/org/camunda/bpm/engine/test/api/runtime/ProcessInstanceQueryTest.java @@ -62,6 +62,7 @@ import org.camunda.bpm.engine.test.util.ProcessEngineTestRule; import org.camunda.bpm.engine.test.util.ProvidedProcessEngineRule; import org.camunda.bpm.engine.variable.Variables; +import org.camunda.bpm.model.bpmn.Bpmn; import org.camunda.bpm.model.bpmn.BpmnModelInstance; import org.junit.Assert; import org.junit.Before; @@ -2227,6 +2228,45 @@ public void testQueryByRootProcessInstances() { assertEquals(processInstanceId, list.get(0).getId()); } + @Test + public void testQueryByRootProcessInstanceId() { + // given a parent process instance with a couple of subprocesses + BpmnModelInstance baseProcess = Bpmn.createExecutableProcess("baseProcess") + .startEvent("startRoot") + .callActivity() + .calledElement("levelOneProcess") + .endEvent("endRoot") + .done(); + + BpmnModelInstance levelOneProcess = Bpmn.createExecutableProcess("levelOneProcess") + .startEvent("startLevelOne") + .callActivity() + .calledElement("levelTwoProcess") + .endEvent("endLevelOne") + .done(); + + BpmnModelInstance levelTwoProcess = Bpmn.createExecutableProcess("levelTwoProcess") + .startEvent("startLevelTwo") + .userTask("Task1") + .endEvent("endLevelTwo") + .done(); + + testHelper.deploy(baseProcess, levelOneProcess, levelTwoProcess); + String rootProcessId = runtimeService.startProcessInstanceByKey("baseProcess").getId(); + List allProcessInstances = runtimeService.createProcessInstanceQuery().list(); + + // when + ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery() + .rootProcessInstanceId(rootProcessId); + + // then + assertEquals(3, allProcessInstances.stream() + .filter(process -> process.getRootProcessInstanceId().equals(rootProcessId)) + .count()); + assertEquals(3, processInstanceQuery.count()); + assertEquals(3, processInstanceQuery.list().size()); + } + @Test public void testQueryByRootProcessInstancesAndSuperProcess() { // when diff --git a/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricProcessInstanceTest.java b/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricProcessInstanceTest.java index 0bf3bfcab1a..56e9a7995f6 100644 --- a/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricProcessInstanceTest.java +++ b/engine/src/test/java/org/camunda/bpm/engine/test/history/HistoricProcessInstanceTest.java @@ -2802,6 +2802,47 @@ public void testExcludingProcessInstanceIdsAndProcessInstanceIdNotIn() { assertThat(count).isEqualTo(0L); } + @Test + public void shouldQueryByRootProcessInstanceId() { + // given a parent process instance with a couple of subprocesses + BpmnModelInstance rootProcess = Bpmn.createExecutableProcess("rootProcess") + .startEvent("startRoot") + .callActivity() + .calledElement("levelOneProcess") + .endEvent("endRoot") + .done(); + + BpmnModelInstance levelOneProcess = Bpmn.createExecutableProcess("levelOneProcess") + .startEvent("startLevelOne") + .callActivity() + .calledElement("levelTwoProcess") + .endEvent("endLevelOne") + .done(); + + BpmnModelInstance levelTwoProcess = Bpmn.createExecutableProcess("levelTwoProcess") + .startEvent("startLevelTwo") + .userTask("Task1") + .endEvent("endLevelTwo") + .done(); + + deployment(rootProcess, levelOneProcess, levelTwoProcess); + String rootProcessId = runtimeService.startProcessInstanceByKey("rootProcess").getId(); + List allHistoricProcessInstances = historyService.createHistoricProcessInstanceQuery() + .list(); + + // when + HistoricProcessInstanceQuery historicProcessInstanceQuery = historyService.createHistoricProcessInstanceQuery() + .rootProcessInstanceId(rootProcessId); + + // then + assertEquals(3, allHistoricProcessInstances.size()); + assertEquals(3, allHistoricProcessInstances.stream() + .filter(process -> process.getRootProcessInstanceId().equals(rootProcessId)) + .count()); + assertEquals(3, historicProcessInstanceQuery.count()); + assertEquals(3, historicProcessInstanceQuery.list().size()); + } + protected void deployment(String... resources) { testHelper.deploy(resources); }