diff --git a/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/StarterFeignClientConfiguration.java b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/StarterFeignClientConfiguration.java index 0c6b6e763..91d071282 100644 --- a/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/StarterFeignClientConfiguration.java +++ b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/StarterFeignClientConfiguration.java @@ -1,10 +1,48 @@ package cn.axzo.workflow.starter; +import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient; import cn.axzo.workflow.starter.api.WorkflowCoreService; import cn.axzo.workflow.starter.api.WorkflowManageService; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanDefinitionHolder; +import org.springframework.beans.factory.config.BeanExpressionContext; +import org.springframework.beans.factory.config.BeanExpressionResolver; +import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.beans.factory.support.AbstractBeanDefinition; +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.cloud.openfeign.FeignClientFactoryBean; +import org.springframework.context.EnvironmentAware; +import org.springframework.context.ResourceLoaderAware; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.env.Environment; +import org.springframework.core.io.ResourceLoader; +import org.springframework.core.type.AnnotationMetadata; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; +import org.springframework.util.ObjectUtils; +import org.springframework.util.StringUtils; + +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; /** * 根据参数动态实例化可用 Bean @@ -25,4 +63,5 @@ public class StarterFeignClientConfiguration { @EnableFeignClients(clients = WorkflowManageService.class) public static class WorkflowManageServiceClient { } + } diff --git a/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/WorkflowEngineStarterAutoConfiguration.java b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/WorkflowEngineStarterAutoConfiguration.java index 232c50771..466f464d9 100644 --- a/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/WorkflowEngineStarterAutoConfiguration.java +++ b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/WorkflowEngineStarterAutoConfiguration.java @@ -25,6 +25,7 @@ import cn.axzo.workflow.starter.mq.broadcast.consumer.InnerTaskEventListener; import cn.axzo.workflow.starter.mq.broadcast.consumer.InnerWorkflowListener; import cn.axzo.workflow.starter.mq.monitor.WorkflowEngineStarterDefaultMQMonitor; import cn.axzo.workflow.starter.mq.monitor.console.WorkflowEngineStarterMQMonitorController; +import cn.axzo.workflow.starter.selector.MetaFeignClientEnableSelector; import org.apache.commons.lang3.StringUtils; import org.apache.rocketmq.client.exception.MQClientException; import org.apache.rocketmq.common.MixAll; @@ -51,7 +52,7 @@ import java.util.List; */ @Configuration(proxyBeanMethods = false) @EnableConfigurationProperties(WorkflowEngineStarterProperties.class) -@Import({StarterFeignClientConfiguration.class, StarterBroadcastMQConfiguration.class, StarterRPCInvokeMQConfiguration.class}) +@Import({StarterFeignClientConfiguration.class, StarterBroadcastMQConfiguration.class, StarterRPCInvokeMQConfiguration.class, MetaFeignClientEnableSelector.class}) public class WorkflowEngineStarterAutoConfiguration { private final Logger log = LoggerFactory.getLogger(WorkflowEngineStarterAutoConfiguration.class); @@ -147,4 +148,5 @@ public class WorkflowEngineStarterAutoConfiguration { Environment environment) { return new WorkflowEngineStarterDefaultMQMonitor(mqAdminExtObjectProvider, broadcastDLQProcessorObjectProvider, rpcDLQProcessorObjectProvider, workflowEngineStarterProperties, environment); } + } diff --git a/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/WorkflowEngineStarterProperties.java b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/WorkflowEngineStarterProperties.java index 584d75484..9d103a013 100644 --- a/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/WorkflowEngineStarterProperties.java +++ b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/WorkflowEngineStarterProperties.java @@ -18,6 +18,10 @@ import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.ASYNC; */ @ConfigurationProperties(prefix = "workflow.engine.starter") public class WorkflowEngineStarterProperties { + /** + * + */ + private Boolean metaFeign = false; /** * 特殊用途,不建议接入方使用 */ @@ -84,6 +88,14 @@ public class WorkflowEngineStarterProperties { */ private Boolean alert = false; + public Boolean getMetaFeign() { + return metaFeign; + } + + public void setMetaFeign(Boolean metaFeign) { + this.metaFeign = metaFeign; + } + public Boolean getManageable() { return manageable; } diff --git a/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/api/WorkflowCoreService.java b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/api/WorkflowCoreService.java index 92b09c7e4..9eb987904 100644 --- a/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/api/WorkflowCoreService.java +++ b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/api/WorkflowCoreService.java @@ -1,10 +1,339 @@ package cn.axzo.workflow.starter.api; +import cn.axzo.workflow.starter.feign.ext.WorkflowEngineStarterFeignConfiguration; +import cn.axzo.workflow.common.util.ThreadUtil; +import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.ASYNC; +import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC; +import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO; +import cn.azxo.framework.common.model.CommonResponse; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import javax.validation.constraints.NotBlank; +import cn.axzo.workflow.common.annotation.InvokeMode; +import cn.axzo.workflow.common.annotation.Manageable; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAdminPageReqVO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCarbonCopyDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateWithFormDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO; +import cn.axzo.workflow.common.model.response.BpmPageResult; +import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO; +import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO; +import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLogVO; +import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO; +import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO; +import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PutMapping; +import javax.annotation.Nullable; +import javax.validation.constraints.NotNull; +import java.util.List; +import java.util.Map; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnOptionalNodeDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCompleteDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCreateDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAttachmentDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskBackAuditDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCommentDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskPageSearchDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskRemindDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskTransferDTO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceGroupVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskDonePageItemVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskTodoPageItemVO; +import javax.validation.constraints.NotEmpty; + /** - * just for compiler - * - * @author wangli - * @since 2024-09-09 18:25 + * Workflow Engine Starter Core Service + *
+ * 该类是根据 API 动态生成,不同版本可能会开放新的接口,或回收一些旧接口 */ +@org.springframework.cloud.openfeign.FeignClient(name = "workflow-engine-starter-core", url = "${axzo.service.workflow-engine.starter:http://workflow-engine:8080}", configuration = WorkflowEngineStarterFeignConfiguration.class) public interface WorkflowCoreService { + + /** + * 业务节点唤醒, 该节点废弃,请换成 {@link ProcessActivityApi#trigger(cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO)} 接口 + *
+ * 当模型中使用了“业务节点”,且设置了“不设置审批人”模式,则当业务监听到 PROCESS_ACTIVITY_START 事件时,可通过该接口推动流程继续运行 + */ + @Deprecated + @GetMapping("/api/process/activity/trigger") + Boolean trigger(@NotBlank(message = "触发 ID 不能为空") @RequestParam String triggerId); + + /** + * 业务节点唤醒 + * + * @param dto + * @return + */ + @PostMapping("/api/process/activity/trigger") + Boolean trigger(@Validated @RequestBody BpmnActivityTriggerDTO dto); + + /** + * 业务节点设置审批人, 不支持重复设置 + *
+ * 当模型中使用了“业务节点”,且设置了“业务指定审批人”模式,则当业务监听到 PROCESS_ACTIVITY_WAIT_ASSIGNEE 事件时,可通过该接口设置动态设置审批人 + *
+ * 注意:如果调用接口时,传入的审批人集合为空,流程引擎将对该审批流程实例自动中止。 + * + * @param dto + * @return + */ + @PostMapping("/api/process/activity/assignee/set") + @Operation(summary = "业务节点设置审批人,不支持重复调用设置审批人,需一次性传入所有审批人") + Boolean setAssignee(@Validated @RequestBody BpmnActivitySetAssigneeDTO dto); + + /** + * 创建审批流程 + * + *
+ * MQ 触发规则: + * 1. 当前流程实例会依次触发 process-instance-created 和 process-instance-started 事件 + * 2. 第一个审批任务会依次触发 process-task-assigned 和 process-task-created 事件 + *+ * + * @param dto {@link BpmnProcessInstanceCreateDTO} + */ + @Operation(summary = "创建审批流程, MQ 触发规则:1. 当前流程实例会依次触发 process-instance-created 和 process-instance-started 事件,2. 第一个审批任务会依次触发 process-task-assigned 和 process-task-created 事件") + @PostMapping("/api/process/instance/create") + @InvokeMode(SYNC) + String createProcessInstance(@Validated @RequestBody BpmnProcessInstanceCreateDTO dto); + + /** + * 发起人主动撤回审核 + * + *
+ * MQ 触发规则: + * 1. 当前流程实例中现存的任务会依次触发 process-task-deleted 事件 + * 2. 当前流程实例会触发 process-instance-cancelled 事件 + *+ * + * @param dto {@link BpmnProcessInstanceCancelDTO} + * @return + */ + @Operation(summary = "发起人主动撤回审核,MQ 触发规则:1. 当前流程实例中现存的任务会依次触发 process-task-deleted 事件,2. 当前流程实例会触发 process-instance-cancelled 事件") + @DeleteMapping("/api/process/instance/cancel") + Boolean cancelProcessInstance(@Validated @RequestBody BpmnProcessInstanceCancelDTO dto); + + /** + * 中止流程实例 + * + * @param dto + * @return + */ + @Operation(summary = "中止流程实例") + @DeleteMapping("/api/process/instance/abort") + Boolean abortProcessInstance(@Validated @RequestBody BpmnProcessInstanceAbortDTO dto); + + /** + * 批量中止流程实例 + * + * @param dtos + * @return + */ + @Operation(summary = "批量中止流程实例") + @DeleteMapping("/api/process/instance/batch/abort") + BatchOperationResultVO batchAbortProcessInstance(@Validated @RequestBody List
+ * MQ 触发规则: + * 1. 当前审批任务会依次触发 process-task-completed 和 process-task-deleted 事件(如果有下一级审批,则会触发第 2.1 点中的事件, + * 如果当前审核任务最后一级审批,则会触发第 2.2 点中的事件) + * 2.1. 下一级审批任务会依次触发 process-task-assigned 和 process-task-created 事件 + * 2.2. 流程实例正常结束会触发 process-instance-completed 事件 + *+ */ + @Operation(summary = "同意,MQ 触发规则:1. 当前审批任务会依次触发 process-task-completed 和 process-task-deleted 事件(如果有下一级审批,则会触发第 2.1 点中的事件,如果当前审核任务最后一级审批,则会触发第 2.2 点中的事件),2.1. 下一级审批任务会依次触发 process-task-assigned 和 process-task-created 事件,2.2. 流程实例正常结束会触发 process-instance-completed 事件") + @PostMapping("/api/process/task/approve") + Boolean approveTask(@Validated @RequestBody BpmnTaskAuditDTO dto); + + /** + * 批量同意 + * + * @param dtos + * @return + */ + @Operation(summary = "批量同意") + @PostMapping("/api/process/task/batch/approve") + BatchOperationResultVO batchApproveTask(@Validated @RequestBody List
+ * MQ 触发规则: + * 1. 当前审批任务会触发 process-task-deleted 事件 + * 2. 当前流程实例会触发 process-instance-rejected 事件 + *+ */ + @Operation(summary = "驳回,MQ 触发规则:1. 当前审批任务会触发 process-task-deleted 事件, 2. 当前流程实例会触发 process-instance-rejected 事件") + @PostMapping("/api/process/task/reject") + Boolean rejectTask(@Validated @RequestBody BpmnTaskAuditDTO dto); + + /** + * 批量驳回 + * + * @param dtos 批量请求参数 + * @return + */ + @PostMapping("/api/process/task/batch/reject") + BatchOperationResultVO batchRejectTask(@Validated @RequestBody List
+ * workflowCoreService.async().createProcessInstance(); + *+ */ + default WorkflowCoreService sync() { + ThreadUtil.set(SYNC); + return this; + } + + default WorkflowCoreService async() { + ThreadUtil.set(ASYNC); + return this; + } } diff --git a/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/api/WorkflowManageService.java b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/api/WorkflowManageService.java index 2d5ba5e8d..b6c262f2a 100644 --- a/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/api/WorkflowManageService.java +++ b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/api/WorkflowManageService.java @@ -1,10 +1,721 @@ package cn.axzo.workflow.starter.api; +import cn.axzo.workflow.starter.feign.ext.WorkflowEngineStarterFeignConfiguration; +import cn.axzo.workflow.common.util.ThreadUtil; +import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.ASYNC; +import static cn.axzo.workflow.common.enums.RpcInvokeModeEnum.SYNC; +import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient; +import cn.axzo.workflow.client.config.CommonFeignConfiguration; +import cn.axzo.workflow.common.annotation.InvokeMode; +import cn.axzo.workflow.common.annotation.Manageable; +import cn.axzo.workflow.common.model.request.bpmn.BpmnButtonMetaInfo; +import cn.azxo.framework.common.model.CommonResponse; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import java.util.List; +import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelCreateDTO; +import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelSearchDTO; +import cn.axzo.workflow.common.model.request.bpmn.model.BpmnModelUpdateDTO; +import cn.axzo.workflow.common.model.response.BpmPageResult; +import cn.axzo.workflow.common.model.response.bpmn.model.BpmnModelDetailVO; +import cn.axzo.workflow.common.model.response.bpmn.model.BpmnModelExtVO; +import io.swagger.v3.oas.annotations.Operation; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivitySetAssigneeDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnActivityTriggerDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAbortDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceAdminPageReqVO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCancelDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCarbonCopyDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCheckApproverDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceCreateWithFormDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceLogQueryDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceMyPageReqVO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessInstanceQueryDTO; +import cn.axzo.workflow.common.model.response.bpmn.BatchOperationResultVO; +import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceAdminPageItemVO; +import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceLogVO; +import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstancePageItemVO; +import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessInstanceVO; +import cn.axzo.workflow.common.model.response.bpmn.process.ProcessNodeDetailVO; +import com.fasterxml.jackson.databind.node.ObjectNode; +import javax.annotation.Nullable; +import java.util.Map; +import cn.axzo.workflow.common.model.request.category.CategoryConfigCreateDTO; +import cn.axzo.workflow.common.model.request.category.CategoryConfigSearchDTO; +import cn.axzo.workflow.common.model.request.category.CategoryCreateDTO; +import cn.axzo.workflow.common.model.request.category.CategorySearchDTO; +import cn.axzo.workflow.common.model.request.category.CategoryUpdateDTO; +import cn.axzo.workflow.common.model.response.category.CategoryConfigItemVO; +import cn.axzo.workflow.common.model.response.category.CategoryItemVO; +import org.springframework.web.bind.annotation.PathVariable; +import cn.axzo.workflow.common.model.request.bpmn.RestBpmnProcessVariable; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnOptionalNodeDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCompleteDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnRobotTaskCreateDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAttachmentDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskAuditDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskBackAuditDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCommentDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskPageSearchDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskRemindDTO; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskTransferDTO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceGroupVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnHistoricTaskInstanceVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskDonePageItemVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskInstanceVO; +import cn.axzo.workflow.common.model.response.bpmn.task.BpmnTaskTodoPageItemVO; +import javax.validation.constraints.NotEmpty; +import cn.axzo.workflow.common.model.request.bpmn.definition.BpmnProcessDefinitionUpdateDTO; +import cn.axzo.workflow.common.model.request.bpmn.process.BpmnProcessDefinitionPageDTO; +import cn.axzo.workflow.common.model.response.bpmn.process.BpmnProcessDefinitionVO; + /** - * just for compiler - * - * @author wangli - * @since 2024-09-09 18:26 + * Workflow Engine Starter Management Service + *
+ * 该类是根据 API 动态生成,不同版本可能会开放新的接口,或回收一些旧接口
*/
+@org.springframework.cloud.openfeign.FeignClient(name = "workflow-engine-starter-manage", url = "${axzo.service.workflow-engine.starter:http://workflow-engine:8080}", configuration = WorkflowEngineStarterFeignConfiguration.class)
public interface WorkflowManageService {
+
+ /**
+ * 获取流程操作按钮列表
+ *
+ * @return 流程操作按钮列表
+ */
+ @GetMapping("/api/process/config/button/list")
+ @InvokeMode(SYNC)
+ List
+ * 偏向业务的接口,flowable 引擎是站在流程定义维度进行激活和挂起
+ *
+ * @return true 能更新,表明该模型关联的所有定义版本都是挂起状态
+ */
+ @Operation(summary = "获取指定模型的扩展属性")
+ @GetMapping("/api/process/model/ext")
+ @InvokeMode(SYNC)
+ BpmnModelExtVO getModelExt(@NotBlank(message = "模型 ID 不能为空") @RequestParam(required = false) String modelId);
+
+ /**
+ * 修改流程信息
+ */
+ @Operation(summary = "更新流程模型")
+ @PutMapping("/api/process/model/update")
+ @InvokeMode(SYNC)
+ String update(@RequestBody BpmnModelUpdateDTO dto);
+
+ /**
+ * 通过模型 ID 部署模型
+ *
+ * @return 部署完成的流程定义Id
+ */
+ @Operation(summary = "通过模型 ID 部署流程模型")
+ @PostMapping("/api/process/model/deploy")
+ @InvokeMode(SYNC)
+ String deployById(@NotBlank(message = "流程模型 ID 不能为空") @RequestParam(required = false) String processModelId, @RequestParam(required = false, defaultValue = "") String modelTenantId, @RequestParam(required = false) String operator);
+
+ /**
+ * 通过模型 KEY 部署模型
+ *
+ * @return 部署完成的流程定义Id
+ */
+ @Operation(summary = "通过模型 KEY 部署流程模型")
+ @PostMapping("/api/process/model/deployByKey")
+ @InvokeMode(SYNC)
+ String deployByKey(@NotBlank(message = "流程模型 KEY 不能为空") @RequestParam(required = false) String processModelKey, @NotBlank(message = "租户不能为空") @RequestParam(required = false) String modelTenantId, @RequestParam(required = false) String operator);
+
+ /**
+ * 通过模型 ID 取消部署流程模型
+ *
+ * @param processModelId
+ * @param tenantId
+ * @param operator
+ * @return
+ */
+ @Operation(summary = "通过模型 ID 取消部署流程模型")
+ @PostMapping("/api/process/model/undeploy")
+ @InvokeMode(SYNC)
+ Void unDeployById(@NotBlank(message = "流程模型 ID 不能为空") @RequestParam(required = false) String processModelId, @RequestParam(required = false, defaultValue = "") String tenantId, @RequestParam(required = false) String operator);
+
+ /**
+ * 通过模型 ID 删除模型
+ */
+ @Operation(summary = "删除指定模型 ID 的流程模型")
+ @DeleteMapping("/api/process/model/delete")
+ @InvokeMode(SYNC)
+ Void deleteById(@NotBlank(message = "流程模型 ID 不能为空") @RequestParam String processModelId, @RequestParam(required = false, defaultValue = "") String tenantId);
+
+ /**
+ * 通过模型 KEY 删除模型
+ *
+ * @param processModelKey
+ * @param tenantId
+ * @return
+ */
+ @Operation(summary = "删除指定模型 KEY 的流程模型")
+ @DeleteMapping("/api/process/model/deleteByKey")
+ @InvokeMode(SYNC)
+ Void deleteByKey(@NotBlank(message = "流程模型 KEY 不能为空") @RequestParam String processModelKey, @RequestParam(required = false, defaultValue = "") String tenantId);
+
+ /**
+ * 通过模型 ID 修改模型状态
+ *
+ * @param modelId
+ * @param status
+ * @param operator
+ * @return
+ */
+ @Operation(summary = "修改模型状态")
+ @PostMapping("/api/process/model/changeStatus")
+ @InvokeMode(SYNC)
+ Void changeStatus(@NotBlank(message = "模型 ID 不能为空") @RequestParam String modelId, @NotNull(message = "状态不能为空") @RequestParam Integer status, @RequestParam(required = false) String operator);
+
+ /**
+ * 查询流程模型使用的分类列表
+ *
+ * @return
+ */
+ @Operation(summary = "查询流程模型使用的分类列表")
+ @GetMapping("/api/process/model/category/ids")
+ @InvokeMode(SYNC)
+ List
+ * 入参是二选一:当只有 jobId 时,仅将指定的 JOB 转移到正常的队列中;
+ * 而传入的是具体的实例 ID,那么会将这个流程下的所有在死信队列中的任务都转移到正常的队列中
+ *
+ * @param jobId 具体的 JOB ID
+ * @param procInstId 具体的实例 ID
+ * @return
+ */
+ @GetMapping("/api/process/job/dead-letter/resume")
+ @Manageable
+ Void executeDeadLetterJobAction(@RequestParam(required = false) String jobId, @RequestParam(required = false) String procInstId);
+
+ /**
+ * 获取指定业务分类
+ *
+ * @return
+ */
+ @GetMapping("/api/process/category/get")
+ @InvokeMode(SYNC)
+ CategoryItemVO get(@RequestParam Long id);
+
+ /**
+ * 获取指定业务分类集合
+ *
+ * @param ids
+ * @return
+ */
+ @GetMapping("/api/process/category/getByIds")
+ @InvokeMode(SYNC)
+ List
+ * 同一层级结构
+ */
+ @Operation(summary = "获取指定流程实例的审批过程信息")
+ @GetMapping("/api/process/task/list/flat")
+ @Manageable
+ @InvokeMode(SYNC)
+ List
+ * 分组结构
+ */
+ @Operation(summary = "获取指定流程实例的审批过程信息")
+ @GetMapping("/api/process/task/list/group")
+ @Manageable
+ @InvokeMode(SYNC)
+ List
+ * workflowManageService.sync().getTenantIds();
+ *
+ */
+ default WorkflowManageService sync() {
+ ThreadUtil.set(SYNC);
+ return this;
+ }
+
+ /**
+ * 强制使用‘异步’模式调用该方法,请在调用真实方法前调用该方法
+ *
+ * workflowManageService.async().getTenantIds();
+ *
+ */
+ default WorkflowManageService async() {
+ ThreadUtil.set(ASYNC);
+ return this;
+ }
}
diff --git a/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/selector/MetaFeignClientEnableSelector.java b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/selector/MetaFeignClientEnableSelector.java
new file mode 100644
index 000000000..13599b0fd
--- /dev/null
+++ b/workflow-engine-spring-boot-starter/src/main/java/cn/axzo/workflow/starter/selector/MetaFeignClientEnableSelector.java
@@ -0,0 +1,320 @@
+package cn.axzo.workflow.starter.selector;
+
+import cn.axzo.workflow.client.annotation.WorkflowEngineFeignClient;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.FactoryBean;
+import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.config.BeanDefinitionHolder;
+import org.springframework.beans.factory.config.BeanExpressionContext;
+import org.springframework.beans.factory.config.BeanExpressionResolver;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.cloud.client.ConditionalOnReactiveDiscoveryEnabled;
+import org.springframework.cloud.openfeign.FeignClientFactoryBean;
+import org.springframework.context.EnvironmentAware;
+import org.springframework.context.ResourceLoaderAware;
+import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
+import org.springframework.core.annotation.AnnotationAttributes;
+import org.springframework.core.env.Environment;
+import org.springframework.core.io.ResourceLoader;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.core.type.filter.AnnotationTypeFilter;
+import org.springframework.util.Assert;
+import org.springframework.util.ClassUtils;
+import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 原生 FeignClient 的注册
+ *
+ * @author wangli
+ * @since 2024-09-10 09:56
+ */
+@Slf4j
+public class MetaFeignClientEnableSelector implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
+
+ private ResourceLoader resourceLoader;
+
+ private Environment environment;
+
+ static void validateFallback(final Class clazz) {
+ Assert.isTrue(!clazz.isInterface(), "Fallback class must implement the interface annotated by @FeignClient");
+ }
+
+ static void validateFallbackFactory(final Class clazz) {
+ Assert.isTrue(!clazz.isInterface(), "Fallback factory must produce instances "
+ + "of fallback classes that implement the interface annotated by @FeignClient");
+ }
+
+ static String getName(String name) {
+ if (!StringUtils.hasText(name)) {
+ return "";
+ }
+
+ String host = null;
+ try {
+ String url;
+ if (!name.startsWith("http://") && !name.startsWith("https://")) {
+ url = "http://" + name;
+ }
+ else {
+ url = name;
+ }
+ host = new URI(url).getHost();
+
+ }
+ catch (URISyntaxException e) {
+ }
+ Assert.state(host != null, "Service id not legal hostname (" + name + ")");
+ return name;
+ }
+
+ static String getUrl(String url) {
+ if (StringUtils.hasText(url) && !(url.startsWith("#{") && url.contains("}"))) {
+ if (!url.contains("://")) {
+ url = "http://" + url;
+ }
+ try {
+ new URL(url);
+ }
+ catch (MalformedURLException e) {
+ throw new IllegalArgumentException(url + " is malformed", e);
+ }
+ }
+ return url;
+ }
+
+ static String getPath(String path) {
+ if (StringUtils.hasText(path)) {
+ path = path.trim();
+ if (!path.startsWith("/")) {
+ path = "/" + path;
+ }
+ if (path.endsWith("/")) {
+ path = path.substring(0, path.length() - 1);
+ }
+ }
+ return path;
+ }
+
+ @Override
+ public void setEnvironment(Environment environment) {
+ this.environment = environment;
+ }
+
+ @Override
+ public void setResourceLoader(ResourceLoader resourceLoader) {
+ this.resourceLoader = resourceLoader;
+ }
+
+ @Override
+ public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
+ Boolean metaFeignEnabled = environment.getProperty("workflow.engine.starter.meta-feign", Boolean.class);
+ log.error("current meta-feign result: {}", metaFeignEnabled);
+ if(!Boolean.TRUE.equals(metaFeignEnabled)){
+ return;
+ }
+ LinkedHashSet