diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java index 283d18745..c58d5cd00 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/conf/FlowableConfiguration.java @@ -3,8 +3,10 @@ package cn.axzo.workflow.core.conf; import cn.axzo.workflow.core.engine.behavior.CustomActivityBehaviorFactory; import cn.axzo.workflow.core.engine.id.DistributedTimeBasedIdGenerator; import cn.axzo.workflow.core.engine.job.AsyncApproveTaskJobHandler; +import cn.axzo.workflow.core.engine.job.AsyncCountersignUserTaskJobHandler; import cn.axzo.workflow.core.engine.job.AsyncExtTaskInstJobHandler; import cn.axzo.workflow.core.engine.job.AsyncRejectTaskJobHandler; +import cn.axzo.workflow.core.engine.job.AsyncTransferUserTaskJobHandler; import cn.axzo.workflow.core.engine.job.exception.handler.CustomAsyncRunnableExecutionExceptionHandler; import cn.axzo.workflow.core.engine.persistence.CustomMybatisHistoricProcessInstanceDataManager; import cn.axzo.workflow.core.service.ExtAxHiTaskInstService; @@ -52,6 +54,8 @@ public class FlowableConfiguration { configuration.addCustomJobHandler(new AsyncApproveTaskJobHandler()); configuration.addCustomJobHandler(new AsyncRejectTaskJobHandler(extAxHiTaskInstService)); configuration.addCustomJobHandler(new AsyncExtTaskInstJobHandler(extAxHiTaskInstService)); + configuration.addCustomJobHandler(new AsyncTransferUserTaskJobHandler()); + configuration.addCustomJobHandler(new AsyncCountersignUserTaskJobHandler(extAxHiTaskInstService)); // 异步任务异常重试时间间隔 configuration.setDefaultFailedJobWaitTime(30); configuration.setAsyncFailedJobWaitTime(30); diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomCountersignUserTaskAsyncCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomCountersignUserTaskAsyncCmd.java new file mode 100644 index 000000000..518f876ed --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomCountersignUserTaskAsyncCmd.java @@ -0,0 +1,65 @@ +package cn.axzo.workflow.core.engine.cmd; + +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO; +import cn.axzo.workflow.core.engine.job.AsyncCountersignUserTaskJobHandler; +import cn.hutool.json.JSONUtil; +import org.flowable.common.engine.impl.interceptor.Command; +import org.flowable.common.engine.impl.interceptor.CommandContext; +import org.flowable.engine.TaskService; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.impl.util.CommandContextUtil; +import org.flowable.job.service.JobService; +import org.flowable.job.service.impl.persistence.entity.JobEntity; +import org.flowable.task.api.Task; +import org.flowable.task.api.history.HistoricTaskInstance; +import org.flowable.task.api.history.HistoricTaskInstanceQuery; +import org.flowable.task.service.impl.persistence.entity.TaskEntity; + +import java.io.Serializable; + +import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask; + +public class CustomCountersignUserTaskAsyncCmd implements Command, Serializable { + private final BpmnTaskCountersignDTO dto; + + public CustomCountersignUserTaskAsyncCmd(BpmnTaskCountersignDTO dto) { + this.dto = dto; + } + + @Override + public Void execute(CommandContext commandContext) { + ProcessEngineConfigurationImpl processEngineConfiguration = + CommandContextUtil.getProcessEngineConfiguration(commandContext); + HistoricTaskInstanceQuery taskQuery = + processEngineConfiguration.getHistoryService().createHistoricTaskInstanceQuery(); + HistoricTaskInstance historicTaskInstance = taskQuery.taskId(dto.getTaskId()).singleResult(); + + TaskService taskService = processEngineConfiguration.getTaskService(); + Task task = taskService.createTaskQuery().taskId(dto.getTaskId()).singleResult(); + + validTask(historicTaskInstance, (TaskEntity) task, dto.getOriginAssigner()); + startAsync(processEngineConfiguration, task); + return null; + } + + private void startAsync(ProcessEngineConfigurationImpl processEngineConfiguration, Task task) { + JobService jobService = processEngineConfiguration.getJobServiceConfiguration().getJobService(); + + JobEntity job = jobService.createJob(); + // 这里的 executionId 可为 null + job.setExecutionId(task.getExecutionId()); + job.setProcessInstanceId(task.getProcessInstanceId()); + job.setProcessDefinitionId(task.getProcessDefinitionId()); + job.setElementId(task.getTaskDefinitionKey()); + job.setElementName(task.getName()); + job.setJobHandlerType(AsyncCountersignUserTaskJobHandler.TYPE); + job.setTenantId(task.getTenantId()); + + // 携带自定义的数据 + job.setCustomValues(JSONUtil.toJsonStr(dto)); + + // 创建异步任务并调度 + jobService.createAsyncJob(job, false); + jobService.scheduleAsyncJob(job); + } +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomTransferUserTaskAsyncCmd.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomTransferUserTaskAsyncCmd.java new file mode 100644 index 000000000..116e06e85 --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/cmd/CustomTransferUserTaskAsyncCmd.java @@ -0,0 +1,68 @@ +package cn.axzo.workflow.core.engine.cmd; + +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskTransferDTO; +import cn.axzo.workflow.core.engine.job.AsyncTransferUserTaskJobHandler; +import cn.hutool.json.JSONUtil; +import com.google.common.collect.Lists; +import org.flowable.common.engine.impl.interceptor.Command; +import org.flowable.common.engine.impl.interceptor.CommandContext; +import org.flowable.engine.TaskService; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.impl.util.CommandContextUtil; +import org.flowable.job.service.JobService; +import org.flowable.job.service.impl.persistence.entity.JobEntity; +import org.flowable.task.api.Task; +import org.flowable.task.api.history.HistoricTaskInstance; +import org.flowable.task.api.history.HistoricTaskInstanceQuery; +import org.flowable.task.service.impl.persistence.entity.TaskEntity; + +import java.io.Serializable; + +import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTask; +import static cn.axzo.workflow.core.engine.cmd.helper.CustomTaskHelper.validTaskAssignerDuplicated; + +/** + * 异步转交任务的命令执行器 + */ +public class CustomTransferUserTaskAsyncCmd implements Command, Serializable { + + private final BpmnTaskTransferDTO dto; + + public CustomTransferUserTaskAsyncCmd(BpmnTaskTransferDTO dto) { + this.dto = dto; + } + + @Override + public Void execute(CommandContext commandContext) { + ProcessEngineConfigurationImpl processEngineConfiguration = CommandContextUtil.getProcessEngineConfiguration(commandContext); + HistoricTaskInstanceQuery taskQuery = processEngineConfiguration.getHistoryService().createHistoricTaskInstanceQuery(); + HistoricTaskInstance historicTaskInstance = taskQuery.taskId(dto.getTaskId()).singleResult(); + TaskService taskService = processEngineConfiguration.getTaskService(); + Task task = taskService.createTaskQuery().taskId(dto.getTaskId()).singleResult(); + validTask(historicTaskInstance, (TaskEntity) task, dto.getOriginAssigner()); + validTaskAssignerDuplicated(commandContext, (TaskEntity) task, Lists.newArrayList(dto.getTargetAssigner())); + startAsync(processEngineConfiguration, task); + return null; + } + + private void startAsync(ProcessEngineConfigurationImpl processEngineConfiguration, Task task) { + JobService jobService = processEngineConfiguration.getJobServiceConfiguration().getJobService(); + + JobEntity job = jobService.createJob(); + // 这里的 executionId 可为 null + job.setExecutionId(task.getExecutionId()); + job.setProcessInstanceId(task.getProcessInstanceId()); + job.setProcessDefinitionId(task.getProcessDefinitionId()); + job.setElementId(task.getTaskDefinitionKey()); + job.setElementName(task.getName()); + job.setJobHandlerType(AsyncTransferUserTaskJobHandler.TYPE); + job.setTenantId(task.getTenantId()); + + // 携带自定义的数据 + job.setCustomValues(JSONUtil.toJsonStr(dto)); + + // 创建异步任务并调度 + jobService.createAsyncJob(job, false); + jobService.scheduleAsyncJob(job); + } +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncCountersignUserTaskJobHandler.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncCountersignUserTaskJobHandler.java new file mode 100644 index 000000000..91f886f8c --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncCountersignUserTaskJobHandler.java @@ -0,0 +1,46 @@ +package cn.axzo.workflow.core.engine.job; + +import cn.axzo.workflow.common.enums.BpmnCountersignTypeEnum; +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskCountersignDTO; +import cn.axzo.workflow.core.engine.cmd.CustomCountersignUserTaskCmd; +import cn.axzo.workflow.core.service.ExtAxHiTaskInstService; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.flowable.common.engine.impl.interceptor.CommandContext; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.impl.util.CommandContextUtil; +import org.flowable.job.service.JobHandler; +import org.flowable.job.service.impl.persistence.entity.JobEntity; +import org.flowable.variable.api.delegate.VariableScope; + +@Slf4j +public class AsyncCountersignUserTaskJobHandler implements JobHandler { + + public static final String TYPE = "async-countersign-task"; + + private final ExtAxHiTaskInstService extAxHiTaskInstService; + + public AsyncCountersignUserTaskJobHandler(ExtAxHiTaskInstService extAxHiTaskInstService) { + this.extAxHiTaskInstService = extAxHiTaskInstService; + } + + @Override + public String getType() { + return TYPE; + } + + @Override + public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) { + log.info("AsyncCountersignUserTaskJobHandler executing..."); + ProcessEngineConfigurationImpl processEngineConfiguration = + CommandContextUtil.getProcessEngineConfiguration(commandContext); + BpmnTaskCountersignDTO dto = JSONUtil.toBean(job.getCustomValues(), BpmnTaskCountersignDTO.class); + processEngineConfiguration.getCommandExecutor().execute(new CustomCountersignUserTaskCmd(BpmnCountersignTypeEnum.valueOfType(dto.getCountersignType()), + dto.getTaskId(), + dto.getOriginAssigner(), + dto.getAdvice(), + dto.getAttachmentList(), + dto.getTargetAssignerList(), + extAxHiTaskInstService)); + } +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncTransferUserTaskJobHandler.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncTransferUserTaskJobHandler.java new file mode 100644 index 000000000..607b1f4b7 --- /dev/null +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/engine/job/AsyncTransferUserTaskJobHandler.java @@ -0,0 +1,35 @@ +package cn.axzo.workflow.core.engine.job; + +import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskTransferDTO; +import cn.axzo.workflow.core.engine.cmd.CustomTransferUserTaskCmd; +import cn.hutool.json.JSONUtil; +import lombok.extern.slf4j.Slf4j; +import org.flowable.common.engine.impl.interceptor.CommandContext; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.impl.util.CommandContextUtil; +import org.flowable.job.service.JobHandler; +import org.flowable.job.service.impl.persistence.entity.JobEntity; +import org.flowable.variable.api.delegate.VariableScope; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +public class AsyncTransferUserTaskJobHandler implements JobHandler { + + public static final String TYPE = "async-transfer-task"; + + @Override + public String getType() { + return TYPE; + } + + @Override + public void execute(JobEntity job, String configuration, VariableScope variableScope, CommandContext commandContext) { + log.info("AsyncTransferUserTaskJobHandler executing..."); + ProcessEngineConfigurationImpl processEngineConfiguration = + CommandContextUtil.getProcessEngineConfiguration(commandContext); + BpmnTaskTransferDTO dto = JSONUtil.toBean(job.getCustomValues(), BpmnTaskTransferDTO.class); + processEngineConfiguration.getCommandExecutor().execute(new CustomTransferUserTaskCmd(dto.getTaskId(), + dto.getOriginAssigner(), dto.getAdvice(), dto.getAttachmentList(), dto.getTargetAssigner())); + } +} diff --git a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessTaskServiceImpl.java b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessTaskServiceImpl.java index 4c86d32df..a66791d6f 100644 --- a/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessTaskServiceImpl.java +++ b/workflow-engine-core/src/main/java/cn/axzo/workflow/core/service/impl/BpmnProcessTaskServiceImpl.java @@ -25,10 +25,12 @@ import cn.axzo.workflow.core.engine.cmd.CustomApproveTaskAsyncCmd; import cn.axzo.workflow.core.engine.cmd.CustomApproveTaskCmd; import cn.axzo.workflow.core.engine.cmd.CustomCommentTaskCmd; import cn.axzo.workflow.core.engine.cmd.CustomCompleteDummyTaskCmd; +import cn.axzo.workflow.core.engine.cmd.CustomCountersignUserTaskAsyncCmd; import cn.axzo.workflow.core.engine.cmd.CustomCountersignUserTaskCmd; import cn.axzo.workflow.core.engine.cmd.CustomCreateDummyTaskCmd; import cn.axzo.workflow.core.engine.cmd.CustomRejectionTaskAsyncCmd; import cn.axzo.workflow.core.engine.cmd.CustomRejectionTaskCmd; +import cn.axzo.workflow.core.engine.cmd.CustomTransferUserTaskAsyncCmd; import cn.axzo.workflow.core.engine.cmd.CustomTransferUserTaskCmd; import cn.axzo.workflow.core.engine.event.MessagePushEventBuilder; import cn.axzo.workflow.core.engine.event.MessagePushEventImpl; @@ -501,8 +503,12 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService { @Transactional(rollbackFor = Exception.class) public void transferTask(BpmnTaskTransferDTO dto) { CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor(); - commandExecutor.execute(new CustomTransferUserTaskCmd(dto.getTaskId(), - dto.getOriginAssigner(), dto.getAdvice(), dto.getAttachmentList(), dto.getTargetAssigner())); + if (dto.getAsync() != null && dto.getAsync()) { + commandExecutor.execute(new CustomTransferUserTaskAsyncCmd(dto)); + } else { + commandExecutor.execute(new CustomTransferUserTaskCmd(dto.getTaskId(), + dto.getOriginAssigner(), dto.getAdvice(), dto.getAttachmentList(), dto.getTargetAssigner())); + } } @@ -530,9 +536,14 @@ public class BpmnProcessTaskServiceImpl implements BpmnProcessTaskService { @Transactional(rollbackFor = Exception.class) public void countersignTask(BpmnTaskCountersignDTO dto) { CommandExecutor commandExecutor = processEngineConfiguration.getCommandExecutor(); - commandExecutor.execute(new CustomCountersignUserTaskCmd(BpmnCountersignTypeEnum.valueOfType(dto.getCountersignType()), dto.getTaskId(), - dto.getOriginAssigner(), dto.getAdvice(), dto.getAttachmentList(), dto.getTargetAssignerList(), - extAxHiTaskInstService)); + if (dto.getAsync() != null && dto.getAsync()) { + //异步处理 + commandExecutor.execute(new CustomCountersignUserTaskAsyncCmd(dto)); + } else { + commandExecutor.execute(new CustomCountersignUserTaskCmd(BpmnCountersignTypeEnum.valueOfType(dto.getCountersignType()), dto.getTaskId(), + dto.getOriginAssigner(), dto.getAdvice(), dto.getAttachmentList(), dto.getTargetAssignerList(), + extAxHiTaskInstService)); + } } @Override