Skip to content

Commit a74447c

Browse files
authored
Throw more specific FlowableIllegalArgumentException for invalid state during dynamic state changes (#4182)
1 parent aa0477d commit a74447c

5 files changed

Lines changed: 78 additions & 9 deletions

File tree

modules/flowable-engine/src/main/java/org/flowable/engine/impl/dynamic/AbstractDynamicStateManager.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import org.flowable.bpmn.model.ValuedDataObject;
5757
import org.flowable.common.engine.api.FlowableException;
5858
import org.flowable.common.engine.impl.el.DefinitionVariableContainer;
59+
import org.flowable.common.engine.api.FlowableIllegalArgumentException;
5960
import org.flowable.common.engine.api.delegate.Expression;
6061
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
6162
import org.flowable.common.engine.api.delegate.event.FlowableEventDispatcher;
@@ -325,7 +326,7 @@ protected List<ExecutionEntity> resolveActiveExecutions(String processInstanceId
325326
.collect(Collectors.toList());
326327

327328
if (executions.isEmpty()) {
328-
throw new FlowableException("Active execution could not be found with activity id " + activityId);
329+
throw new FlowableIllegalArgumentException("Active execution could not be found with activity id " + activityId);
329330
}
330331

331332
return executions;
@@ -447,7 +448,7 @@ protected void prepareMoveExecutionEntityContainer(MoveExecutionEntityContainer
447448
protected FlowElement resolveFlowElementFromBpmnModel(BpmnModel bpmnModel, String activityId) {
448449
FlowElement flowElement = bpmnModel.getFlowElement(activityId);
449450
if (flowElement == null) {
450-
throw new FlowableException("Cannot find activity '" + activityId + "' in process definition with id '" + bpmnModel.getMainProcess().getId() + "'");
451+
throw new FlowableIllegalArgumentException("Cannot find activity '" + activityId + "' in process definition with id '" + bpmnModel.getMainProcess().getId() + "'");
451452
}
452453
return flowElement;
453454
}

modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/changestate/ChangeStateForCallActivityTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.List;
2121

2222
import org.flowable.common.engine.api.FlowableException;
23+
import org.flowable.common.engine.api.FlowableIllegalArgumentException;
2324
import org.flowable.common.engine.api.scope.ScopeTypes;
2425
import org.flowable.common.engine.impl.history.HistoryLevel;
2526
import org.flowable.engine.impl.test.HistoryTestHelper;
@@ -355,15 +356,15 @@ public void testSetCurrentActivityInSubProcessInstanceSpecificVersion() {
355356
.processInstanceId(processInstance.getId())
356357
.moveActivityIdToSubProcessInstanceActivityId("firstTask", "theTask", "callActivity")
357358
.changeState())
358-
.isExactlyInstanceOf(FlowableException.class)
359+
.isExactlyInstanceOf(FlowableIllegalArgumentException.class)
359360
.hasMessage("Cannot find activity 'theTask' in process definition with id 'oneTaskProcess'");
360-
361+
361362
//Invalid "unExistent" process definition version
362363
assertThatThrownBy(() -> runtimeService.createChangeActivityStateBuilder()
363364
.processInstanceId(processInstance.getId())
364365
.moveActivityIdToSubProcessInstanceActivityId("firstTask", "theTask", "callActivity", 5)
365366
.changeState())
366-
.isExactlyInstanceOf(FlowableException.class)
367+
.isExactlyInstanceOf(FlowableIllegalArgumentException.class)
367368
.hasMessage("Cannot find activity 'theTask' in process definition with id 'oneTaskProcess'");
368369

369370
//Change state specifying the first version

modules/flowable-engine/src/test/java/org/flowable/engine/test/api/runtime/migration/ProcessInstanceMigrationCallActivityTest.java

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

2828
import org.assertj.core.api.Condition;
2929
import org.flowable.common.engine.api.FlowableException;
30+
import org.flowable.common.engine.api.FlowableIllegalArgumentException;
3031
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
3132
import org.flowable.engine.impl.test.PluggableFlowableTestCase;
3233
import org.flowable.engine.migration.ActivityMigrationMapping;
@@ -274,7 +275,7 @@ public void testValidationOfInvalidActivityInMigrationMappingToCallActivitySubPr
274275
"Invalid mapping for 'userTask1Id' to 'wrongActivityId', cannot be found in the process definition with id 'oneTaskProcess'"));
275276

276277
assertThatThrownBy(() -> processInstanceMigrationBuilder.migrate(processInstance.getId()))
277-
.isExactlyInstanceOf(FlowableException.class)
278+
.isExactlyInstanceOf(FlowableIllegalArgumentException.class)
278279
.hasMessage("Cannot find activity 'wrongActivityId' in process definition with id 'oneTaskProcess'");
279280

280281
completeProcessInstanceTasks(processInstance.getId());
@@ -318,7 +319,7 @@ public void testValidationOfInvalidCallActivityInMigrateMappingToCallActivitySub
318319
"There's no call activity element with id 'wrongCallActivity' in the process definition with id 'twoTasksParentProcess'"));
319320

