Skip to content

Commit

Permalink
feature(engine): add activityIdIn filter to HistoricProcessInstanceQuery
Browse files Browse the repository at this point in the history
related to: #4618
  • Loading branch information
venetrius committed Sep 18, 2024
1 parent 8de6e2d commit c088a99
Show file tree
Hide file tree
Showing 7 changed files with 146 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,13 @@
"desc": "Only include historic process instances which belong to no tenant. Value may only be `true`, as `false` is the default behavior."
},

"activityIdIn": {
"type": "array",
"itemType": "string",
"desc": "Restrict to instances that have an active activity or failing activity with one of given ids. It works
similarly to the activityIdIn filter in the runtime query. ${listTypeDescription}"
},

"executedActivityIdIn": {
"type": "array",
"itemType": "string",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ public class HistoricProcessInstanceQueryDto extends AbstractQueryDto<HistoricPr
private Boolean withoutTenantId;
private List<String> executedActivityIdIn;
private List<String> activeActivityIdIn;
private List<String> activityIdIn;
private Boolean active;
private Boolean suspended;
private Boolean completed;
Expand Down Expand Up @@ -336,6 +337,11 @@ public void setActiveActivityIdIn(List<String> activeActivityIdIn) {
this.activeActivityIdIn = activeActivityIdIn;
}

@CamundaQueryParam(value = "activityIdIn", converter = StringListConverter.class)
public void setactivityIdIn(List<String> activityIdIn) {
this.activityIdIn = activityIdIn;
}

@CamundaQueryParam(value = "executedJobAfter", converter = DateConverter.class)
public void setExecutedJobAfter(Date executedJobAfter) {
this.executedJobAfter = executedJobAfter;
Expand Down Expand Up @@ -539,6 +545,10 @@ protected void applyFilters(HistoricProcessInstanceQuery query) {
query.activeActivityIdIn(activeActivityIdIn.toArray(new String[0]));
}

if(activityIdIn!= null && !activityIdIn.isEmpty()) {
query.activityIdIn(activityIdIn.toArray(new String[0]));
}

if (executedJobAfter != null) {
query.executedJobAfter(executedJobAfter);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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_ACTIVE_OR_FAILING_ACTIVITY_IDS = "activityIdIn";

@ClassRule
public static TestContainerRule rule = new TestContainerRule();
Expand Down Expand Up @@ -2318,4 +2319,32 @@ public void testQueryByRootProcessInstancesAsPost() {
verify(mockedQuery).rootProcessInstances();
}

@Test
public void testQueryByActivityIdIn() {
given()
.queryParam(QUERY_PARAM_ACTIVE_OR_FAILING_ACTIVITY_IDS, "1,2")
.then().expect()
.statusCode(Status.OK.getStatusCode())
.when()
.get(HISTORIC_PROCESS_INSTANCE_RESOURCE_URL);

verify(mockedQuery).activityIdIn("1", "2");
}

@Test
public void testQueryByActivityIdInAsPost() {
Map<String, List<String>> parameters = new HashMap<String, List<String>>();
parameters.put(QUERY_PARAM_ACTIVE_OR_FAILING_ACTIVITY_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).activityIdIn("1", "2");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,11 @@ public interface HistoricProcessInstanceQuery extends Query<HistoricProcessInsta
*/
HistoricProcessInstanceQuery activeActivityIdIn(String... ids);

/**
* Only select historic process instances that have active activities or failing activities with given ids.
*/
HistoricProcessInstanceQuery activityIdIn(String... ids);

/**
* Only select historic process instances that executed an job after the given date.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ public class HistoricProcessInstanceQueryImpl extends AbstractVariableQueryImpl<
protected boolean isTenantIdSet;
protected String[] executedActivityIds;
protected String[] activeActivityIds;
protected String[] activityIds;
protected String state;

protected String caseInstanceId;
Expand Down Expand Up @@ -471,6 +472,10 @@ public String[] getActiveActivityIds() {
return activeActivityIds;
}

public String[] getActivityIds() {
return activityIds;
}

public String getBusinessKey() {
return businessKey;
}
Expand Down Expand Up @@ -770,6 +775,14 @@ public HistoricProcessInstanceQuery activeActivityIdIn(String... ids) {
return this;
}

@Override
public HistoricProcessInstanceQuery activityIdIn(String... ids) {
ensureNotNull(BadUserRequestException.class, "activity ids", (Object[]) ids);
ensureNotContainsNull(BadUserRequestException.class, "activity ids", Arrays.asList(ids));
this.activityIds = ids;
return this;
}

@Override
public HistoricProcessInstanceQuery active() {
ensureNull(BadUserRequestException.class, "Already querying for historic process instance with another state", state, state);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@

<bind name="INC_JOIN" value="false" />
<bind name="HAI_JOIN" value="false" />
<bind name="RU_JOB_JOIN" value="false" />
<bind name="JOIN_TYPE" value="'inner join'" />

<foreach collection="queries" item="query">
Expand All @@ -413,9 +414,13 @@
<bind name="INC_JOIN" value="true" />
</if>

<if test="query != null &amp;&amp; (query.executedActivityIds != null and query.executedActivityIds.length > 0) || (query.activeActivityIds != null and query.activeActivityIds.length > 0)">
<if test="query != null &amp;&amp; (query.executedActivityIds != null and query.executedActivityIds.length > 0) || (query.activeActivityIds != null and query.activeActivityIds.length > 0) || (query.activityIds != null and query.activityIds.length > 0)">
<bind name="HAI_JOIN" value="true" />
</if>

<if test="query != null &amp;&amp; (query.activityIds != null and query.activityIds.length > 0)">
<bind name="RU_JOB_JOIN" value="true" />
</if>
</foreach>

<if test="INC_JOIN">
Expand All @@ -425,6 +430,11 @@
LEFT JOIN ${prefix}ACT_HI_ACTINST HAI
ON HAI.PROC_INST_ID_ = SELF.ID_
</if>

<if test="RU_JOB_JOIN">
LEFT JOIN ${prefix}ACT_RU_JOB RU_JOB
ON RU_JOB.PROCESS_INSTANCE_ID_ = SELF.PROC_INST_ID_
</if>

<!-- actual value conditions are checked in the WHERE part;
however here we must join once for every variable condition.
Expand Down Expand Up @@ -626,6 +636,21 @@
)
</if>

<if test="query.activityIds != null and query.activityIds.length > 0">
${queryType} (
(
HAI.END_TIME_ IS NULL
AND HAI.ACT_ID_ IN
<foreach item="activityId" index="index" collection="query.activityIds" open="(" separator="," close=")">
#{activityId}
</foreach>
) OR RU_JOB.FAILED_ACT_ID_ IN
<foreach item="activityId" index="index" collection="query.activityIds" open="(" separator="," close=")">
#{activityId}
</foreach>
)
</if>

<if test="query.executedActivityIds != null and query.executedActivityIds.length > 0">
${queryType} (
HAI.END_TIME_ IS NOT NULL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1546,6 +1546,62 @@ public void testHistoricProcInstQueryWithActiveActivityIds() {
assertEquals(result.get(0).getId(), processInstance.getId());
}

@Test
@RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL)
public void testHistoricProcInstQueryWithActivityIdsWithoutError() {
// given
deployment(ProcessModels.TWO_TASKS_PROCESS);
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("Process");

// assume
HistoricActivityInstance historicActivityInstance = historyService
.createHistoricActivityInstanceQuery()
.activityId("userTask1")
.singleResult();
assertNotNull(historicActivityInstance);

// when
List<HistoricProcessInstance> result = historyService
.createHistoricProcessInstanceQuery()
.activityIdIn(historicActivityInstance.getActivityId())
.list();

// then
assertNotNull(result);
assertEquals(1, result.size());
assertEquals(result.get(0).getId(), processInstance.getId());
}

@Test
@RequiredHistoryLevel(ProcessEngineConfiguration.HISTORY_FULL)
@Deployment(resources = {"org/camunda/bpm/engine/test/history/HistoricProcessInstanceTest.testHistoricProcessInstanceQueryWithIncidents.bpmn"})
public void testHistoricProcInstQueryWithActivityIdsWithError() {
// given
runtimeService.startProcessInstanceByKey("Process_1");
testHelper.executeAvailableJobs();

runtimeService.startProcessInstanceByKey("Process_1");

// 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<HistoricProcessInstance> result = historyService
.createHistoricProcessInstanceQuery()
.activityIdIn("ServiceTask_3")
.list();

// then
assertNotNull(result);
assertEquals(1, result.size());
assertEquals(result.get(0).getId(), failingInstance.getId());
}

@Test
public void testHistoricProcInstQueryWithActiveActivityIdsNull() {
try {
Expand Down

0 comments on commit c088a99

Please sign in to comment.