Skip to content

Commit 7bc6912

Browse files
Merge branch 'main' of github.com:flowable/flowable-engine into flowable-release-8.1.0
2 parents 61454ae + b925ba7 commit 7bc6912

18 files changed

Lines changed: 377 additions & 0 deletions

File tree

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/* Licensed under the Apache License, Version 2.0 (the "License");
2+
* you may not use this file except in compliance with the License.
3+
* You may obtain a copy of the License at
4+
*
5+
* http://www.apache.org/licenses/LICENSE-2.0
6+
*
7+
* Unless required by applicable law or agreed to in writing, software
8+
* distributed under the License is distributed on an "AS IS" BASIS,
9+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
* See the License for the specific language governing permissions and
11+
* limitations under the License.
12+
*/
13+
package org.flowable.rest.app;
14+
15+
import static net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson;
16+
import static org.assertj.core.api.Assertions.assertThat;
17+
18+
import org.flowable.cmmn.api.CmmnRuntimeService;
19+
import org.flowable.cmmn.api.CmmnTaskService;
20+
import org.flowable.cmmn.api.runtime.CaseInstance;
21+
import org.flowable.cmmn.engine.test.CmmnDeployment;
22+
import org.flowable.cmmn.spring.impl.test.FlowableCmmnSpringExtension;
23+
import org.flowable.engine.RuntimeService;
24+
import org.flowable.engine.TaskService;
25+
import org.flowable.engine.runtime.ProcessInstance;
26+
import org.flowable.engine.test.Deployment;
27+
import org.flowable.spring.impl.test.FlowableSpringExtension;
28+
import org.flowable.task.api.Task;
29+
import org.junit.jupiter.api.Test;
30+
import org.junit.jupiter.api.extension.ExtendWith;
31+
import org.springframework.beans.factory.annotation.Autowired;
32+
import org.springframework.boot.resttestclient.TestRestTemplate;
33+
import org.springframework.boot.resttestclient.autoconfigure.AutoConfigureTestRestTemplate;
34+
import org.springframework.boot.test.context.SpringBootTest;
35+
import org.springframework.http.HttpStatus;
36+
import org.springframework.http.ResponseEntity;
37+
38+
import tools.jackson.databind.JsonNode;
39+
40+
import net.javacrumbs.jsonunit.core.Option;
41+
42+
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
43+
@ExtendWith({
44+
FlowableCmmnSpringExtension.class,
45+
FlowableSpringExtension.class,
46+
})
47+
@AutoConfigureTestRestTemplate
48+
public class CrossEngineRestQueryTest {
49+
50+
@Autowired
51+
protected RuntimeService runtimeService;
52+
53+
@Autowired
54+
protected TaskService taskService;
55+
56+
@Autowired
57+
protected CmmnRuntimeService cmmnRuntimeService;
58+
59+
@Autowired
60+
protected CmmnTaskService cmmnTaskService;
61+
62+
@Autowired
63+
protected TestRestTemplate restTemplate;
64+
65+
@Test
66+
@Deployment(resources = "processWithCaseTask.bpmn20.xml")
67+
@CmmnDeployment(resources = "oneHumanTaskCase.cmmn")
68+
void queryCaseInstancesByParentProcessInstanceId() {
69+
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("processWithCaseTask");
70+
71+
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceQuery()
72+
.parentProcessInstanceId(processInstance.getId())
73+
.singleResult();
74+
assertThat(caseInstance).isNotNull();
75+
76+
ResponseEntity<JsonNode> response = restTemplate.withBasicAuth("rest-admin", "test")
77+
.getForEntity("/cmmn-api/cmmn-runtime/case-instances?parentProcessInstanceId={id}",
78+
JsonNode.class, processInstance.getId());
79+
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
80+
assertThatJson(response.getBody())
81+
.when(Option.IGNORING_EXTRA_FIELDS)
82+
.isEqualTo("{"
83+
+ " data: ["
84+
+ " { id: '" + caseInstance.getId() + "' }"
85+
+ " ]"
86+
+ "}");
87+
88+
response = restTemplate.withBasicAuth("rest-admin", "test")
89+
.getForEntity("/cmmn-api/cmmn-runtime/case-instances?parentProcessInstanceId=nonExisting",
90+
JsonNode.class);
91+
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
92+
assertThatJson(response.getBody())
93+
.when(Option.IGNORING_EXTRA_FIELDS)
94+
.isEqualTo("{ data: [] }");
95+
96+
response = restTemplate.withBasicAuth("rest-admin", "test")
97+
.getForEntity("/cmmn-api/cmmn-history/historic-case-instances?parentProcessInstanceId={id}",
98+
JsonNode.class, processInstance.getId());
99+
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
100+
assertThatJson(response.getBody())
101+
.when(Option.IGNORING_EXTRA_FIELDS)
102+
.isEqualTo("{"
103+
+ " data: ["
104+
+ " { id: '" + caseInstance.getId() + "' }"
105+
+ " ]"
106+
+ "}");
107+
108+
Task caseTask = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).singleResult();
109+
cmmnTaskService.complete(caseTask.getId());
110+
111+
response = restTemplate.withBasicAuth("rest-admin", "test")
112+
.getForEntity("/cmmn-api/cmmn-history/historic-case-instances?parentProcessInstanceId={id}",
113+
JsonNode.class, processInstance.getId());
114+
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
115+
assertThatJson(response.getBody())
116+
.when(Option.IGNORING_EXTRA_FIELDS)
117+
.isEqualTo("{"
118+
+ " data: ["
119+
+ " { id: '" + caseInstance.getId() + "' }"
120+
+ " ]"
121+
+ "}");
122+
}
123+
124+
@Test
125+
@Deployment(resources = "oneTaskProcess.bpmn20.xml")
126+
@CmmnDeployment(resources = "caseWithProcessTask.cmmn")
127+
void queryProcessInstancesByParentCaseInstanceId() {
128+
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceBuilder()
129+
.caseDefinitionKey("caseWithProcessTask")
130+
.start();
131+
132+
ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
133+
.parentCaseInstanceId(caseInstance.getId())
134+
.singleResult();
135+
assertThat(processInstance).isNotNull();
136+
137+
ResponseEntity<JsonNode> response = restTemplate.withBasicAuth("rest-admin", "test")
138+
.getForEntity("/service/runtime/process-instances?parentCaseInstanceId={id}",
139+
JsonNode.class, caseInstance.getId());
140+
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
141+
assertThatJson(response.getBody())
142+
.when(Option.IGNORING_EXTRA_FIELDS)
143+
.isEqualTo("{"
144+
+ " data: ["
145+
+ " { id: '" + processInstance.getId() + "' }"
146+
+ " ]"
147+
+ "}");
148+
149+
response = restTemplate.withBasicAuth("rest-admin", "test")
150+
.getForEntity("/service/runtime/process-instances?parentCaseInstanceId=nonExisting",
151+
JsonNode.class);
152+
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
153+
assertThatJson(response.getBody())
154+
.when(Option.IGNORING_EXTRA_FIELDS)
155+
.isEqualTo("{ data: [] }");
156+
157+
response = restTemplate.withBasicAuth("rest-admin", "test")
158+
.getForEntity("/service/history/historic-process-instances?parentCaseInstanceId={id}",
159+
JsonNode.class, caseInstance.getId());
160+
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
161+
assertThatJson(response.getBody())
162+
.when(Option.IGNORING_EXTRA_FIELDS)
163+
.isEqualTo("{"
164+
+ " data: ["
165+
+ " { id: '" + processInstance.getId() + "' }"
166+
+ " ]"
167+
+ "}");
168+
169+
Task processTask = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
170+
taskService.complete(processTask.getId());
171+
172+
response = restTemplate.withBasicAuth("rest-admin", "test")
173+
.getForEntity("/service/history/historic-process-instances?parentCaseInstanceId={id}",
174+
JsonNode.class, caseInstance.getId());
175+
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
176+
assertThatJson(response.getBody())
177+
.when(Option.IGNORING_EXTRA_FIELDS)
178+
.isEqualTo("{"
179+
+ " data: ["
180+
+ " { id: '" + processInstance.getId() + "' }"
181+
+ " ]"
182+
+ "}");
183+
}
184+
}