320321
assertThatThrownBy(() -> processInstanceMigrationBuilder.migrate(processInstance.getId()))
321-
.isExactlyInstanceOf(FlowableException.class)
322+
.isExactlyInstanceOf(FlowableIllegalArgumentException.class)
322323
.hasMessage("Cannot find activity 'wrongCallActivity' in process definition with id 'twoTasksParentProcess'");
323324

324325
completeProcessInstanceTasks(processInstance.getId());
@@ -357,7 +358,7 @@ public void testMigrateMovingActivityIntoCallActivitySubProcessSpecificVersion()
357358
.isEqualTo(Collections.singletonList("Invalid mapping for 'theTask' to 'userTask1Id', cannot be found in the process definition with id 'MP'"));
358359

359360
assertThatThrownBy(() -> processInstanceMigrationBuilder.migrate(processInstance.getId()))
360-
.isExactlyInstanceOf(FlowableException.class)
361+
.isExactlyInstanceOf(FlowableIllegalArgumentException.class)
361362
.hasMessage("Cannot find activity 'userTask1Id' in process definition with id 'MP'");
362363

363364
//Second migration attempt using and invalid "unExistent" version
@@ -371,7 +372,7 @@ public void testMigrateMovingActivityIntoCallActivitySubProcessSpecificVersion()
371372
.isEqualTo(Collections.singletonList("Invalid mapping for 'theTask' to 'userTask1Id', cannot be found in the process definition with id 'MP'"));
372373

373374
assertThatThrownBy(() -> processInstanceMigrationBuilder2.migrate(processInstance.getId()))
374-
.isExactlyInstanceOf(FlowableException.class)
375+
.isExactlyInstanceOf(FlowableIllegalArgumentException.class)
375376
.hasMessage("Cannot find activity 'userTask1Id' in process definition with id 'MP'");
376377

377378
//Second migration attempt specifies the version of the call activity subProcess

modules/flowable-rest/src/test/java/org/flowable/rest/service/api/runtime/ExecutionResourceTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.apache.http.HttpStatus;
2323
import org.apache.http.client.methods.CloseableHttpResponse;
2424
import org.apache.http.client.methods.HttpGet;
25+
import org.apache.http.client.methods.HttpPost;
2526
import org.apache.http.client.methods.HttpPut;
2627
import org.apache.http.entity.StringEntity;
2728
import org.flowable.engine.runtime.Execution;
@@ -308,4 +309,21 @@ public void testIllegalExecutionAction() throws Exception {
308309
CloseableHttpResponse response = executeRequest(httpPut, HttpStatus.SC_BAD_REQUEST);
309310
closeResponse(response);
310311
}
312+
313+
@Test
314+
@Deployment(resources = { "org/flowable/rest/service/api/runtime/ExecutionResourceTest.process-with-subprocess.bpmn20.xml" })
315+
public void testChangeExecutionActivityStateWithInvalidStartActivity() throws Exception {
316+
runtimeService.startProcessInstanceByKey("processOne");
317+
Execution execution = runtimeService.createExecutionQuery().activityId("processTask").singleResult();
318+
assertThat(execution).isNotNull();
319+
320+
ObjectNode requestNode = objectMapper.createObjectNode();
321+
ArrayNode startActivityArray = requestNode.putArray("startActivityIds");
322+
startActivityArray.add("doesNotExist");
323+
324+
HttpPost httpPost = new HttpPost(SERVER_URL_PREFIX + RestUrls.createRelativeResourceUrl(RestUrls.URL_EXECUTION, execution.getId()) + "/change-state");
325+
httpPost.setEntity(new StringEntity(requestNode.toString()));
326+
CloseableHttpResponse response = executeRequest(httpPost, HttpStatus.SC_BAD_REQUEST);
327+
closeResponse(response);
328+
}
311329
}

