diff --git a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/delegate/DirigibleCallDelegate.java b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/delegate/DirigibleCallDelegate.java index 90b40f25e3d..ce2d5289db9 100644 --- a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/delegate/DirigibleCallDelegate.java +++ b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/delegate/DirigibleCallDelegate.java @@ -9,6 +9,7 @@ */ package org.eclipse.dirigible.components.engine.bpm.flowable.delegate; +import jakarta.annotation.Nullable; import org.eclipse.dirigible.commons.api.helpers.GsonHelper; import org.eclipse.dirigible.components.engine.bpm.flowable.dto.ExecutionData; import org.eclipse.dirigible.graalium.core.DirigibleJavascriptCodeRunner; @@ -21,7 +22,6 @@ import org.graalvm.polyglot.Value; import org.springframework.beans.BeanUtils; -import jakarta.annotation.Nullable; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; @@ -36,7 +36,7 @@ public class DirigibleCallDelegate implements JavaDelegate { /** The js expression regex. */ - private static Pattern JS_EXPRESSION_REGEX = Pattern.compile("(.*\\.m?js)(?:\\/(\\w*))?(?:\\/(\\w*))?"); + private static final Pattern JS_EXPRESSION_REGEX = Pattern.compile("(.*\\.(?:m?js|ts))(?:\\/(\\w*))?(?:\\/(\\w*))?"); /** * The handler. @@ -48,95 +48,6 @@ public class DirigibleCallDelegate implements JavaDelegate { */ private FixedValue type; - /** - * Getter for the handler attribute. - * - * @return the handler - */ - public FixedValue getHandler() { - return handler; - } - - /** - * Setter of the handler attribute. - * - * @param handler the handler - */ - public void setHandler(FixedValue handler) { - this.handler = handler; - } - - /** - * Getter for the engine attribute. - * - * @return the type - */ - public FixedValue getType() { - return type; - } - - /** - * Setter of the engine attribute. - * - * @param type the type - */ - public void setType(FixedValue type) { - this.type = type; - } - - /** - * Execute. - * - * @param execution the execution - */ - @Override - public void execute(DelegateExecution execution) { - - String action = (String) execution.getVariable(DIRIGIBLE_BPM_INTERNAL_SKIP_STEP); - if (SKIP.getActionName() - .equals(action)) { - execution.removeVariable(DIRIGIBLE_BPM_INTERNAL_SKIP_STEP); - return; - } - - Map context = new HashMap<>(); - ExecutionData executionData = new ExecutionData(); - BeanUtils.copyProperties(execution, executionData); - context.put("execution", GsonHelper.toJson(executionData)); - if (type == null) { - type = new FixedValue("javascript"); - } - if (handler == null) { - throw new BpmnError("Handler cannot be null at the call delegate."); - } - executeJSHandler(context); - } - - /** - * Execute JS handler. - * - * @param context the context - */ - private void executeJSHandler(Map context) { - RepositoryPath path = new RepositoryPath(handler.getExpressionText()); - JSTask task = JSTask.fromRepositoryPath(path); - - try (DirigibleJavascriptCodeRunner runner = new DirigibleJavascriptCodeRunner(context, false)) { - Source source = runner.prepareSource(task.getSourceFilePath()); - Value value = runner.run(source); - - if (task.hasExportedClassAndMethod()) { - value.getMember(task.getClassName()) - .newInstance() - .getMember(task.getMethodName()) - .executeVoid(); - } else if (task.hasExportedMethod()) { - value.getMember(task.getMethodName()) - .executeVoid(); - } - - } - } /** * The Class JSTask. @@ -182,7 +93,8 @@ static class JSTask { static JSTask fromRepositoryPath(RepositoryPath repositoryPath) { var matcher = JS_EXPRESSION_REGEX.matcher(repositoryPath.getPath()); if (!matcher.matches()) { - throw new BpmnError("Invalid JS expression provided for task!"); + throw new BpmnError("Invalid JS expression provided for task! Path [" + repositoryPath.getPath() + "] doesn't match " + + JS_EXPRESSION_REGEX); } String maybeClassName; @@ -246,4 +158,94 @@ public boolean hasExportedMethod() { } } + /** + * Getter for the handler attribute. + * + * @return the handler + */ + public FixedValue getHandler() { + return handler; + } + + /** + * Setter of the handler attribute. + * + * @param handler the handler + */ + public void setHandler(FixedValue handler) { + this.handler = handler; + } + + /** + * Getter for the engine attribute. + * + * @return the type + */ + public FixedValue getType() { + return type; + } + + /** + * Setter of the engine attribute. + * + * @param type the type + */ + public void setType(FixedValue type) { + this.type = type; + } + + /** + * Execute. + * + * @param execution the execution + */ + @Override + public void execute(DelegateExecution execution) { + + String action = (String) execution.getVariable(DIRIGIBLE_BPM_INTERNAL_SKIP_STEP); + if (SKIP.getActionName() + .equals(action)) { + execution.removeVariable(DIRIGIBLE_BPM_INTERNAL_SKIP_STEP); + return; + } + + Map context = new HashMap<>(); + ExecutionData executionData = new ExecutionData(); + BeanUtils.copyProperties(execution, executionData); + context.put("execution", GsonHelper.toJson(executionData)); + if (type == null) { + type = new FixedValue("javascript"); + } + if (handler == null) { + throw new BpmnError("Handler cannot be null at the call delegate."); + } + executeJSHandler(context); + } + + /** + * Execute JS handler. + * + * @param context the context + */ + private void executeJSHandler(Map context) { + RepositoryPath path = new RepositoryPath(handler.getExpressionText()); + JSTask task = JSTask.fromRepositoryPath(path); + + try (DirigibleJavascriptCodeRunner runner = new DirigibleJavascriptCodeRunner(context, false)) { + Source source = runner.prepareSource(task.getSourceFilePath()); + Value value = runner.run(source); + + if (task.hasExportedClassAndMethod()) { + value.getMember(task.getClassName()) + .newInstance() + .getMember(task.getMethodName()) + .executeVoid(); + } else if (task.hasExportedMethod()) { + value.getMember(task.getMethodName()) + .executeVoid(); + } + + } + } + } 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 4bf7f09a0d2..9121f753092 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 @@ -9,19 +9,9 @@ */ 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 static org.eclipse.dirigible.components.engine.bpm.flowable.dto.TaskActionData.TaskAction.*; -import static org.eclipse.dirigible.components.engine.bpm.flowable.service.BpmService.DIRIGIBLE_BPM_INTERNAL_SKIP_STEP; -import static org.eclipse.dirigible.components.engine.bpm.flowable.service.task.TaskQueryExecutor.*; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.*; -import java.util.stream.Collectors; - +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.node.ObjectNode; import org.apache.commons.io.IOUtils; import org.eclipse.dirigible.components.api.security.UserFacade; import org.eclipse.dirigible.components.base.endpoint.BaseEndpoint; @@ -32,6 +22,7 @@ import org.eclipse.dirigible.components.ide.workspace.service.WorkspaceService; import org.eclipse.dirigible.repository.api.RepositoryNotFoundException; import org.flowable.bpmn.model.BpmnModel; +import org.flowable.common.engine.api.FlowableObjectNotFoundException; import org.flowable.engine.*; import org.flowable.engine.history.HistoricProcessInstance; import org.flowable.engine.repository.ProcessDefinition; @@ -52,9 +43,19 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.server.ResponseStatusException; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.*; +import java.util.stream.Collectors; + +import static java.text.MessageFormat.format; +import static org.eclipse.dirigible.components.engine.bpm.flowable.dto.ActionData.Action.RETRY; +import static org.eclipse.dirigible.components.engine.bpm.flowable.dto.ActionData.Action.SKIP; +import static org.eclipse.dirigible.components.engine.bpm.flowable.dto.TaskActionData.TaskAction.*; +import static org.eclipse.dirigible.components.engine.bpm.flowable.service.BpmService.DIRIGIBLE_BPM_INTERNAL_SKIP_STEP; +import static org.eclipse.dirigible.components.engine.bpm.flowable.service.task.TaskQueryExecutor.Type; /** * Front facing REST service serving the BPM related resources and operations. @@ -90,34 +91,6 @@ public class BpmFlowableEndpoint extends BaseEndpoint { @Autowired private TaskQueryExecutor taskQueryExecutor; - - /** - * Gets the bpm provider flowable. - * - * @return the bpm provider flowable - */ - public BpmProviderFlowable getBpmProviderFlowable() { - return bpmProviderFlowable; - } - - /** - * Gets the bpm service. - * - * @return the bpm service - */ - public BpmService getBpmService() { - return bpmService; - } - - /** - * Gets the workspace service. - * - * @return the workspace service - */ - public WorkspaceService getWorkspaceService() { - return workspaceService; - } - /** * Get the BPM model source. * @@ -142,6 +115,15 @@ public ResponseEntity getModel(@PathVariable("workspace") String wor return ResponseEntity.ok(model); } + /** + * Gets the bpm service. + * + * @return the bpm service + */ + public BpmService getBpmService() { + return bpmService; + } + /** * Sanitize path. * @@ -181,6 +163,14 @@ public ResponseEntity saveModel(@PathVariable("workspace") String workspace return ResponseEntity.ok(getWorkspaceService().getURI(workspace, project, path)); } + /** + * Gets the workspace service. + * + * @return the workspace service + */ + public WorkspaceService getWorkspaceService() { + return workspaceService; + } /** * Get the Stencil-Set. @@ -313,6 +303,43 @@ public ResponseEntity> getProcessInstanceTasks(@PathVariable("id") return ResponseEntity.ok(taskDTOS); } + private static Type extractPrincipalType(String type) { + Type principalType; + try { + principalType = Type.fromString(type); + } catch (IllegalArgumentException e) { + principalType = Type.ASSIGNEE; + } + return principalType; + } + + private TaskDTO mapToDTO(Task task) { + List identityLinks = getTaskService().getIdentityLinksForTask(task.getId()); + + TaskDTO dto = new TaskDTO(); + dto.setId(task.getId()); + dto.setName(task.getName()); + dto.setAssignee(task.getAssignee()); + dto.setFormKey(task.getFormKey()); + dto.setCreateTime(task.getCreateTime()); + dto.setProcessInstanceId(task.getProcessInstanceId()); + dto.setCandidateUsers(identityLinks.stream() + .map(IdentityLinkInfo::getUserId) + .filter(Objects::nonNull) + .collect(Collectors.joining(","))); + dto.setCandidateGroups(identityLinks.stream() + .map(IdentityLinkInfo::getGroupId) + .filter(Objects::nonNull) + .collect(Collectors.joining(","))); + return dto; + } + + private TaskService getTaskService() { + return bpmService.getBpmProviderFlowable() + .getProcessEngine() + .getTaskService(); + } + @GetMapping(value = "/bpm-processes/tasks") public ResponseEntity> getTasks(@RequestParam(value = "type", required = false) String type) { List taskDTOS = taskQueryExecutor.findTasks(extractPrincipalType(type)) @@ -322,14 +349,20 @@ public ResponseEntity> getTasks(@RequestParam(value = "type", requ return ResponseEntity.ok(taskDTOS); } - private static Type extractPrincipalType(String type) { - Type principalType; + @GetMapping(value = "/bpm-processes/tasks/{taskId}/variables") + public ResponseEntity getTaskVariables(@PathVariable("taskId") String taskId) { + TaskService taskService = getTaskService(); + try { - principalType = Type.fromString(type); - } catch (IllegalArgumentException e) { - principalType = Type.ASSIGNEE; + Map variables = taskService.getVariables(taskId); + TaskVariablesDTO taskVariables = new TaskVariablesDTO(variables); + + return ResponseEntity.ok(taskVariables); + } catch (FlowableObjectNotFoundException ex) { + logger.debug("Missing task with id [{}]", taskId, ex); + return ResponseEntity.notFound() + .build(); } - return principalType; } @PostMapping(value = "/bpm-processes/tasks/{id}") @@ -353,33 +386,6 @@ public ResponseEntity executeTaskAction(@PathVariable("id") String id, @ .build(); } - private TaskService getTaskService() { - return bpmService.getBpmProviderFlowable() - .getProcessEngine() - .getTaskService(); - } - - private TaskDTO mapToDTO(Task task) { - List identityLinks = getTaskService().getIdentityLinksForTask(task.getId()); - - TaskDTO dto = new TaskDTO(); - dto.setId(task.getId()); - dto.setName(task.getName()); - dto.setAssignee(task.getAssignee()); - dto.setFormKey(task.getFormKey()); - dto.setCreateTime(task.getCreateTime()); - dto.setProcessInstanceId(task.getProcessInstanceId()); - dto.setCandidateUsers(identityLinks.stream() - .map(IdentityLinkInfo::getUserId) - .filter(Objects::nonNull) - .collect(Collectors.joining(","))); - dto.setCandidateGroups(identityLinks.stream() - .map(IdentityLinkInfo::getGroupId) - .filter(Objects::nonNull) - .collect(Collectors.joining(","))); - return dto; - } - /** * Add or update active process instance variable. * @@ -466,7 +472,7 @@ public ResponseEntity> getDeadLetterJobs(@PathVariable("id") String id @GetMapping(value = "/bpm-processes/diagram/definition/{processDefinitionKey}", produces = "image/png") public ResponseEntity getProcessDefinitionImage(@PathVariable("processDefinitionKey") String processDefinitionKey) throws IOException { - ProcessEngine processEngine = ((ProcessEngine) getBpmProviderFlowable().getProcessEngine()); + ProcessEngine processEngine = getBpmProviderFlowable().getProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); ProcessDefinition process = repositoryService.createProcessDefinitionQuery() @@ -486,6 +492,15 @@ public ResponseEntity getProcessDefinitionImage(@PathVariable("processDe return ResponseEntity.ok(new byte[] {}); } + /** + * Gets the bpm provider flowable. + * + * @return the bpm provider flowable + */ + public BpmProviderFlowable getBpmProviderFlowable() { + return bpmProviderFlowable; + } + /** * Gets the process image. * @@ -495,7 +510,7 @@ public ResponseEntity getProcessDefinitionImage(@PathVariable("processDe */ @GetMapping(value = "/bpm-processes/diagram/instance/{processInstanceId}", produces = "image/png") public ResponseEntity getProcessInstanceImage(@PathVariable("processInstanceId") String processInstanceId) throws IOException { - ProcessEngine processEngine = ((ProcessEngine) getBpmProviderFlowable().getProcessEngine()); + ProcessEngine processEngine = getBpmProviderFlowable().getProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); ProcessEngineConfiguration processEngineConfiguration = processEngine.getProcessEngineConfiguration(); RuntimeService runtimeService = processEngine.getRuntimeService(); diff --git a/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/TaskVariablesDTO.java b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/TaskVariablesDTO.java new file mode 100644 index 00000000000..4100e1a4a7f --- /dev/null +++ b/components/engine/engine-bpm-flowable/src/main/java/org/eclipse/dirigible/components/engine/bpm/flowable/endpoint/TaskVariablesDTO.java @@ -0,0 +1,16 @@ +package org.eclipse.dirigible.components.engine.bpm.flowable.endpoint; + +import java.util.Map; + +class TaskVariablesDTO { + + private final Map variables; + + public TaskVariablesDTO(Map variables) { + this.variables = variables; + } + + public Map getVariables() { + return variables; + } +}