Skip to content

Commit 900eeab

Browse files
committed
MODWRKFLOW-72: Properly handle when workflow engine does not have a workflow to deactivate on workflow delete.
Call the history from the engine and if there is no history, then the workflow is not activated.
1 parent b995534 commit 900eeab

2 files changed

Lines changed: 91 additions & 15 deletions

File tree

service/src/main/java/org/folio/rest/workflow/service/WorkflowEngineService.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ public class WorkflowEngineService {
3232
private static final String WORKFLOW_ENGINE_ACTIVATE_URL_TEMPLATE = "%s%s/workflow-engine/workflows/activate";
3333
private static final String WORKFLOW_ENGINE_DEACTIVATE_URL_TEMPLATE = "%s%s/workflow-engine/workflows/deactivate";
3434

35+
private static final String PROCESS_DEFINITION_SORTED_URL_TEMPLATE = "%s%s/processDefinitionId=%s&sortBy=startTime&sortOrder=asc";
3536
private static final String PROCESS_DEFINITION_START_URL_TEMPLATE = "%s%s/process-definition/%s/start";
3637
private static final String PROCESS_DEFINITION_GET_URL_TEMPLATE = "%s%s/process-definition%s";
3738

@@ -93,10 +94,14 @@ public Workflow deactivate(String workflowId, String tenant, String token)
9394
public void delete(String workflowId, String tenant, String token)
9495
throws WorkflowEngineServiceException {
9596

96-
try {
97-
deactivate(workflowId, tenant, token);
98-
} catch (WorkflowEngineServiceException e) {
99-
throw new WorkflowEngineServiceException(String.format("Failed to delete Workflow '%s' due to deactivation failure: %s!", workflowId, e.getMessage()), e);
97+
final ArrayNode node = fetchProcessInstanceHistory(workflowId, tenant, token);
98+
99+
if (!node.isEmpty()) {
100+
try {
101+
deactivate(workflowId, tenant, token);
102+
} catch (WorkflowEngineServiceException e) {
103+
throw new WorkflowEngineServiceException(String.format("Failed to delete Workflow '%s' due to deactivation failure: %s!", workflowId, e.getMessage()), e);
104+
}
100105
}
101106

102107
workflowRepo.deleteById(workflowId);
@@ -187,7 +192,7 @@ private ArrayNode fetchProcessInstanceHistory(String processDefinitionId, String
187192

188193
HttpEntity<Void> httpEntity = new HttpEntity<>(headers(tenant, token));
189194

190-
String arguments = String.format("?processDefinitionId=%s&sortBy=startTime&sortOrder=asc", processDefinitionId);
195+
String arguments = String.format(PROCESS_DEFINITION_SORTED_URL_TEMPLATE, okapiUrl, restPath, processDefinitionId);
191196
String url = String.format(HISTORY_PROCESS_INSTANCE_URL_TEMPLATE, okapiUrl, restPath, arguments);
192197

193198
try {

service/src/test/java/org/folio/rest/workflow/service/WorkflowEngineServiceTest.java

Lines changed: 81 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import static org.junit.jupiter.api.Assertions.assertThrows;
1010
import static org.mockito.ArgumentMatchers.any;
1111
import static org.mockito.ArgumentMatchers.anyString;
12+
import static org.mockito.ArgumentMatchers.contains;
1213
import static org.mockito.Mockito.doAnswer;
1314
import static org.mockito.Mockito.doNothing;
1415
import static org.mockito.Mockito.never;
@@ -40,12 +41,16 @@
4041
import tools.jackson.databind.JsonNode;
4142
import tools.jackson.databind.json.JsonMapper;
4243
import tools.jackson.databind.node.ArrayNode;
44+
import tools.jackson.databind.node.JsonNodeFactory;
4345
import tools.jackson.databind.node.ObjectNode;
4446

4547
@ExtendWith(SpringExtension.class)
4648
@ExtendWith(MockitoExtension.class)
4749
class WorkflowEngineServiceTest {
4850

51+
private static final String PROCESS_DEFINITION_ID = "processDefinitionId=";
52+
private static final String DEACTIVATE = "workflow-engine/workflows/deactivate";
53+
4954
@Mock
5055
private WorkflowRepo workflowRepo;
5156

@@ -132,12 +137,20 @@ void deactivateWorksTest() throws WorkflowEngineServiceException {
132137

133138
@Test
134139
void deleteWorksTest() throws WorkflowEngineServiceException {
135-
WorkflowDto workflowDto = (WorkflowDto) workflow;
140+
141+
// The array node value is not expected to be processed beyond that the array is empty or not.
142+
ArrayNode arrayNodeSingle = JsonNodeFactory.instance.arrayNode();
143+
arrayNodeSingle.add("");
144+
145+
ResponseEntity<ArrayNode> responseArray = new ResponseEntity<>(arrayNodeSingle, HttpStatus.OK);
136146
ResponseEntity<Workflow> responseEntity = new ResponseEntity<>(HttpStatus.OK);
147+
148+
WorkflowDto workflowDto = (WorkflowDto) workflow;
137149
setField(responseEntity, "body", workflow);
138150

139151
when(workflowRepo.getViewById(anyString(), ArgumentMatchers.<Class<WorkflowDto>>any())).thenReturn(workflowDto);
140-
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<Workflow>>any())).thenReturn(responseEntity);
152+
when(restTemplate.exchange(contains(PROCESS_DEFINITION_ID), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<ArrayNode>>any())).thenReturn(responseArray);
153+
when(restTemplate.exchange(contains(DEACTIVATE), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<Workflow>>any())).thenReturn(responseEntity);
141154
when(workflowRepo.save(any())).thenReturn(workflow);
142155
doNothing().when(workflowRepo).deleteById(anyString());
143156

@@ -147,14 +160,30 @@ void deleteWorksTest() throws WorkflowEngineServiceException {
147160
verify(workflowRepo).deleteById(anyString());
148161
}
149162

163+
@Test
164+
void deleteNotActiveWorksTest() throws WorkflowEngineServiceException {
165+
166+
// The array node value is not expected to be processed beyond that the array is empty or not.
167+
ArrayNode arrayNodeSingle = JsonNodeFactory.instance.arrayNode();
168+
169+
ResponseEntity<ArrayNode> responseArray = new ResponseEntity<>(arrayNodeSingle, HttpStatus.OK);
170+
171+
when(restTemplate.exchange(contains(PROCESS_DEFINITION_ID), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<ArrayNode>>any())).thenReturn(responseArray);
172+
doNothing().when(workflowRepo).deleteById(anyString());
173+
174+
workflowEngineService.delete(UUID, OKAPI_TENANT, OKAPI_TOKEN);
175+
176+
verify(workflowRepo).deleteById(anyString());
177+
}
178+
150179
@Test
151180
void deleteThrowsExceptionUnableGetUpdatedTest() {
152-
WorkflowDto workflowDto = (WorkflowDto) workflow;
181+
153182
ResponseEntity<Workflow> responseEntity = new ResponseEntity<>(HttpStatus.ACCEPTED);
183+
154184
setField(responseEntity, "body", workflow);
155185

156-
when(workflowRepo.getViewById(anyString(), ArgumentMatchers.<Class<WorkflowDto>>any())).thenReturn(workflowDto);
157-
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<Workflow>>any())).thenReturn(responseEntity);
186+
when(restTemplate.exchange(contains(DEACTIVATE), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<Workflow>>any())).thenReturn(responseEntity);
158187

159188
assertThrows(WorkflowEngineServiceException.class, () ->
160189
workflowEngineService.delete(UUID, OKAPI_TENANT, OKAPI_TOKEN)
@@ -166,12 +195,20 @@ void deleteThrowsExceptionUnableGetUpdatedTest() {
166195

167196
@Test
168197
void deleteThrowsExceptionFailedToSaveTest() {
169-
WorkflowDto workflowDto = (WorkflowDto) workflow;
198+
199+
// The array node value is not expected to be processed beyond that the array is empty or not.
200+
ArrayNode arrayNodeSingle = JsonNodeFactory.instance.arrayNode();
201+
arrayNodeSingle.add("");
202+
203+
ResponseEntity<ArrayNode> responseArray = new ResponseEntity<>(arrayNodeSingle, HttpStatus.OK);
170204
ResponseEntity<Workflow> responseEntity = new ResponseEntity<>(HttpStatus.OK);
205+
206+
WorkflowDto workflowDto = (WorkflowDto) workflow;
171207
setField(responseEntity, "body", workflow);
172208

173209
when(workflowRepo.getViewById(anyString(), ArgumentMatchers.<Class<WorkflowDto>>any())).thenReturn(workflowDto);
174-
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<Workflow>>any())).thenReturn(responseEntity);
210+
when(restTemplate.exchange(contains(PROCESS_DEFINITION_ID), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<ArrayNode>>any())).thenReturn(responseArray);
211+
when(restTemplate.exchange(contains(DEACTIVATE), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<Workflow>>any())).thenReturn(responseEntity);
175212
when(workflowRepo.save(any())).thenThrow(new RuntimeException("Trigger Failure"));
176213

177214
assertThrows(WorkflowEngineServiceException.class, () -> {
@@ -184,12 +221,12 @@ void deleteThrowsExceptionFailedToSaveTest() {
184221

185222
@Test
186223
void deleteThrowsExceptionFailedToSendWithNullResponseBodyTest() {
187-
WorkflowDto workflowDto = (WorkflowDto) workflow;
224+
188225
ResponseEntity<Workflow> responseEntity = new ResponseEntity<>(HttpStatus.OK);
226+
189227
setField(responseEntity, "body", null);
190228

191-
when(workflowRepo.getViewById(anyString(), ArgumentMatchers.<Class<WorkflowDto>>any())).thenReturn(workflowDto);
192-
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<Workflow>>any())).thenReturn(responseEntity);
229+
when(restTemplate.exchange(contains(DEACTIVATE), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<Workflow>>any())).thenReturn(responseEntity);
193230

194231
assertThrows(WorkflowEngineServiceException.class, () -> {
195232
workflowEngineService.delete(UUID, OKAPI_TENANT, OKAPI_TOKEN);
@@ -338,6 +375,40 @@ void historyWorksTest() throws WorkflowEngineServiceException {
338375
assertEquals(historyArrayNode, response);
339376
}
340377

378+
@Test
379+
void historyWorksWithoutOkFetchingIncidentsHistoryTest() throws WorkflowEngineServiceException {
380+
381+
WorkflowOperationalDto workflowOperationalDto = (WorkflowOperationalDto) workflowOperational;
382+
383+
ResponseEntity<ArrayNode> deploymentEntity = new ResponseEntity<>(HttpStatus.OK);
384+
ResponseEntity<ArrayNode> processEntity = new ResponseEntity<>(HttpStatus.OK);
385+
ResponseEntity<ArrayNode> incidentsEntity = new ResponseEntity<>(HttpStatus.FOUND);
386+
387+
ObjectNode deploymentNode = mapper.createObjectNode();
388+
deploymentNode.put("id", UUID);
389+
390+
ObjectNode processNode = mapper.createObjectNode();
391+
processNode.put("id", UUID);
392+
393+
ArrayNode deploymentArrayNode = mapper.createArrayNode();
394+
deploymentArrayNode.add(deploymentNode);
395+
setField(deploymentEntity, "body", deploymentArrayNode);
396+
397+
ArrayNode processArrayNode = mapper.createArrayNode();
398+
processArrayNode.add(processNode);
399+
setField(processEntity, "body", processArrayNode);
400+
401+
ArrayNode incidentsArrayNode = mapper.createArrayNode();
402+
setField(incidentsEntity, "body", incidentsArrayNode);
403+
404+
when(workflowRepo.getViewById(anyString(), ArgumentMatchers.<Class<WorkflowOperationalDto>>any())).thenReturn(workflowOperationalDto);
405+
when(restTemplate.exchange(anyString(), any(HttpMethod.class), any(HttpEntity.class), ArgumentMatchers.<Class<ArrayNode>>any()))
406+
.thenReturn(processEntity, processEntity, incidentsEntity);
407+
408+
JsonNode response = workflowEngineService.history(UUID, OKAPI_TENANT, OKAPI_TOKEN);
409+
assertEquals(processArrayNode, response);
410+
}
411+
341412
@Test
342413
void historyThrowsExceptionWithNotOkHttpStatusForProcessTest() {
343414
WorkflowOperationalDto workflowOperationalDto = (WorkflowOperationalDto) workflowOperational;

0 commit comments

Comments
 (0)