modules/flowable-rest/src/test/java/org/flowable/rest/service/api/runtime/ProcessInstanceChangeActivityStateResourceTest.java

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,4 +143,52 @@ public void testChangeActivityStateManyToOneWithMI() throws Exception {
143143

144144
assertProcessEnded(processInstance.getId());
145145
}
146+
147+
@Test
148+
@Deployment(resources = { "org/flowable/rest/service/api/runtime/parallelTask.bpmn20.xml" })
149+
public void testChangeActivityStateManyToOneWithInvalidStartActivity() throws Exception {
150+
Authentication.setAuthenticatedUserId("testUser");
151+
ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder()
152+
.processDefinitionKey("startParallelProcess")
153+
.start();
154+
Task task = taskService.createTaskQuery().processInstanceId(processInstance.getId()).singleResult();
155+
taskService.complete(task.getId());
156+
Authentication.setAuthenticatedUserId(null);
157+
158+
ObjectNode requestNode = objectMapper.createObjectNode();
159+
ArrayNode cancelActivityArray = requestNode.putArray("cancelActivityIds");
160+
cancelActivityArray.add("task1");
161+
cancelActivityArray.add("task2");
162+
163+
ArrayNode startActivityArray = requestNode.putArray("startActivityIds");
164+
startActivityArray.add("doesNotExist");
165+
166+
HttpPost httpPost = new HttpPost(buildUrl(RestUrls.URL_PROCESS_INSTANCE_CHANGE_STATE, processInstance.getId()));
167+
httpPost.setEntity(new StringEntity(requestNode.toString()));
168+
CloseableHttpResponse response = executeRequest(httpPost, HttpStatus.SC_BAD_REQUEST);
169+
closeResponse(response);
170+
}
171+
172+
@Test
173+
@Deployment(resources = { "org/flowable/rest/service/api/runtime/parallelTask.bpmn20.xml" })
174+
public void testChangeActivityStateOneToManyWithInvalidCancelActivity() throws Exception {
175+
Authentication.setAuthenticatedUserId("testUser");
176+
ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder()
177+
.processDefinitionKey("startParallelProcess")
178+
.start();
179+
Authentication.setAuthenticatedUserId(null);
180+
181+
ObjectNode requestNode = objectMapper.createObjectNode();
182+
ArrayNode cancelActivityArray = requestNode.putArray("cancelActivityIds");
183+
cancelActivityArray.add("doesNotExist");
184+
185+
ArrayNode startActivityArray = requestNode.putArray("startActivityIds");
186+
startActivityArray.add("task1");
187+
startActivityArray.add("task2");
188+
189+
HttpPost httpPost = new HttpPost(buildUrl(RestUrls.URL_PROCESS_INSTANCE_CHANGE_STATE, processInstance.getId()));
190+
httpPost.setEntity(new StringEntity(requestNode.toString()));
191+
CloseableHttpResponse response = executeRequest(httpPost, HttpStatus.SC_BAD_REQUEST);
192+
closeResponse(response);
193+
}
146194
}

0 commit comments

Comments
 (0)