modules/flowable-app-rest/src/test/java/org/flowable/test/persistence/EntityParameterTypesOverview.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -949,6 +949,7 @@ protected static void addCaseInstanceParams() {
949949
info.addQueryParameter("rootScopeId", PARAMETER_TYPE_NVARCHAR);
950950
info.addQueryParameter("rootScopeIdItem", PARAMETER_TYPE_NVARCHAR);
951951
info.addQueryParameter("parentCaseInstanceId", PARAMETER_TYPE_VARCHAR);
952+
info.addQueryParameter("parentProcessInstanceId", PARAMETER_TYPE_VARCHAR);
952953
info.addQueryParameter("startedBefore", PARAMETER_TYPE_TIMESTAMP);
953954
info.addQueryParameter("startedAfter", PARAMETER_TYPE_TIMESTAMP);
954955
info.addQueryParameter("startedBy", PARAMETER_TYPE_VARCHAR);
@@ -1064,6 +1065,7 @@ protected static void addHistoricCaseInstanceParams() {
10641065
info.addQueryParameter("rootScopeId", PARAMETER_TYPE_NVARCHAR);
10651066
info.addQueryParameter("rootScopeIdItem", PARAMETER_TYPE_NVARCHAR);
10661067
info.addQueryParameter("parentCaseInstanceId", PARAMETER_TYPE_VARCHAR);
1068+
info.addQueryParameter("parentProcessInstanceId", PARAMETER_TYPE_VARCHAR);
10671069
info.addQueryParameter("startedBefore", PARAMETER_TYPE_TIMESTAMP);
10681070
info.addQueryParameter("startedAfter", PARAMETER_TYPE_TIMESTAMP);
10691071
info.addQueryParameter("finishedBefore", PARAMETER_TYPE_TIMESTAMP);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<definitions xmlns="http://www.omg.org/spec/CMMN/20151109/MODEL"
3+
targetNamespace="http://flowable.org/cmmn">
4+
5+
<case id="caseWithProcessTask">
6+
<casePlanModel id="myPlanModel" name="My CasePlanModel">
7+
<planItem id="planItem1" definitionRef="theProcess" />
8+
<processTask id="theProcess" processRef="oneTaskProcess" isBlocking="true" />
9+
</casePlanModel>
10+
</case>
11+
12+
</definitions>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
3+
xmlns:flowable="http://flowable.org/bpmn"
4+
targetNamespace="http://flowable.org/bpmn">
5+
6+
<process id="processWithCaseTask">
7+
<startEvent id="start" />
8+
<sequenceFlow id="flow1" sourceRef="start" targetRef="caseTask" />
9+
<serviceTask id="caseTask" flowable:type="case" flowable:caseDefinitionKey="oneHumanTaskCase" />
10+
<sequenceFlow id="flow2" sourceRef="caseTask" targetRef="end" />
11+
<endEvent id="end" />
12+
</process>
13+
14+
</definitions>

modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/api/history/HistoricCaseInstanceQuery.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,11 @@ public interface HistoricCaseInstanceQuery extends Query<HistoricCaseInstanceQue
287287
*/
288288
HistoricCaseInstanceQuery parentCaseInstanceId(String parentCaseInstanceId);
289289

290+
/**
291+
* Only select historic case instances that have the given parent process instance id.
292+
*/
293+
HistoricCaseInstanceQuery parentProcessInstanceId(String parentProcessInstanceId);
294+
290295
/**
291296
* Only select historic case instances that do not have a callback identifier.
292297
*/

modules/flowable-cmmn-api/src/main/java/org/flowable/cmmn/api/runtime/CaseInstanceQuery.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ public interface CaseInstanceQuery extends Query<CaseInstanceQuery, CaseInstance
6666
CaseInstanceQuery caseInstanceCallbackIds(Set<String> callbackIds);
6767
CaseInstanceQuery caseInstanceCallbackType(String callbackType);
6868
CaseInstanceQuery parentCaseInstanceId(String parentCaseInstanceId);
69+
CaseInstanceQuery parentProcessInstanceId(String parentProcessInstanceId);
6970
CaseInstanceQuery caseInstanceReferenceId(String referenceId);
7071
CaseInstanceQuery caseInstanceReferenceType(String referenceType);
7172
CaseInstanceQuery caseInstanceIsCompleteable();

modules/flowable-cmmn-engine-configurator/src/test/java/org/flowable/cmmn/test/CaseTaskTest.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
import org.assertj.core.groups.Tuple;
2929
import org.flowable.cmmn.api.CallbackTypes;
30+
import org.flowable.cmmn.api.history.HistoricCaseInstance;
3031
import org.flowable.cmmn.api.runtime.CaseInstance;
3132
import org.flowable.cmmn.engine.test.CmmnDeployment;
3233
import org.flowable.common.engine.api.FlowableException;
@@ -1543,4 +1544,63 @@ public Void execute(CommandContext commandContext) {
15431544
}
15441545
}
15451546

1547+
@Test
1548+
@CmmnDeployment(resources = "org/flowable/cmmn/test/CaseTaskTest.testCaseTask.cmmn")
1549+
public void testParentProcessInstanceIdQuery() {
1550+
Deployment deployment = processEngineRepositoryService.createDeployment()
1551+
.addClasspathResource("org/flowable/cmmn/test/caseTaskProcess.bpmn20.xml")
1552+
.deploy();
1553+
1554+
try {
1555+
ProcessInstance processInstance = processEngineRuntimeService.startProcessInstanceByKey("caseTask");
1556+
List<Task> processTasks = processEngineTaskService.createTaskQuery().processInstanceId(processInstance.getId()).list();
1557+
assertThat(processTasks).hasSize(1);
1558+
1559+
processEngineTaskService.complete(processTasks.get(0).getId());
1560+
1561+
CaseInstance caseInstance = cmmnRuntimeService.createCaseInstanceQuery()
1562+
.parentProcessInstanceId(processInstance.getId())
1563+
.singleResult();
1564+
assertThat(caseInstance).isNotNull();
1565+
assertThat(caseInstance.getCallbackType()).isEqualTo(CallbackTypes.EXECUTION_CHILD_CASE);
1566+
1567+
assertThat(cmmnRuntimeService.createCaseInstanceQuery()
1568+
.parentProcessInstanceId("nonExistingId")
1569+
.count()).isZero();
1570+
1571+
HistoricCaseInstance historicCaseInstance = cmmnHistoryService.createHistoricCaseInstanceQuery()
1572+
.parentProcessInstanceId(processInstance.getId())
1573+
.singleResult();
1574+
assertThat(historicCaseInstance).isNotNull();
1575+
assertThat(historicCaseInstance.getId()).isEqualTo(caseInstance.getId());
1576+
1577+
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery()
1578+
.parentProcessInstanceId("nonExistingId")
1579+
.count()).isZero();
1580+
1581+
List<Task> caseTasks = cmmnTaskService.createTaskQuery().caseInstanceId(caseInstance.getId()).list();
1582+
assertThat(caseTasks).hasSize(1);
1583+
cmmnTaskService.complete(caseTasks.get(0).getId());
1584+
1585+
assertThat(cmmnRuntimeService.createCaseInstanceQuery()
1586+
.parentProcessInstanceId(processInstance.getId())
1587+
.count()).isZero();
1588+
1589+
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery()
1590+
.parentProcessInstanceId(processInstance.getId())
1591+
.singleResult()).isNotNull();
1592+
1593+
processTasks = processEngineTaskService.createTaskQuery().processInstanceId(processInstance.getId()).list();
1594+
assertThat(processTasks).hasSize(1);
1595+
processEngineTaskService.complete(processTasks.get(0).getId());
1596+
1597+
assertThat(cmmnHistoryService.createHistoricCaseInstanceQuery()
1598+
.parentProcessInstanceId(processInstance.getId())
1599+
.singleResult()).isNotNull();
1600+
1601+
} finally {
1602+
processEngineRepositoryService.deleteDeployment(deployment.getId(), true);
1603+
}
1604+
}
1605+
15461606
}

modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/history/HistoricCaseInstanceQueryImpl.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public class HistoricCaseInstanceQueryImpl extends AbstractVariableQueryImpl<His
104104
protected String callbackId;
105105
protected String callbackType;
106106
protected String parentCaseInstanceId;
107+
protected String parentProcessInstanceId;
107108
protected boolean withoutCallbackId;
108109
protected String referenceId;
109110
protected String referenceType;
@@ -776,6 +777,19 @@ public HistoricCaseInstanceQuery parentCaseInstanceId(String parentCaseInstanceI
776777
return this;
777778
}
778779

780+
@Override
781+
public HistoricCaseInstanceQuery parentProcessInstanceId(String parentProcessInstanceId) {
782+
if (parentProcessInstanceId == null) {
783+
throw new FlowableIllegalArgumentException("parentProcessInstanceId is null");
784+
}
785+
if (inOrStatement) {
786+
this.currentOrQueryObject.parentProcessInstanceId = parentProcessInstanceId;
787+
} else {
788+
this.parentProcessInstanceId = parentProcessInstanceId;
789+
}
790+
return this;
791+
}
792+
779793
@Override
780794
public HistoricCaseInstanceQuery withoutCaseInstanceCallbackId() {
781795
if (inOrStatement) {
@@ -1477,6 +1491,10 @@ public String getParentCaseInstanceId() {
14771491
return parentCaseInstanceId;
14781492
}
14791493

1494+
public String getParentProcessInstanceId() {
1495+
return parentProcessInstanceId;
1496+
}
1497+
14801498
public boolean isWithoutCallbackId() {
14811499
return withoutCallbackId;
14821500
}

modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/runtime/CaseInstanceQueryImpl.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public class CaseInstanceQueryImpl extends AbstractVariableQueryImpl<CaseInstanc
8989
protected Set<String> callbackIds;
9090
protected String callbackType;
9191
protected String parentCaseInstanceId;
92+
protected String parentProcessInstanceId;
9293
protected String referenceId;
9394
protected String referenceType;
9495
protected boolean completeable;
@@ -680,6 +681,19 @@ public CaseInstanceQuery parentCaseInstanceId(String parentCaseInstanceId) {
680681
return this;
681682
}
682683

684+
@Override
685+
public CaseInstanceQuery parentProcessInstanceId(String parentProcessInstanceId) {
686+
if (parentProcessInstanceId == null) {
687+
throw new FlowableIllegalArgumentException("parentProcessInstanceId is null");
688+
}
689+
if (inOrStatement) {
690+
this.currentOrQueryObject.parentProcessInstanceId = parentProcessInstanceId;
691+
} else {
692+
this.parentProcessInstanceId = parentProcessInstanceId;
693+
}
694+
return this;
695+
}
696+
683697
@Override
684698
public CaseInstanceQuery caseInstanceReferenceId(String referenceId) {
685699
if (referenceId == null) {
@@ -1295,6 +1309,10 @@ public String getParentCaseInstanceId() {
12951309
return parentCaseInstanceId;
12961310
}
12971311

1312+
public String getParentProcessInstanceId() {
1313+
return parentProcessInstanceId;
1314+
}
1315+
12981316
public String getReferenceId() {
12991317
return referenceId;
13001318
}

0 commit comments

Comments
 (0)