From d68d9e1b122693d1158bd7a6dd5957ce4009463a Mon Sep 17 00:00:00 2001 From: Aleksandar Zlatkovski Date: Fri, 16 Feb 2024 14:08:30 +0200 Subject: [PATCH 1/4] Feature#3335: Retry failed process step impl --- .../engine/bpm/flowable/dto/ActionData.java | 25 ++++++++++++++ .../endpoint/BpmFlowableEndpoint.java | 34 +++++++++++++++++++ .../provider/BpmProviderFlowable.java | 2 ++ .../src/main/resources/stencilset_bpmn.json | 4 +-- .../bpm-process-instances.html | 4 +++ .../js/bpm-process-instances.js | 23 +++++++++++++ 6 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/dto/ActionData.java diff --git a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/dto/ActionData.java b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/dto/ActionData.java new file mode 100644 index 00000000000..54f4642a358 --- /dev/null +++ b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/dto/ActionData.java @@ -0,0 +1,25 @@ +package org.eclipse.dirigible.components.engine.bpm.flowable.dto; + +public class ActionData { + + private String action; + + public String getAction() { + return action; + } + + public enum Action { + RETRY("RETRY"); + + private final String actionName; + + Action(String actionName) { + this.actionName = actionName; + } + + public String getActionName() { + return actionName; + } + + } +} diff --git a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java index e0f73423615..6945dc98304 100644 --- a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java +++ b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java @@ -11,6 +11,7 @@ package org.eclipse.dirigible.components.engine.bpm.flowable.endpoint; import static java.text.MessageFormat.format; +import static org.eclipse.dirigible.components.engine.bpm.flowable.dto.ActionData.Action.*; import java.io.IOException; import java.io.InputStream; @@ -19,6 +20,7 @@ import java.util.*; import org.apache.commons.io.IOUtils; import org.eclipse.dirigible.components.base.endpoint.BaseEndpoint; +import org.eclipse.dirigible.components.engine.bpm.flowable.dto.ActionData; import org.eclipse.dirigible.components.engine.bpm.flowable.dto.ProcessDefinitionData; import org.eclipse.dirigible.components.engine.bpm.flowable.dto.ProcessInstanceData; import org.eclipse.dirigible.components.engine.bpm.flowable.dto.VariableData; @@ -33,6 +35,7 @@ import org.flowable.engine.RuntimeService; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.image.ProcessDiagramGenerator; +import org.flowable.job.api.Job; import org.flowable.variable.api.persistence.entity.VariableInstance; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -279,6 +282,37 @@ public ResponseEntity addProcessInstanceVariables(@PathVariable("id") Stri .build(); } + @PostMapping(value = "/bpm-processes/instance/{id}") + public ResponseEntity executeAction(@PathVariable("id") String id, @RequestBody ActionData actionData) { + + if (RETRY.getActionName() + .equals(actionData.getAction())) { + BpmService bpmService = getBpmService(); + List jobs = bpmService.getBpmProviderFlowable() + .getProcessEngine() + .getManagementService() + .createDeadLetterJobQuery() + .processInstanceId(id) + .list(); + if (jobs.isEmpty()) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body("No dead letter jobs found for process instance id [" + id + "]"); + } + + bpmService.getBpmProviderFlowable() + .getProcessEngine() + .getManagementService() + .moveDeadLetterJobToExecutableJob(jobs.get(0) + .getId(), + 1); + return ResponseEntity.ok() + .build(); + } else { + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .body("Invalid action id provided [" + actionData.getAction() + "]"); + } + } + /** * Gets the process image. * diff --git a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/provider/BpmProviderFlowable.java b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/provider/BpmProviderFlowable.java index 70ffca8063d..1d7261cac2b 100644 --- a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/provider/BpmProviderFlowable.java +++ b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/provider/BpmProviderFlowable.java @@ -161,6 +161,8 @@ public ProcessEngine getProcessEngine() { cfg.setDatabaseSchemaUpdate(updateSchema ? ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE : ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE); + cfg.setAsyncExecutorActivate(true); + cfg.setAsyncFailedJobWaitTime(1); processEngine = cfg.buildProcessEngine(); if (logger.isInfoEnabled()) { logger.info("Done initializng the Flowable Process Engine."); diff --git a/components/engine/engine-bpm-flowable/src/main/resources/stencilset_bpmn.json b/components/engine/engine-bpm-flowable/src/main/resources/stencilset_bpmn.json index 4297ec0388e..5f95664a59e 100644 --- a/components/engine/engine-bpm-flowable/src/main/resources/stencilset_bpmn.json +++ b/components/engine/engine-bpm-flowable/src/main/resources/stencilset_bpmn.json @@ -109,7 +109,7 @@ "id" : "asynchronousdefinition", "type" : "Boolean", "title" : "Asynchronous", - "value" : "false", + "value" : "true", "description" : "Define the activity as asynchronous.", "popular" : true } ] @@ -129,7 +129,7 @@ "id" : "exclusivedefinition", "type" : "Boolean", "title" : "Exclusive", - "value" : "false", + "value" : "true", "description" : "Define the activity as exclusive.", "popular" : true } ] diff --git a/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/bpm-process-instances.html b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/bpm-process-instances.html index c38d7bf7d0a..466ac228f97 100644 --- a/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/bpm-process-instances.html +++ b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/bpm-process-instances.html @@ -36,6 +36,10 @@ glyph="sap-icon--search" title="Toggle search" aria-label="Toggle search" ng-click="instances.toggleSearch()"> + + + { + console.log('Successfully retried process instance with id [' + this.processInstanceId + ']'); + $scope.reload(); + }) + .catch((error) => { + console.error('Error making POST request:', error); + }); + } + this.selectAllChanged = function () { for (let instance of this.instancesList) { instance.selected = this.selectAll; @@ -74,6 +96,7 @@ ideBpmProcessInstancesView.controller('IDEBpmProcessInstancesViewController', [' messageHub.postMessage('diagram.instance', { instance: instance.id }); messageHub.postMessage('instance.selected', { instance: instance.id }); instance.selected = true; + this.selectedProcessInstanceId = instance.id; } From e8e40dbb188f3089dfd7feea27a25c50ecafd23e Mon Sep 17 00:00:00 2001 From: Aleksandar Zlatkovski Date: Thu, 22 Feb 2024 15:10:58 +0200 Subject: [PATCH 2/4] Feature#3335: Remove small waiting time used for testing --- .../engine/bpm/flowable/provider/BpmProviderFlowable.java | 1 - 1 file changed, 1 deletion(-) diff --git a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/provider/BpmProviderFlowable.java b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/provider/BpmProviderFlowable.java index 1d7261cac2b..901ac835198 100644 --- a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/provider/BpmProviderFlowable.java +++ b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/provider/BpmProviderFlowable.java @@ -162,7 +162,6 @@ public ProcessEngine getProcessEngine() { : ProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE); cfg.setAsyncExecutorActivate(true); - cfg.setAsyncFailedJobWaitTime(1); processEngine = cfg.buildProcessEngine(); if (logger.isInfoEnabled()) { logger.info("Done initializng the Flowable Process Engine."); From c09f05738eba5dc5050d2386b2f1427c2a9ab5a9 Mon Sep 17 00:00:00 2001 From: Aleksandar Zlatkovski Date: Thu, 22 Feb 2024 16:25:35 +0200 Subject: [PATCH 3/4] Feature#3335: Introduce dead-letter job view --- .../endpoint/BpmFlowableEndpoint.java | 14 ++++++ .../ide-bpm-workspace/bpm-process-jobs.html | 48 +++++++++++++++++++ .../bpm-process-jobs-view.extension | 5 ++ .../ide-bpm-workspace/js/bpm-perspective.js | 3 +- .../ide-bpm-workspace/js/bpm-process-jobs.js | 43 +++++++++++++++++ .../services/bpm-process-jobs-view.js | 23 +++++++++ 6 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/bpm-process-jobs.html create mode 100644 components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/extensions/bpm-process-jobs-view.extension create mode 100644 components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/js/bpm-process-jobs.js create mode 100644 components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/services/bpm-process-jobs-view.js diff --git a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java index 6945dc98304..dfa57ed36db 100644 --- a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java +++ b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java @@ -313,6 +313,20 @@ public ResponseEntity executeAction(@PathVariable("id") String id, @Requ } } + @GetMapping(value = "/bpm-processes/instance/{id}/jobs") + public ResponseEntity> getDeadLetterJobs(@PathVariable("id") String id) { + + BpmService bpmService = getBpmService(); + List jobs = bpmService.getBpmProviderFlowable() + .getProcessEngine() + .getManagementService() + .createDeadLetterJobQuery() + .processInstanceId(id) + .list(); + + return ResponseEntity.ok(jobs); + } + /** * Gets the process image. * diff --git a/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/bpm-process-jobs.html b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/bpm-process-jobs.html new file mode 100644 index 00000000000..2adf1bd32fa --- /dev/null +++ b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/bpm-process-jobs.html @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
IdProcess Instance IdExecution IdException messageStacktrace
{{next.id}}{{next.processInstanceId}}{{next.executionId}}{{next.exceptionMessage}}{{next.exceptionStacktrace}}
{{getNoDataMessage()}}
+
+ + diff --git a/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/extensions/bpm-process-jobs-view.extension b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/extensions/bpm-process-jobs-view.extension new file mode 100644 index 00000000000..9dbe86e8c6d --- /dev/null +++ b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/extensions/bpm-process-jobs-view.extension @@ -0,0 +1,5 @@ +{ + "module": "ide-bpm-workspace/services/bpm-process-jobs-view.js", + "extensionPoint": "ide-view", + "description": "Business Process Jobs" +} \ No newline at end of file diff --git a/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/js/bpm-perspective.js b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/js/bpm-perspective.js index 23ee67f3178..92e9537e54e 100644 --- a/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/js/bpm-perspective.js +++ b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/js/bpm-perspective.js @@ -17,11 +17,12 @@ IDEBPMWorkspacePerspective.config(["messageHubProvider", function (messageHubPro IDEBPMWorkspacePerspective.controller("BpmWorkspaceViewController", ["$scope", function ($scope) { $scope.layoutModel = { - views: ["bpm-process-definitions-view", "bpm-process-instances-view", "bpm-process-context-view", "bpm-image-viewer", "bpm-user-tasks"], + views: ["bpm-process-definitions-view", "bpm-process-instances-view", "bpm-process-context-view", "bpm-process-jobs-view", "bpm-image-viewer", "bpm-user-tasks"], viewSettings: { "bpm-process-definitions-view": { expanded: true }, "bpm-process-instances-view": { expanded: true }, "bpm-process-context-view": { expanded: true }, + "bpm-process-jobs-view": { expanded: true }, "bpm-image-viewer": { closable: false }, }, layoutSettings: { diff --git a/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/js/bpm-process-jobs.js b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/js/bpm-process-jobs.js new file mode 100644 index 00000000000..92fb70a26c4 --- /dev/null +++ b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/js/bpm-process-jobs.js @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2023 SAP SE or an SAP affiliate company and Eclipse Dirigible contributors + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v20.html + * + * SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and Eclipse Dirigible contributors + * SPDX-License-Identifier: EPL-2.0 + */ +let ideBpmProcessJobsView = angular.module('ide-bpm-process-jobs', ['ideUI', 'ideView']); + +ideBpmProcessJobsView.config(["messageHubProvider", function (messageHubProvider) { + messageHubProvider.eventIdPrefix = 'bpm'; +}]); + +ideBpmProcessJobsView.controller('IDEBpmProcessJobsViewController', ['$scope', '$http', '$timeout', 'messageHub', function ($scope, $http, $timeout,messageHub,) { + + $scope.jobsList = []; + + $scope.reload = function () { + console.log("Reloading data for current process instance id: " + $scope.currentProcessInstanceId) + $scope.fetchData($scope.currentProcessInstanceId); + }; + + $scope.fetchData = function(processInstanceId) { + $http.get('/services/ide/bpm/bpm-processes/instance/' + processInstanceId + '/jobs', { params: { 'limit': 100 } }) + .then((response) => { + $scope.jobsList = response.data; + }); + } + + $scope.getNoDataMessage = function () { + return 'No jobs have been found.'; + } + + messageHub.onDidReceiveMessage('instance.selected', function (msg) { + const processInstanceId = msg.data.instance; + $scope.fetchData(processInstanceId); + }); + +}]); \ No newline at end of file diff --git a/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/services/bpm-process-jobs-view.js b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/services/bpm-process-jobs-view.js new file mode 100644 index 00000000000..b9f48aee7c1 --- /dev/null +++ b/components/ide/ide-ui-bpm-workspace/src/main/resources/META-INF/dirigible/ide-bpm-workspace/services/bpm-process-jobs-view.js @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2023 SAP SE or an SAP affiliate company and Eclipse Dirigible contributors + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v2.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v20.html + * + * SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and Eclipse Dirigible contributors + * SPDX-License-Identifier: EPL-2.0 + */ +const viewData = { + id: "bpm-process-jobs-view", + label: "Dead-Letter Jobs", + factory: "frame", + region: "bottom", + link: "../ide-bpm-workspace/bpm-process-jobs.html", +}; +if (typeof exports !== 'undefined') { + exports.getView = function () { + return viewData; + } +} \ No newline at end of file From ca2f2d3d3d0e5889393da3b2e7e4149f0be493da Mon Sep 17 00:00:00 2001 From: Aleksandar Zlatkovski Date: Sat, 24 Feb 2024 21:53:35 +0200 Subject: [PATCH 4/4] Feature#3335: Add javadoc and renaming --- .../endpoint/BpmFlowableEndpoint.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java index dfa57ed36db..7f750f12dc0 100644 --- a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java +++ b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/BpmFlowableEndpoint.java @@ -269,6 +269,11 @@ public ResponseEntity> getProcessInstanceVariables(@PathV return ResponseEntity.ok(variables); } + /** + * Add or update active process instance variable + * + * @param id the process instance id + */ @PostMapping(value = "/bpm-processes/instance/{id}/variables") public ResponseEntity addProcessInstanceVariables(@PathVariable("id") String id, @RequestBody VariableData variableData) { @@ -282,8 +287,14 @@ public ResponseEntity addProcessInstanceVariables(@PathVariable("id") Stri .build(); } + /** + * Execute action on active process instance variable + * + * @param id the process instance id + * @param actionData the action to be executed, possible values: RETRY + */ @PostMapping(value = "/bpm-processes/instance/{id}") - public ResponseEntity executeAction(@PathVariable("id") String id, @RequestBody ActionData actionData) { + public ResponseEntity executeProcessInstanceAction(@PathVariable("id") String id, @RequestBody ActionData actionData) { if (RETRY.getActionName() .equals(actionData.getAction())) { @@ -313,6 +324,12 @@ public ResponseEntity executeAction(@PathVariable("id") String id, @Requ } } + /** + * List dead-letter jobs for an active process instance variables. + * + * @param id the process instance id + * @return list of dead-letter jobs + */ @GetMapping(value = "/bpm-processes/instance/{id}/jobs") public ResponseEntity> getDeadLetterJobs(@PathVariable("id") String id) {