提交 8bc7ed85 编写于 作者: doc_wei's avatar doc_wei

Activiti5升级flowable

无相关合并请求
......@@ -72,6 +72,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<flowable.version>6.4.2</flowable.version>
</properties>
<dependencies>
......
文件已删除
......@@ -28,23 +28,33 @@
<artifactId>skyeye-userauth</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- activiti工作流 -->
<!-- flowable 核心包 -->
<dependency>
<groupId>org.flowable</groupId>
<artifactId>flowable-spring-boot-starter</artifactId>
<version>${flowable.version}</version>
</dependency>
<!-- flowable json转换包 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>${activiti.version}</version>
<groupId>org.flowable</groupId>
<artifactId>flowable-json-converter</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-actuator</artifactId>
<version>${activiti.version}</version>
<groupId>org.flowable</groupId>
<artifactId>flowable-bpmn-converter</artifactId>
<version>${flowable.version}</version>
</dependency>
<!-- flowable 设计器接口包 -->
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-rest</artifactId>
<version>${activiti.version}</version>
<groupId>org.flowable</groupId>
<artifactId>flowable-ui-modeler-rest</artifactId>
<version>${flowable.version}</version>
</dependency>
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-codec</artifactId>
......@@ -65,38 +75,6 @@
<artifactId>batik-svggen</artifactId>
<version>1.7</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-explorer</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.vaadin.addons</groupId>
<artifactId>dcharts-widget</artifactId>
<version>0.10.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/dcharts-widget-0.10.0.jar</systemPath>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-modeler</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-diagram-rest</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-simple-workflow</artifactId>
<version>${activiti.version}</version>
</dependency>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring</artifactId>
<version>${activiti.version}</version>
</dependency>
</dependencies>
<build>
......
package com.skyeye.activiti.cmd.rollback;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Gateway;
import org.flowable.bpmn.model.SequenceFlow;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.HistoricTaskInstanceQueryImpl;
import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import java.util.*;
import java.util.stream.Collectors;
/**
*
* @ClassName: AbstractGateWayRollbackOperateStrategy
* @Description:
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:29
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
@Slf4j
public abstract class AbstractGateWayRollbackOperateStrategy extends AbstractRollbackOperateStrategy{
public AbstractGateWayRollbackOperateStrategy(RollbackParamsTemplate paramsTemplate) {
super(paramsTemplate);
}
@Override
public void existNextFinishedTask() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
List<HistoricTaskInstance> historicTaskInstanceList = CommandContextUtil.getHistoricTaskService(commandContext)
.findHistoricTaskInstancesByQueryCriteria(
(HistoricTaskInstanceQueryImpl) new HistoricTaskInstanceQueryImpl()
.finished()
.processInstanceId(hisTask.getProcessInstanceId())
.taskCompletedAfter(hisTask.getEndTime())
);
if (!historicTaskInstanceList
.stream()
.filter(obj -> paramsTemplate.getNextFlowIdList().contains(obj.getTaskDefinitionKey()))
.collect(Collectors.toList())
.isEmpty()) {
String msg = "存在已完成下一节点任务";
throw new FlowableException(msg);
}
}
@Override
public void deleteRuntimeTasks() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
// 删除正在执行任务
List<Task> taskList = CommandContextUtil.getTaskService(commandContext)
.createTaskQuery()
.processInstanceId(hisTask.getProcessInstanceId())
.taskCreatedAfter(hisTask.getEndTime())
.list();
taskList.stream()
.filter(obj -> paramsTemplate.getNextFlowIdList().contains(obj.getTaskDefinitionKey()))
.forEach(obj -> {
log.info("删除运行时任务:" + obj);
removeRuntimeTaskOperate((TaskEntity) obj);
});
// 删除历史任务
List<HistoricTaskInstanceEntity> historicTaskInstances = CommandContextUtil.getHistoricTaskService(commandContext)
.findHistoricTasksByProcessInstanceId(hisTask.getProcessInstanceId());
historicTaskInstances.forEach(obj -> {
if (obj.getCreateTime().getTime() <= hisTask.getEndTime().getTime() && paramsTemplate.getNextFlowIdList().contains(obj.getTaskDefinitionKey())) {
log.info("删除历史任务:" + obj);
CommandContextUtil.getHistoricTaskService(commandContext).deleteHistoricTask(obj);
}
});
}
/**
* 使用并行网关进行 线条流汇总时候,会出现 特殊bug
*
* @param parent
*/
protected void processGateway(ExecutionEntity parent) {
// 当前正在运行所以任务
List<TaskEntity> taskEntityList = CommandContextUtil.getTaskService(commandContext)
.findTasksByProcessInstanceId(parent.getProcessInstanceId());
boolean isExistPassGatewayTask = false;
// 下一节点任务
List<TaskEntity> nextTaskList = taskEntityList.stream()
.filter(obj -> paramsTemplate.getNextFlowIdList().contains(obj.getTaskDefinitionKey()))
.collect(Collectors.toList());
if (!nextTaskList.isEmpty()) {
log.info("已经生成过网关任务");
isExistPassGatewayTask = true;
// 网关的连线
Map<String, SequenceFlow> sqFlowMap = new HashMap<>();
paramsTemplate.getGatewayMap().values().forEach(obj -> {
obj.getIncomingFlows().forEach(item -> {
if (null != paramsTemplate.getGatewayMap().get(item.getSourceRef())) {
log.info("跳过gateway 间连线:" + item);
return;
}
if (paramsTemplate.getHisTask().getTaskDefinitionKey().equals(item.getSourceRef())) {
log.info("跳过当前回退历史任务:" + item);
return;
}
sqFlowMap.put(item.getSourceRef(), item);
});
});
// 创建网关相关连线 execution
createCompleteGatewayExecution(parent, sqFlowMap);
// 删除当前正在执行任务
Set<String> nestTaskIdSet = new HashSet<>();
nextTaskList.forEach(obj -> {
removeRuntimeTaskOperate(obj);
nestTaskIdSet.add(obj.getId());
});
// 移除正在执行下一节点历史任务
List<HistoricTaskInstanceEntity> historicTaskInstanceList = CommandContextUtil.getHistoricTaskService(commandContext)
.findHistoricTasksByProcessInstanceId(parent.getProcessInstanceId());
historicTaskInstanceList.forEach(obj -> {
if (nestTaskIdSet.contains(obj.getId())) {
CommandContextUtil.getHistoricTaskService(commandContext).deleteHistoricTask(obj);
}
});
}
if (isExistPassGatewayTask) {
} else {
log.info("移除网关连线");
List<ExecutionEntity> executionEntityList = CommandContextUtil.getExecutionEntityManager(commandContext)
.findExecutionsByParentExecutionAndActivityIds(parent.getProcessInstanceId(), paramsTemplate.getGatewayMap().keySet());
Map<String, FlowElement> targetGatewayMap = paramsTemplate.getCurrentTaskElement()
.getOutgoingFlows().stream().filter(obj -> obj.getTargetFlowElement() instanceof Gateway)
.map(obj -> obj.getTargetFlowElement())
.collect(Collectors.toMap(FlowElement::getId, obj -> obj));
List<ExecutionEntity> toRemoveList = new ArrayList<>();
executionEntityList.forEach(obj -> {
if (null != targetGatewayMap.get(obj.getActivityId())) {
toRemoveList.add(obj);
targetGatewayMap.put(obj.getActivityId(), null);
}
});
if (!toRemoveList.isEmpty()) {
toRemoveList.forEach(obj -> {
log.info("移除连线:" + obj);
CommandContextUtil.getExecutionEntityManager(commandContext).delete(obj);
});
}
}
}
/**
* 创建 Gateway 相关连线
*
* @param parent
* @param sqFlowMap
*/
protected void createCompleteGatewayExecution(ExecutionEntity parent, Map<String, SequenceFlow> sqFlowMap) {
sqFlowMap.values().forEach(obj -> {
ExecutionEntity newExecution = CommandContextUtil.getExecutionEntityManager(commandContext)
.createChildExecution(parent);
newExecution.setCurrentFlowElement(obj.getTargetFlowElement());
newExecution.setActive(false);
log.debug("创建 gateway 连线 execution");
CommandContextUtil.getAgenda(commandContext).planContinueProcessInCompensation(newExecution);
});
}
}
package com.skyeye.activiti.cmd.rollback;
import com.skyeye.activiti.mapper.HistoryActivityInstanceMapper;
import com.skyeye.common.util.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.impl.ActivityInstanceQueryImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.HistoricTaskInstanceQueryImpl;
import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @ClassName: AbstractRollbackOperateStrategy
* @Description:
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:30
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
@Slf4j
public abstract class AbstractRollbackOperateStrategy implements RollbackOperateStrategy {
protected RollbackParamsTemplate paramsTemplate;
/**
* 任务处理人
*/
protected String assignee;
protected Map<String, Object> variables;
protected CommandContext commandContext;
/**
* 无法操作
*/
protected HistoryActivityInstanceMapper historyActivityInstanceMapper;
protected RuntimeService runtimeService;
public AbstractRollbackOperateStrategy(RollbackParamsTemplate paramsTemplate) {
this.paramsTemplate = paramsTemplate;
this.historyActivityInstanceMapper = SpringUtils.getBean(HistoryActivityInstanceMapper.class);
this.runtimeService = SpringUtils.getBean(RuntimeService.class);
}
@Override
public void process(CommandContext commandContext, String assignee) {
process(commandContext, assignee, new HashMap<>());
}
@Override
public void process(CommandContext commandContext, String assignee, Map<String, Object> variables) {
this.commandContext = commandContext;
this.assignee = assignee;
this.variables = variables;
log.info("处理 existNextFinishedTask");
existNextFinishedTask();
log.info("配置任务执行人 setAssignee");
setAssignee();
log.info("处理 createExecution");
createExecution();
log.info("处理 deleteRuntimeTasks");
deleteRuntimeTasks();
log.info("处理 deleteHisActInstance");
deleteHisActInstance();
}
/**
* 获取 当前执行 execution
* @return
*/
protected ExecutionEntity getExecutionEntity() {
ExecutionEntity executionEntity = CommandContextUtil.getExecutionEntityManager(commandContext)
.findById(paramsTemplate.getHisTask().getExecutionId());
if (null == executionEntity) {
log.info("没找到回退任务的 execution,从同级任务处获取");
List<ExecutionEntity> executionEntityList = CommandContextUtil
.getExecutionEntityManager(commandContext)
.findExecutionsByParentExecutionAndActivityIds(paramsTemplate.getHisTask().getProcessInstanceId(), paramsTemplate.getNextFlowIdList());
if (executionEntityList.isEmpty()) {
throw new FlowableException("没有找到临近节点");
}
executionEntity = executionEntityList.get(0);
}
return executionEntity;
}
protected void removeHisTask(HistoricTaskInstance hisTask) {
// 移除历史任务列表
log.info("移除历史任务 [ id = " + hisTask.getId() + " ]");
CommandContextUtil.getHistoricTaskService().deleteHistoricTask((HistoricTaskInstanceEntity) hisTask);
}
/**
* 移除 ru_ 相关数据
* @param obj
*/
protected void removeRuntimeTaskOperate(TaskEntity obj) {
log.debug("移除 IdentityLink: " + obj.getId());
CommandContextUtil.getIdentityLinkService(commandContext).deleteIdentityLinksByTaskId(obj.getId());
log.debug("移除 Variable: " + obj.getId());
CommandContextUtil.getVariableService(commandContext).deleteVariablesByExecutionId(obj.getExecutionId());
log.debug("移除 Task: " + obj.getId());
CommandContextUtil.getTaskService(commandContext).deleteTasksByExecutionId(obj.getExecutionId());
log.debug("移除 execution: " + obj.getExecutionId());
CommandContextUtil.getExecutionEntityManager(commandContext).delete(obj.getExecutionId());
}
protected void createExecution(ExecutionEntity newExecution) {
newExecution.setActive(true);
// 测试设置变量
newExecution.setVariablesLocal(variables);
newExecution.setCurrentFlowElement(paramsTemplate.getCurrentTaskElement());
// 创建新任务
log.debug("创建新任务");
CommandContextUtil.getAgenda(commandContext).planContinueProcessInCompensation(newExecution);
}
@Override
public void existNextFinishedTask() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
List<HistoricTaskInstance> hisTaskList = CommandContextUtil.getHistoricTaskService().findHistoricTaskInstancesByQueryCriteria(
(HistoricTaskInstanceQueryImpl) new HistoricTaskInstanceQueryImpl()
.processInstanceId(hisTask.getProcessInstanceId())
.taskCompletedAfter(hisTask.getEndTime())
);
if (!hisTaskList.isEmpty()) {
hisTaskList.forEach(obj -> {
if (paramsTemplate.getNextFlowIdList().contains(obj.getTaskDefinitionKey())) {
String msg = "存在已完成下一节点任务";
throw new FlowableException(msg);
}
});
}
}
@Override
public void deleteHisActInstance() {
List<ActivityInstance> activityInstanceEntityList = CommandContextUtil.getActivityInstanceEntityManager(commandContext)
.findActivityInstancesByQueryCriteria(
new ActivityInstanceQueryImpl()
.processInstanceId(paramsTemplate.getHisTask().getProcessInstanceId())
);
List<String> ids = new ArrayList<>();
activityInstanceEntityList.forEach(obj -> {
// 时间大于 任务创建时间 之后线条
if (obj.getStartTime().getTime() > paramsTemplate.getHisTask().getCreateTime().getTime()
&& paramsTemplate.getNextFlowIdList().contains(obj.getActivityId())) {
ids.add(obj.getId());
}
// 当前任务的连线 ID
if (paramsTemplate.getHisTask().getTaskDefinitionKey().equals(obj.getActivityId())
&& obj.getEndTime().getTime() > paramsTemplate.getHisTask().getCreateTime().getTime()
) {
ids.add(obj.getId());
}
});
// 移除当前任务连线
// LOGGER.debug("移除当前任务连线");
// ids.forEach(obj -> CommandContextUtil.getActivityInstanceEntityManager(commandContext).delete(obj));
// 移除历史任务连线
// 历史任务删除失败,改用自己写mapper 完成删除功能
// ids.forEach(obj -> CommandContextUtil.getHistoricActivityInstanceEntityManager(commandContext).delete(obj));
log.debug("移除历史任务连线");
ids.forEach(obj -> historyActivityInstanceMapper.delete(obj));
}
@Override
public void deleteRuntimeTasks() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
List<TaskEntity> taskEntityList = CommandContextUtil.getTaskService(commandContext).findTasksByProcessInstanceId(hisTask.getProcessInstanceId());
taskEntityList.forEach(obj -> {
if (paramsTemplate.getNextFlowIdList().contains(obj.getTaskDefinitionKey())){
log.info("移除正在执行的下一节点任务");
// 移除任务
removeRuntimeTaskOperate(obj);
}
});
// 移除历史任务信息
List<HistoricTaskInstanceEntity> historicTaskInstanceList = CommandContextUtil.getHistoricTaskService(commandContext)
.findHistoricTasksByProcessInstanceId(hisTask.getProcessInstanceId());
historicTaskInstanceList.forEach(obj->{
if (paramsTemplate.getNextFlowIdList().contains(obj.getTaskDefinitionKey())){
CommandContextUtil.getHistoricTaskService(commandContext).deleteHistoricTask(obj);
}
});
}
@Override
public void setAssignee() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
String key = RollbackConstants.ASSIGNEE_PREFIX_KEY + hisTask.getProcessInstanceId() + hisTask.getTaskDefinitionKey();
variables.put(key, assignee);
}
@Override
public void setAssigneeExpr(String assigneeExpr, String assigneeListExpr) {
// to override
}
}
package com.skyeye.activiti.cmd.rollback;
import com.skyeye.activiti.cmd.rollback.impl.*;
import org.flowable.bpmn.model.*;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.TaskService;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.List;
/**
*
* @ClassName: DefaultRollbackStrategyFactoryBean
* @Description:
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:28
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
@Component
public class DefaultRollbackStrategyFactoryBean implements RollbackStrategyFactory {
private Logger LOGGER = LoggerFactory.getLogger(DefaultRollbackStrategyFactoryBean.class);
@Autowired
private RepositoryService repositoryService;
@Autowired
private TaskService taskService;
@Override
public RollbackOperateStrategy createStrategy(HistoricTaskInstance hisTask) {
BpmnModel bpmnModel = repositoryService.getBpmnModel(hisTask.getProcessDefinitionId());
RollbackParamsTemplate template = new RollbackParamsTemplate();
template.setHisTask(hisTask);
// 获取当前任务的节点信息
getThisUserTask(template, bpmnModel, hisTask);
// 获取下一节点信息
getNextElementInfo(template, bpmnModel);
// 创建策略
RollbackOperateStrategy strategy = createStrategyInstance(template);
return strategy;
}
/**
* @param template
* @return
*/
@Override
public boolean currentMultiInstanceTaskUnfinished(RollbackParamsTemplate template) {
if (template.getCurrentTaskElement().getLoopCharacteristics() == null) {
LOGGER.info("当前任务节点不是会签节点");
return false;
}
long count = taskService.createTaskQuery()
.processInstanceId(template.getHisTask().getProcessInstanceId())
.taskDefinitionKey(template.getHisTask().getTaskDefinitionKey())
.count();
if (count > 0) {
LOGGER.info("具有未完成当前节点任务");
return true;
}
return false;
}
/**
* 生成策略
*
* @param template
* @return
*/
private RollbackOperateStrategy createStrategyInstance(RollbackParamsTemplate template) {
// 处理正在执行会签节点
if (currentMultiInstanceTaskUnfinished(template)) {
LOGGER.info("-回退 正在执行会签 策略");
return new ActiveMultiInstanceTaskRollbackOperateStrategy(template);
}
// 默认节点处理策略
if (template.getCurrentTaskElement().getLoopCharacteristics() == null
&& template.getGatewayMap().isEmpty()
&& !template.getNextUserTaskList().isEmpty()) {
LOGGER.info("-回退 普通任务 策略");
return new NextDefaultUserTaskRollbackOperateStrategy(template);
}
// 下一节点 嵌入式子流程
if (template.getCurrentTaskElement().getLoopCharacteristics() == null
&& template.getGatewayMap().isEmpty()
&& !template.getSubProcessMap().isEmpty()) {
LOGGER.info("-回退 嵌入式子流程 策略");
return new NextSubProcessRollbackOperateStrategy(template);
}
// 下一节点 调用式子流程
if (template.getCurrentTaskElement().getLoopCharacteristics() == null
&& template.getGatewayMap().isEmpty()
&& !template.getCallActivityMap().isEmpty()) {
LOGGER.info("-回退 调用式子流程 策略");
return new NextCallActivityRollbackOperateStrategy(template);
}
// 下一节点 网关,多级网关
if (template.getCurrentTaskElement().getLoopCharacteristics() == null
&& !template.getGatewayMap().isEmpty()) {
LOGGER.info("-回退 网关, 多级网关 策略");
return new DefaultTaskNextGatewayRollbackOperateStrategy(template);
}
// 会签已完成
if (template.getCurrentTaskElement().getLoopCharacteristics() != null) {
if ( template.getGatewayMap().isEmpty()
&& !template.getNextUserTaskList().isEmpty()) {
LOGGER.info("-回退 已完成会签,下一节点普通任务 策略");
return new CompletedMultiInstanceTaskAndNextDefaultTaskRollbackOperateStrategy(template);
}
return null;
}
return null;
}
/**
* 获取下一节点任务
*
* @param template
* @param bpmnModel
*/
private void getNextElementInfo(RollbackParamsTemplate template, BpmnModel bpmnModel) {
if (null != template.getCurrentSubProcess()) {
LOGGER.info("当前任务存在于 SubProcess");
getNextElementInfo(template, template.getCurrentSubProcess(), template.getCurrentTaskElement().getOutgoingFlows());
return;
}
LOGGER.info("当前任务存在于 bpmnModel");
// 主线流程图
getNextElementInfo(template, bpmnModel.getMainProcess(), template.getCurrentTaskElement().getOutgoingFlows());
}
/**
* 获取下一节点网关任务
*
* @param template
* @param flowElementsContainer
* @param outgoingFlows
*/
private void getNextElementInfo(RollbackParamsTemplate template, FlowElementsContainer flowElementsContainer, List<SequenceFlow> outgoingFlows) {
for (SequenceFlow flow : outgoingFlows) {
template.getNextFlowIdList().add(flow.getId());
template.getOutGoingMap().put(flow.getId(), flow);
// 下一节点
FlowElement flowElement = flowElementsContainer.getFlowElement(flow.getTargetRef());
template.getNextFlowIdList().add(flowElement.getId());
if (flowElement instanceof UserTask) {
LOGGER.info("下一节点:UserTask");
template.getNextUserTaskList().add((UserTask) flowElement);
} else if (flowElement instanceof Gateway) {
LOGGER.info("下一节点:Gateway");
Gateway gateway = ((Gateway) flowElement);
template.getGatewayMap().put(gateway.getId(), gateway);
getNextElementInfo(template, flowElementsContainer, gateway.getOutgoingFlows());
} else if (flowElement instanceof SubProcess) {
LOGGER.info("下一节点:SubProcess");
SubProcess subProcess = (SubProcess) flowElement;
template.getSubProcessMap().put(subProcess.getId(), subProcess);
} else if (flowElement instanceof CallActivity) {
LOGGER.info("下一节点:CallActivity");
CallActivity callActivity = (CallActivity) flowElement;
template.getCallActivityMap().put(callActivity.getId(), callActivity);
}
}
}
/**
* 获取当前任务
*
* @param template
* @param bpmnModel
* @param hisTask
*/
private void getThisUserTask(RollbackParamsTemplate template, BpmnModel bpmnModel, HistoricTaskInstance hisTask) {
FlowElement flowElement = bpmnModel.getMainProcess().getFlowElement(hisTask.getTaskDefinitionKey());
if (null != flowElement && flowElement instanceof UserTask) {
LOGGER.info("获取回退任务节点");
template.setCurrentTaskElement((UserTask) flowElement);
return;
}
for (FlowElement item : bpmnModel.getMainProcess().getFlowElements()) {
if (item instanceof SubProcess) {
flowElement = ((SubProcess) item).getFlowElement(hisTask.getTaskDefinitionKey());
if (null != flowElement) {
LOGGER.info("当前节点存在于嵌入式子流程");
template.setCurrentTaskElement((UserTask) flowElement);
template.setCurrentSubProcess((SubProcess) item);
return;
}
}
}
LOGGER.error("没有获取回退任务节点");
}
}
package com.skyeye.activiti.cmd.rollback;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.impl.interceptor.Command;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.skyeye.common.util.SpringUtils;
/**
*
* @ClassName: RollbackCmd
* @Description:
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:26
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
public class RollbackCmd implements Command {
private Logger LOGGER = LoggerFactory.getLogger(RollbackCmd.class);
/**
* 任务ID
*/
private String taskId;
private String assignee;
private HistoryService historyService;
private RuntimeService runtimeService;
private RollbackStrategyFactory rollbackStrategyFactory;
/**
* 会签任务 单个执行人 表达式
*/
private String assigneeExpr = "assignee";
/**
* 会签任务 集合 表达式
*/
private String assigneeListExpr = "assigneeList";
public RollbackCmd(String taskId, String assignee) {
this.taskId = taskId;
this.assignee = assignee;
this.historyService = SpringUtils.getBean(HistoryService.class);
this.runtimeService = SpringUtils.getBean(RuntimeService.class);
this.rollbackStrategyFactory = SpringUtils.getBean(RollbackStrategyFactory.class);
}
@Override
public Object execute(CommandContext commandContext) {
HistoricTaskInstance hisTask = historyService.createHistoricTaskInstanceQuery().taskId(taskId).singleResult();
if (null == hisTask.getEndTime()){
String msg = "任务正在执行,不需要回退";
LOGGER.error(msg);
throw new FlowableException(msg);
}
ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(hisTask.getProcessInstanceId()).singleResult();
if (null == pi) {
String msg = "该流程已经完成,无法进行任务回退。";
LOGGER.error(msg);
throw new FlowableException(msg);
}
RollbackOperateStrategy strategy = rollbackStrategyFactory.createStrategy(hisTask);
// 配置任务执行表达式
strategy.setAssigneeExpr(assigneeExpr, assigneeListExpr);
// 处理
strategy.process(commandContext, assignee);
// 判断下一节点类型,根据下一节点类型获得任务处理策略
return null;
}
}
package com.skyeye.activiti.cmd.rollback;
/**
*
* @ClassName: RollbackConstants
* @Description:
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:28
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
public interface RollbackConstants {
/**
* 配置 任务执行人变量
*/
String ASSIGNEE_PREFIX_KEY = "ROLLBACK_ASSIGNEE_PREFIX_";
/**
* 配置 任务执行人变量
*/
String TASK_TYPE_PREFIX_KEY = "ROLLBACK_TASK_TYPE_PREFIX_";
/**
* 会签任务变量
*/
interface MultiInstanceConstants{
String NR_OF_ACTIVE_INSTANCES = "nrOfActiveInstances";
String NR_OF_COMPLETE_INSTANCES = "nrOfCompletedInstances";
String NR_OF_INSTANCE = "nrOfInstances";
String LOOP_COUNTER = "loopCounter";
}
}
package com.skyeye.activiti.cmd.rollback;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import java.util.Map;
/**
*
* @ClassName: RollbackOperateStrategy
* @Description:
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:31
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
public interface RollbackOperateStrategy {
/**
* 处理
*/
void process(CommandContext commandContext, String assignee);
/**
* 处理
*/
void process(CommandContext commandContext, String assignee, Map<String, Object> variables);
/**
* 配置处理标识
* @param assigneeExpr
* @param assigneeListExpr
*/
void setAssigneeExpr(String assigneeExpr, String assigneeListExpr);
/**
* 配置任务处理人
*/
void setAssignee();
/**
* 移除相关关联
*/
void existNextFinishedTask();
/**
* 移除历史痕迹
*/
void deleteHisActInstance();
/**
* 移除正在运行的任务
*/
void deleteRuntimeTasks();
/**
* 创建任务
*/
void createExecution();
}
package com.skyeye.activiti.cmd.rollback;
import lombok.Data;
import org.flowable.bpmn.model.*;
import org.flowable.task.api.history.HistoricTaskInstance;
import java.util.*;
/**
* @ClassName: RollbackParamsTemplate
* @Author: huangrenhao
* @Description:
* @CreateTime: 2020/3/23 0023 下午 3:52
* @Version:
**/
@Data
public class RollbackParamsTemplate {
/**
* 回滚任务
*/
private HistoricTaskInstance hisTask;
/**
* 当前任务节点
*/
private UserTask currentTaskElement;
/**
* 当前节点到下一任务节点间的连线(不包含当前任务节点)
*/
private Set<String> nextFlowIdList = new HashSet<>();
/**
* 当前任务节点到 下一节点 之间线条
*/
private Map<String, SequenceFlow> outGoingMap = new HashMap<>();
/**
* 下一任务节点 集合
*/
private List<UserTask> nextUserTaskList = new ArrayList<>();
/**
* 到下一任务节点 之间的网关集合
*/
private Map<String, Gateway> gatewayMap = new HashMap<>();
/**
* 下一节点是否为 嵌入式子流程
*/
private Map<String, SubProcess> subProcessMap = new HashMap<>();
/**
* 下一节点是否为 调用子流程
*/
private Map<String, CallActivity> callActivityMap = new HashMap<>();
/**
* 当前 嵌入子流程
*/
private SubProcess currentSubProcess;
}
package com.skyeye.activiti.cmd.rollback;
import org.flowable.task.api.history.HistoricTaskInstance;
/**
* @ClassName: RollbackStrategyFactory
* @Author: huangrenhao
* @Description:
* @CreateTime: 2020/3/23 0023 下午 3:33
* @Version:
**/
public interface RollbackStrategyFactory {
/**
* 创建回滚策略
* @param hisTask
* @return
*/
RollbackOperateStrategy createStrategy(HistoricTaskInstance hisTask);
/**
* 当前任务未完成判定
* @param template
* @return
*/
boolean currentMultiInstanceTaskUnfinished(RollbackParamsTemplate template);
}
package com.skyeye.activiti.cmd.rollback.impl;
import com.skyeye.activiti.cmd.rollback.AbstractRollbackOperateStrategy;
import com.skyeye.activiti.cmd.rollback.RollbackConstants;
import com.skyeye.activiti.cmd.rollback.RollbackParamsTemplate;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.common.engine.impl.interceptor.CommandContext;
import org.flowable.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.HistoricTaskInstanceQueryImpl;
import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.flowable.variable.service.impl.HistoricVariableInstanceQueryImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
*
* @ClassName: ActiveMultiInstanceTaskRollbackOperateStrategy
* @Description: 正在执行会签回滚 ,兼容嵌入式子流程
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:25
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
@Slf4j
public class ActiveMultiInstanceTaskRollbackOperateStrategy extends AbstractRollbackOperateStrategy {
private static Logger LOGGER = LoggerFactory.getLogger(NextDefaultUserTaskRollbackOperateStrategy.class);
public ActiveMultiInstanceTaskRollbackOperateStrategy(RollbackParamsTemplate paramsTemplate) {
super(paramsTemplate);
}
boolean isSequential = false;
/**
* 会签任务 单个执行人 表达式
*/
private String assigneeExpr = "assignee";
/**
* 会签任务 集合 表达式
*/
private String assigneeListExpr = "assigneeList";
@Override
public void process(CommandContext commandContext, String assignee, Map<String, Object> variables) {
this.commandContext = commandContext;
this.assignee = assignee;
this.variables = variables;
// 串行会签
if (paramsTemplate.getCurrentTaskElement().getBehavior() instanceof SequentialMultiInstanceBehavior) {
isSequential = true;
} else if (paramsTemplate.getCurrentTaskElement().getBehavior() instanceof MultiInstanceActivityBehavior) {
isSequential = false;
}
LOGGER.info("创建实例");
createExecution();
}
@Override
public void setAssigneeExpr(String assigneeExpr, String assigneeListExpr) {
this.assigneeExpr = assigneeExpr;
this.assigneeListExpr = assigneeListExpr;
}
@Override
public void createExecution() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
List<Task> currentTaskList = CommandContextUtil.getTaskService(commandContext)
.createTaskQuery()
.processInstanceId(hisTask.getProcessInstanceId())
.taskDefinitionKey(hisTask.getTaskDefinitionKey())
.list();
if (currentTaskList.isEmpty()) {
String msg = "当前会签任务已经完成";
throw new FlowableException(msg);
}
if (!isSequential) {
LOGGER.info("处理并行会签");
processMultiInstance();
} else {
LOGGER.info("处理串行会签");
processSequentialInstance();
}
}
/**
* 处理串行会签
* 串行特殊场景 : 下一个顺序执行人已完成任务,当前历史任务不可回退
* a -> b -> c -> d
* b 任务完成时, a 任务不可回退
*/
private void processSequentialInstance() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
// 确认是否具有下一线性完成任务
existNextFinishedTask(hisTask);
// 进行任务回退操作
ExecutionEntity executionEntity = processCommon(hisTask);
if (executionEntity.getId().equals(hisTask.getExecutionId())) {
log.info("未生成过下一节点");
// 移除正在执行任务
List<TaskEntity> taskEntityList = CommandContextUtil.getTaskService(commandContext).findTasksByExecutionId(executionEntity.getId());
taskEntityList.forEach(obj -> {
LOGGER.info("移除正在当前任务记录 [ id = " + obj.getId() + " ] ");
CommandContextUtil.getTaskService(commandContext).deleteTask(obj, true);
HistoricTaskInstance historicTaskInstance = CommandContextUtil.getHistoricTaskService(commandContext).getHistoricTask(obj.getId());
CommandContextUtil.getHistoricTaskService(commandContext).deleteHistoricTask((HistoricTaskInstanceEntity) historicTaskInstance);
});
// 配置任务执行人
executionEntity.setVariable(assigneeExpr, assignee);
// 计数器前置一位
int loopCounter = (int) executionEntity.getVariable(RollbackConstants.MultiInstanceConstants.LOOP_COUNTER);
executionEntity.setVariable(RollbackConstants.MultiInstanceConstants.LOOP_COUNTER, loopCounter - 1);
// 将任务重新激活
executionEntity.setActive(true);
// 创建新任务
CommandContextUtil.getAgenda(commandContext).planContinueProcessInCompensation(executionEntity);
} else {
log.info("已生成过下一任务节点,无法找到当前 execution");
List<Task> taskList = CommandContextUtil.getTaskService(commandContext).createTaskQuery()
.processInstanceId(hisTask.getProcessInstanceId())
.taskDefinitionKey(hisTask.getTaskDefinitionKey())
.list();
Task currentTask = taskList.get(0);
Integer currentLoopCounter = (Integer) runtimeService.getVariableLocal(currentTask.getExecutionId(), RollbackConstants.MultiInstanceConstants.LOOP_COUNTER);
List<String> assigneeList = (List<String>) runtimeService.getVariableLocal(currentTask.getProcessInstanceId(), assigneeListExpr);
if (StringUtils.isEmpty(hisTask.getAssignee())) {
throw new FlowableException("没有找到历史任务执行人,无法进行 执行顺序判断");
}
int index = assigneeList.indexOf(hisTask.getAssignee());
if (index == -1) {
throw new FlowableException("执行人不存在于初始参数,无法进行 执行顺序判断");
}
if (index != currentLoopCounter - 1) {
throw new FlowableException("任务执行人不是 当前执行人的前位 , 不合法回退");
}
// 持久化变量
assigneeList.set(index, assignee);
runtimeService.setVariableLocal(currentTask.getProcessInstanceId(), assigneeListExpr, assigneeList);
// 修改变量
ExecutionEntity newExecution = CommandContextUtil.getExecutionEntityManager(commandContext).findById(currentTask.getExecutionId());
newExecution.setVariableLocal(RollbackConstants.MultiInstanceConstants.LOOP_COUNTER, currentLoopCounter - 1);
newExecution.setVariableLocal(assigneeExpr, assignee);
// 创建新任务
CommandContextUtil.getAgenda(commandContext).planContinueMultiInstanceOperation(newExecution, executionEntity, currentLoopCounter - 1);
// 移除当前任务
CommandContextUtil.getTaskService(commandContext).deleteTask((TaskEntity) currentTask, true);
// 移除历史任务
HistoricTaskInstance historicTaskInstance = CommandContextUtil.getHistoricTaskService(commandContext).getHistoricTask(currentTask.getId());
CommandContextUtil.getHistoricTaskService(commandContext).deleteHistoricTask((HistoricTaskInstanceEntity) historicTaskInstance);
}
// 移除当前历史任务
removeHisTask(hisTask);
}
public void existNextFinishedTask(HistoricTaskInstance hisTask) {
List<HistoricTaskInstance> list = CommandContextUtil.getHistoricTaskService().findHistoricTaskInstancesByQueryCriteria(
(HistoricTaskInstanceQueryImpl) new HistoricTaskInstanceQueryImpl()
.processInstanceId(hisTask.getProcessInstanceId())
.taskDefinitionKey(hisTask.getTaskDefinitionKey())
.finished()
.taskCompletedAfter(hisTask.getEndTime())
);
if (!list.isEmpty()) {
String msg = "串行会签回滚,已经具有下一线性完成任务,无法进行任务回退";
LOGGER.error(msg);
throw new FlowableException(msg);
}
}
/**
* 处理并行会签
*/
private void processMultiInstance() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
// 通用操作部分
ExecutionEntity executionEntity = processCommon(hisTask);
// 未生成过下一节点
if (executionEntity.getId().equals(hisTask.getExecutionId())) {
log.info("未生成过下一节点");
// 配置任务执行人
executionEntity.setVariable(assigneeExpr, assignee);
// 将任务重新激活
executionEntity.setActive(true);
// 创建新任务
CommandContextUtil.getAgenda(commandContext).planContinueProcessInCompensation(executionEntity);
} else {
log.info("已生成过下一任务节点,无法找到当前 execution");
List<HistoricVariableInstance> historicVariableInstanceList = CommandContextUtil.getHistoricVariableService().findHistoricVariableInstancesByQueryCriteria(
new HistoricVariableInstanceQueryImpl()
.processInstanceId(hisTask.getProcessInstanceId())
.executionId(hisTask.getExecutionId())
);
Map<String, Object> hisVarMap = historicVariableInstanceList.stream().collect(Collectors.toMap(HistoricVariableInstance::getVariableName, item -> item.getValue()));
// 流程执行变量
Integer loopCounter = (Integer) hisVarMap.get(RollbackConstants.MultiInstanceConstants.LOOP_COUNTER);
List<ExecutionEntity> executionEntities = CommandContextUtil.getExecutionEntityManager(commandContext)
.findChildExecutionsByParentExecutionId(executionEntity.getId());
List<ExecutionEntity> linkExecutions = executionEntities.stream()
.filter(obj -> {
if (!obj.isActive()) {
Integer currentLoopCounter = (Integer) obj.getVariable(RollbackConstants.MultiInstanceConstants.LOOP_COUNTER);
if (currentLoopCounter.equals(loopCounter)) {
return true;
}
}
return false;
}).collect(Collectors.toList());
if (linkExecutions.isEmpty()) {
throw new FlowableException("没有找到映射节点");
}
ExecutionEntity newExecution = linkExecutions.get(0);
newExecution.setCurrentFlowElement(paramsTemplate.getCurrentTaskElement());
newExecution.setActive(true);
newExecution.setVariables(hisVarMap);
newExecution.setVariable(assigneeExpr, assignee);
// 创建新任务
CommandContextUtil.getAgenda(commandContext).planContinueMultiInstanceOperation(newExecution, executionEntity, loopCounter);
}
// 移除当前历史任务
removeHisTask(hisTask);
}
/**
* 通用处理逻辑
*
* @param hisTask
* @return
*/
private ExecutionEntity processCommon(HistoricTaskInstance hisTask) {
ExecutionEntity executionEntity = CommandContextUtil
.getExecutionEntityManager(commandContext).findById(hisTask.getExecutionId());
if (null == executionEntity) {
LOGGER.error("没有找到历史任务[ executionId = " + hisTask.getExecutionId() + " ]");
// List<ExecutionEntity> executionEntityList = CommandContextUtil
// .getExecutionEntityManager(commandContext)
// .findExecutionsByParentExecutionAndActivityIds(hisTask.getProcessInstanceId(), Collections.singletonList(hisTask.getTaskDefinitionKey()));
List<Task> taskEntityList = CommandContextUtil.getTaskService(commandContext)
.createTaskQuery()
.processInstanceId(hisTask.getProcessInstanceId())
.taskDefinitionKey(hisTask.getTaskDefinitionKey())
.list();
executionEntity = CommandContextUtil.getExecutionEntityManager(commandContext).findById(taskEntityList.get(0).getExecutionId());
}
ExecutionEntity parentExecutionEntity = CommandContextUtil
.getExecutionEntityManager(commandContext).findById(executionEntity.getParentId());
/**
* 将计数器 进行 前移
*/
int nrOfActiveInstances = (int) parentExecutionEntity.getVariable(RollbackConstants.MultiInstanceConstants.NR_OF_ACTIVE_INSTANCES);
int nrOfCompletedInstances = (int) parentExecutionEntity.getVariable(RollbackConstants.MultiInstanceConstants.NR_OF_COMPLETE_INSTANCES);
runtimeService.setVariable(parentExecutionEntity.getId(), RollbackConstants.MultiInstanceConstants.NR_OF_ACTIVE_INSTANCES, nrOfActiveInstances + 1);
runtimeService.setVariable(parentExecutionEntity.getId(), RollbackConstants.MultiInstanceConstants.NR_OF_COMPLETE_INSTANCES, nrOfCompletedInstances - 1);
return parentExecutionEntity;
}
}
package com.skyeye.activiti.cmd.rollback.impl;
import com.skyeye.activiti.cmd.rollback.AbstractRollbackOperateStrategy;
import com.skyeye.activiti.cmd.rollback.RollbackConstants;
import com.skyeye.activiti.cmd.rollback.RollbackParamsTemplate;
import lombok.extern.slf4j.Slf4j;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.flowable.engine.impl.bpmn.behavior.SequentialMultiInstanceBehavior;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.variable.api.history.HistoricVariableInstance;
import org.flowable.variable.service.impl.HistoricVariableInstanceQueryImpl;
import org.flowable.variable.service.impl.persistence.entity.VariableInstanceEntity;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @ClassName: CompletedMultiInstanceTaskAndNextDefaultTaskRollbackOperateStrategy
* @Author: huangrenhao
* @Description: 已完成会签 , 下一节点是普通节点 进行回退
* @CreateTime: 2020/4/21 0021 上午 11:06
* @Version: 1.0
* {@link ParallelMultiInstanceBehavior}
* {@link SequentialMultiInstanceBehavior}
**/
@Slf4j
public class CompletedMultiInstanceTaskAndNextDefaultTaskRollbackOperateStrategy extends AbstractRollbackOperateStrategy {
private boolean isSequence = false;
/**
* 会签任务 单个执行人 表达式
*/
private String assigneeExpr = "assignee";
/**
* 会签任务 集合 表达式
*/
private String assigneeListExpr = "assigneeList";
public CompletedMultiInstanceTaskAndNextDefaultTaskRollbackOperateStrategy(RollbackParamsTemplate paramsTemplate) {
super(paramsTemplate);
}
@Override
public void createExecution() {
if (paramsTemplate.getCurrentTaskElement().getBehavior() instanceof SequentialMultiInstanceBehavior) {
isSequence = true;
}
// 获取 execution
ExecutionEntity executionEntity = getExecutionEntity();
VariableInstanceEntity obj = CommandContextUtil.getVariableService(commandContext)
.findVariableInstanceByExecutionAndName(executionEntity.getProcessInstanceId(), assigneeListExpr);
if (obj == null || !(obj.getValue() instanceof Collection)) {
throw new FlowableException("没有可用会签参数:" + assigneeListExpr);
}
// 会签执行人变量
Collection assignees = (Collection) obj.getValue();
List<HistoricVariableInstance> historicVariableInstances = CommandContextUtil.getHistoricVariableService()
.findHistoricVariableInstancesByQueryCriteria(
new HistoricVariableInstanceQueryImpl()
.executionId(paramsTemplate.getHisTask().getExecutionId())
);
if (historicVariableInstances.isEmpty()) {
throw new FlowableException("没有可用会签任务参数");
}
// 历史变量
Map<String, Object> hisVarMap = historicVariableInstances.stream().collect(Collectors.toMap(HistoricVariableInstance::getVariableName, item -> item.getValue()));
if (hisVarMap.containsKey(assigneeExpr) && hisVarMap.containsKey(RollbackConstants.MultiInstanceConstants.LOOP_COUNTER)) {
log.info("变量有效");
} else {
throw new FlowableException("缺少会签任务变量");
}
/**
* 串行 最终的 loopCounter assignee 都会是最后一个人
*/
if (isSequence) {
List<String> assigneeList = (List<String>) runtimeService.getVariableLocal(paramsTemplate.getHisTask().getProcessInstanceId(), assigneeListExpr);
if (!assigneeList.get(assigneeList.size() - 1).equals(paramsTemplate.getHisTask().getAssignee())) {
String msg = "不是串行最后一个节点,无法进行回退 ";
throw new FlowableException(msg);
}
// 替换任务执行变量
assigneeList.set(assigneeList.size() - 1, assignee);
runtimeService.setVariableLocal(paramsTemplate.getHisTask().getProcessInstanceId(), assigneeListExpr, assigneeList);
}
// 流程执行变量
Integer loopCounter = (Integer) hisVarMap.get(RollbackConstants.MultiInstanceConstants.LOOP_COUNTER);
// 会签主任务
ExecutionEntity parentExecution = CommandContextUtil.getExecutionEntityManager(commandContext)
.createChildExecution(executionEntity.getParent());
parentExecution.setCurrentFlowElement(paramsTemplate.getCurrentTaskElement());
parentExecution.setActive(false);
// 配置 会签 root execution
parentExecution.setMultiInstanceRoot(true);
// 配置主 execution 变量
Map<String, Object> parentVarMap = new HashMap<>();
parentVarMap.put(RollbackConstants.MultiInstanceConstants.NR_OF_ACTIVE_INSTANCES, 1);
parentVarMap.put(RollbackConstants.MultiInstanceConstants.NR_OF_COMPLETE_INSTANCES, assignees.size() - 1);
parentVarMap.put(RollbackConstants.MultiInstanceConstants.NR_OF_INSTANCE, assignees.size());
parentExecution.setVariablesLocal(parentVarMap);
if (isSequence) {
log.info("创建 串行 会签任务");
createSequenceMultiInstance(parentExecution, assignees);
} else {
log.info("创建 并行 会签任务");
createParallelMultiInstance(parentExecution, assignees, loopCounter);
}
removeHisTask(paramsTemplate.getHisTask());
}
private void createSequenceMultiInstance(ExecutionEntity parentExecution, Collection assignees) {
ExecutionEntity newExecution = CommandContextUtil.getExecutionEntityManager(commandContext)
.createChildExecution(parentExecution);
Map<String, Object> varMap = new HashMap<>();
varMap.put(assigneeExpr, assignee);
varMap.put(RollbackConstants.MultiInstanceConstants.LOOP_COUNTER, assignees.size() - 1);
newExecution.setCurrentFlowElement(paramsTemplate.getCurrentTaskElement());
newExecution.setVariablesLocal(varMap);
newExecution.setActive(true);
CommandContextUtil.getAgenda(commandContext).planContinueMultiInstanceOperation(newExecution, parentExecution, assignees.size() - 1);
}
/**
* 创建并行会签任务
*
* @param parentExecution
* @param loopCounter
*/
private void createParallelMultiInstance(ExecutionEntity parentExecution, Collection assignees, Integer loopCounter) {
for (int i = 0; i < assignees.size(); i++) {
if (i != loopCounter) {
Map<String, Object> varMap = new HashMap<>();
varMap.put(RollbackConstants.MultiInstanceConstants.LOOP_COUNTER, i);
varMap.put(assigneeExpr, "已完成任务");
// // 创建 新执行任务
ExecutionEntity newExecution = newExecution = CommandContextUtil.getExecutionEntityManager(commandContext)
.createChildExecution(parentExecution);
newExecution.setCurrentFlowElement(paramsTemplate.getCurrentTaskElement());
newExecution.setActive(false);
newExecution.setVariablesLocal(varMap);
//
// CommandContextUtil.getExecutionEntityManager(commandContext)
// .update(newExecution);
} else {
ExecutionEntity newExecution = CommandContextUtil.getExecutionEntityManager(commandContext)
.createChildExecution(parentExecution);
newExecution.setCurrentFlowElement(paramsTemplate.getCurrentTaskElement());
Map<String, Object> varMap = new HashMap<>();
varMap.put(assigneeExpr, assignee);
varMap.put(RollbackConstants.MultiInstanceConstants.LOOP_COUNTER, i);
newExecution.setVariablesLocal(varMap);
newExecution.setActive(true);
CommandContextUtil.getAgenda(commandContext).planContinueMultiInstanceOperation(newExecution, parentExecution, loopCounter);
}
}
}
}
package com.skyeye.activiti.cmd.rollback.impl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.api.history.HistoricTaskInstance;
import com.skyeye.activiti.cmd.rollback.AbstractGateWayRollbackOperateStrategy;
import com.skyeye.activiti.cmd.rollback.RollbackConstants;
import com.skyeye.activiti.cmd.rollback.RollbackParamsTemplate;
import lombok.extern.slf4j.Slf4j;
/**
* @ClassName: DefaultTaskNextGatewayRollbackOperateStrategy
* @Author: huangrenhao
* @Description: 处理多级网关
* @CreateTime: 2020/4/16 0016 上午 11:45
* @Version:
**/
@Slf4j
public class DefaultTaskNextGatewayRollbackOperateStrategy extends AbstractGateWayRollbackOperateStrategy {
public DefaultTaskNextGatewayRollbackOperateStrategy(RollbackParamsTemplate paramsTemplate) {
super(paramsTemplate);
}
@Override
public void createExecution() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
// 获取正在执行 execution
ExecutionEntity executionEntity = getExecutionEntity();
ExecutionEntity newExecution = CommandContextUtil.getExecutionEntityManager(commandContext)
.createChildExecution(executionEntity.getParent());
// 创建新任务
createExecution(newExecution);
// 特殊处理并行网关
processGateway(executionEntity.getParent());
// 移除历史任务
removeHisTask(hisTask);
}
@Override
public void setAssignee() {
// 进行任务执行人配置,之后使用全局监听出发更新
super.setAssignee();
String type = RollbackConstants.TASK_TYPE_PREFIX_KEY + paramsTemplate.getHisTask().getProcessInstanceId()
+ paramsTemplate.getHisTask().getTaskDefinitionKey();
variables.put(type, DefaultTaskNextGatewayRollbackOperateStrategy.class.getSimpleName());
}
}
package com.skyeye.activiti.cmd.rollback.impl;
import com.skyeye.activiti.cmd.rollback.AbstractRollbackOperateStrategy;
import com.skyeye.activiti.cmd.rollback.RollbackConstants;
import com.skyeye.activiti.cmd.rollback.RollbackParamsTemplate;
import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.CallActivity;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.HistoricTaskInstanceQueryImpl;
import org.flowable.task.service.impl.persistence.entity.HistoricTaskInstanceEntity;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
*
* @ClassName: NextCallActivityRollbackOperateStrategy
* @Description:
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:27
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
@Slf4j
public class NextCallActivityRollbackOperateStrategy extends AbstractRollbackOperateStrategy {
/**
* 下一节点 callActivity
*/
private CallActivity callActivity;
private List<ExecutionEntity> callActivityExecutionList;
private ExecutionEntity callActivityProcess;
public NextCallActivityRollbackOperateStrategy(RollbackParamsTemplate paramsTemplate) {
super(paramsTemplate);
}
@Override
public void existNextFinishedTask() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
Map<String, CallActivity> callActivityMap = paramsTemplate.getCallActivityMap();
String key = callActivityMap.keySet().iterator().next();
this.callActivity = callActivityMap.get(key);
// 下一节点callActivity的 flowId
callActivityExecutionList = CommandContextUtil.getExecutionEntityManager(commandContext)
.findExecutionsByParentExecutionAndActivityIds(hisTask.getProcessInstanceId(), Collections.singletonList(callActivity.getId()));
// callActivity 在 父级流程的 executionId = 子流程的 processInstanceId
ExecutionEntity executionEntity = callActivityExecutionList.get(0);
// 子流程
callActivityProcess = CommandContextUtil.getExecutionEntityManager(commandContext)
.findSubProcessInstanceBySuperExecutionId(executionEntity.getId());
List<HistoricTaskInstance> hisTaskList = CommandContextUtil.getHistoricTaskService(commandContext)
.findHistoricTaskInstancesByQueryCriteria(
(HistoricTaskInstanceQueryImpl) new HistoricTaskInstanceQueryImpl()
.finished()
.processInstanceId(callActivityProcess.getId())
);
if (!hisTaskList.isEmpty()) {
throw new FlowableException("子流程已经具有完成的任务,流程无法回退");
}
}
@Override
public void setAssignee() {
// 进行任务执行人配置,之后使用全局监听出发更新
super.setAssignee();
String type = RollbackConstants.TASK_TYPE_PREFIX_KEY + paramsTemplate.getHisTask().getProcessInstanceId() + paramsTemplate.getHisTask().getTaskDefinitionKey();
variables.put(type, NextCallActivityRollbackOperateStrategy.class.getSimpleName());
}
@Override
public void createExecution() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
ExecutionEntity executionEntity = CommandContextUtil.getExecutionEntityManager(commandContext)
.findById(hisTask.getExecutionId());
if (null == executionEntity) {
log.info("没有找到execution");
executionEntity = callActivityExecutionList.get(0);
}
ExecutionEntity newExecution = CommandContextUtil.getExecutionEntityManager(commandContext)
.createChildExecution(executionEntity.getParent());
// 创建新任务
createExecution(newExecution);
// 移除历史任务
removeHisTask(hisTask);
}
@Override
public void deleteRuntimeTasks() {
ExecutionEntity parentExecution = callActivityExecutionList.get(0);
// 清理子流程
cleanCallActivityProcessInstance(callActivityProcess);
// 清理主流程记录
CommandContextUtil.getExecutionEntityManager(commandContext)
.delete(parentExecution);
}
/**
* // 无效操作
* CommandContextUtil.getExecutionEntityManager(commandContext)
* .deleteProcessInstance(callActivityProcess.getId(), "进行流程撤回", false);
* 清理 调用子流程 相关数据
*
* @param processInstance
*/
private void cleanCallActivityProcessInstance(ExecutionEntity processInstance) {
// 移除正在运行任务信息
List<Task> list = CommandContextUtil.getTaskService(commandContext)
.createTaskQuery()
.processInstanceId(processInstance.getId())
.list();
list.forEach(obj->removeRuntimeTaskOperate((TaskEntity) obj));
// 移除历史任务信息
List<HistoricTaskInstanceEntity> historicTaskInstanceList = CommandContextUtil.getHistoricTaskService(commandContext)
.findHistoricTasksByProcessInstanceId(processInstance.getId());
historicTaskInstanceList.forEach(obj->CommandContextUtil.getHistoricTaskService(commandContext).deleteHistoricTask(obj));
// 移除 子流程实例
CommandContextUtil.getIdentityLinkService(commandContext).deleteIdentityLinksByProcessInstanceId(processInstance.getId());
CommandContextUtil.getVariableService(commandContext).deleteVariablesByExecutionId(processInstance.getId());
CommandContextUtil.getExecutionEntityManager(commandContext).delete(processInstance.getId());
}
}
package com.skyeye.activiti.cmd.rollback.impl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.task.api.history.HistoricTaskInstance;
import com.skyeye.activiti.cmd.rollback.AbstractRollbackOperateStrategy;
import com.skyeye.activiti.cmd.rollback.RollbackConstants;
import com.skyeye.activiti.cmd.rollback.RollbackParamsTemplate;
/**
*
* @ClassName: NextDefaultUserTaskRollbackOperateStrategy
* @Description: 普通节点 ,兼容嵌入式子流程
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:29
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
public class NextDefaultUserTaskRollbackOperateStrategy extends AbstractRollbackOperateStrategy {
public NextDefaultUserTaskRollbackOperateStrategy(RollbackParamsTemplate paramsTemplate) {
super(paramsTemplate);
}
@Override
public void createExecution() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
// 获取正在执行 execution
ExecutionEntity executionEntity = getExecutionEntity();
ExecutionEntity newExecution = CommandContextUtil.getExecutionEntityManager(commandContext).createChildExecution(executionEntity.getParent());
// 创建新任务
createExecution(newExecution);
// 移除历史任务
removeHisTask(hisTask);
}
@Override
public void setAssignee() {
// 进行任务执行人配置,之后使用全局监听出发更新
super.setAssignee();
String type = RollbackConstants.TASK_TYPE_PREFIX_KEY + paramsTemplate.getHisTask().getProcessInstanceId()
+ paramsTemplate.getHisTask().getTaskDefinitionKey();
variables.put(type, NextDefaultUserTaskRollbackOperateStrategy.class.getSimpleName());
}
}
package com.skyeye.activiti.cmd.rollback.impl;
import com.skyeye.activiti.cmd.rollback.AbstractRollbackOperateStrategy;
import com.skyeye.activiti.cmd.rollback.RollbackConstants;
import com.skyeye.activiti.cmd.rollback.RollbackParamsTemplate;
import org.flowable.bpmn.model.SubProcess;
import org.flowable.common.engine.api.FlowableException;
import org.flowable.engine.impl.ActivityInstanceQueryImpl;
import org.flowable.engine.impl.persistence.entity.ExecutionEntity;
import org.flowable.engine.impl.util.CommandContextUtil;
import org.flowable.engine.runtime.ActivityInstance;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.flowable.task.service.impl.HistoricTaskInstanceQueryImpl;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
*
* @ClassName: NextSubProcessRollbackOperateStrategy
* @Description: 下一节点是 嵌入式子流程
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:31
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
public class NextSubProcessRollbackOperateStrategy extends AbstractRollbackOperateStrategy {
private Logger LOGGER = LoggerFactory.getLogger(NextSubProcessRollbackOperateStrategy.class);
/**
* 嵌入子流程中所有节点ID集合
*/
private Set<String> subProcessItemKeySet = new HashSet<>();
private SubProcess subProcess;
public NextSubProcessRollbackOperateStrategy(RollbackParamsTemplate paramsTemplate) {
super(paramsTemplate);
}
@Override
public void existNextFinishedTask() {
Map<String, SubProcess> subProcessMap = paramsTemplate.getSubProcessMap();
List<HistoricTaskInstance> historicTaskInstances = CommandContextUtil.getHistoricTaskService(commandContext)
.findHistoricTaskInstancesByQueryCriteria(
(HistoricTaskInstanceQueryImpl) new HistoricTaskInstanceQueryImpl()
.taskCompletedAfter(paramsTemplate.getHisTask().getEndTime())
.finished()
);
String key = subProcessMap.keySet().iterator().next();
this.subProcess = subProcessMap.get(key);
subProcess.getFlowElements().forEach(obj -> subProcessItemKeySet.add(obj.getId()));
if (!historicTaskInstances.isEmpty()) {
historicTaskInstances.forEach(obj -> {
if (subProcessItemKeySet.contains(obj.getTaskDefinitionKey())) {
LOGGER.error("出现已完成任务,无法进行流程节点撤回: [" + obj + "]");
throw new FlowableException("出现已完成任务,无法进行流程节点撤回");
}
});
}
}
@Override
public void setAssignee() {
// 进行任务执行人配置,之后使用全局监听出发更新
super.setAssignee();
String type = RollbackConstants.TASK_TYPE_PREFIX_KEY + paramsTemplate.getHisTask().getProcessInstanceId() + paramsTemplate.getHisTask().getTaskDefinitionKey();
variables.put(type, NextSubProcessRollbackOperateStrategy.class.getSimpleName());
}
@Override
public void createExecution() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
ExecutionEntity executionEntity = CommandContextUtil.getExecutionEntityManager(commandContext).findById(hisTask.getExecutionId());
/**
* subProcess 作为下一节点的时候,hisTask的execution会被关闭调。所以需要重新创建
*/
if (null == executionEntity) {
LOGGER.info("hisTask:execution 为 null");
List<ExecutionEntity> executionEntityList = CommandContextUtil
.getExecutionEntityManager(commandContext)
.findExecutionsByParentExecutionAndActivityIds(hisTask.getProcessInstanceId(), paramsTemplate.getNextFlowIdList());
if (executionEntityList.isEmpty()) {
throw new FlowableException("没有找到临近节点");
}
executionEntity = executionEntityList.get(0);
}
// 创建主线
ExecutionEntity newExecution = CommandContextUtil.getExecutionEntityManager(commandContext).createChildExecution(executionEntity.getParent());
// 创建新任务
createExecution(newExecution);
// 移除历史任务
removeHisTask(hisTask);
}
@Override
public void deleteHisActInstance() {
List<ActivityInstance> activityInstanceEntityList = CommandContextUtil.getActivityInstanceEntityManager(commandContext)
.findActivityInstancesByQueryCriteria(
new ActivityInstanceQueryImpl()
.processInstanceId(paramsTemplate.getHisTask().getProcessInstanceId())
);
List<String> ids = new ArrayList<>();
activityInstanceEntityList.forEach(obj -> {
// 时间大于 任务创建时间 之后线条
if (obj.getStartTime().getTime() > paramsTemplate.getHisTask().getCreateTime().getTime()
&& subProcessItemKeySet.contains(obj.getActivityId())) {
ids.add(obj.getId());
}
// 当前任务的连线 ID
if (paramsTemplate.getHisTask().getTaskDefinitionKey().equals(obj.getActivityId())
&& obj.getEndTime().getTime() > paramsTemplate.getHisTask().getCreateTime().getTime()
) {
ids.add(obj.getId());
}
});
LOGGER.debug("移除历史任务连线");
ids.forEach(obj -> historyActivityInstanceMapper.delete(obj));
}
@Override
public void deleteRuntimeTasks() {
HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
List<TaskEntity> taskEntityList = CommandContextUtil.getTaskService(commandContext).findTasksByProcessInstanceId(hisTask.getProcessInstanceId());
taskEntityList.forEach(obj -> {
if (subProcessItemKeySet.contains(obj.getTaskDefinitionKey())) {
LOGGER.info("移除正在执行的下一节点任务");
// 移除任务
removeRuntimeTaskOperate(obj);
}
});
// 获取 subProcess 的 ExecutionEntity
Collection<ExecutionEntity> executionEntities = CommandContextUtil
.getExecutionEntityManager(commandContext)
.findExecutionsByParentExecutionAndActivityIds(hisTask.getProcessInstanceId(), Collections.singletonList(subProcess.getId()));
executionEntities.forEach(obj -> {
LOGGER.info("移除 subProcess 层级execution");
List<ExecutionEntity> children = CommandContextUtil
.getExecutionEntityManager(commandContext)
.findChildExecutionsByParentExecutionId(obj.getId());
// 移除级联子节点
children.forEach(item -> CommandContextUtil
.getExecutionEntityManager(commandContext)
.delete(item));
// 移除 subProcess 顶级
CommandContextUtil
.getExecutionEntityManager(commandContext)
.delete(obj);
});
}
}
package com.skyeye.activiti.cmd.rollback.listeners;
import org.flowable.common.engine.api.delegate.event.FlowableEngineEventType;
import org.flowable.common.engine.api.delegate.event.FlowableEvent;
import org.flowable.common.engine.api.delegate.event.FlowableEventListener;
import org.flowable.common.engine.impl.event.FlowableEntityEventImpl;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.task.service.impl.persistence.entity.TaskEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import com.skyeye.activiti.cmd.rollback.RollbackConstants;
import com.skyeye.activiti.cmd.rollback.impl.DefaultTaskNextGatewayRollbackOperateStrategy;
import com.skyeye.activiti.cmd.rollback.impl.NextCallActivityRollbackOperateStrategy;
import com.skyeye.activiti.cmd.rollback.impl.NextDefaultUserTaskRollbackOperateStrategy;
import com.skyeye.activiti.cmd.rollback.impl.NextSubProcessRollbackOperateStrategy;
import com.skyeye.common.util.SpringUtils;
/**
*
* @ClassName: RollbackEventListener
* @Description:
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:24
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
@Component
public class RollbackEventListener implements FlowableEventListener {
private static Logger LOGGER = LoggerFactory.getLogger(RollbackEventListener.class);
@Override
public void onEvent(FlowableEvent event) {
if (FlowableEngineEventType.TASK_CREATED.name().equals(event.getType().name())) {
TaskEntity taskEntity = (TaskEntity)((FlowableEntityEventImpl)event).getEntity();
RuntimeService runtimeService = SpringUtils.getBean(RuntimeService.class);
TaskService taskService = SpringUtils.getBean(TaskService.class);
String key = RollbackConstants.ASSIGNEE_PREFIX_KEY + taskEntity.getProcessInstanceId()
+ taskEntity.getTaskDefinitionKey();
String type = RollbackConstants.TASK_TYPE_PREFIX_KEY + taskEntity.getProcessInstanceId()
+ taskEntity.getTaskDefinitionKey();
Object assigneeValue = runtimeService.getVariable(taskEntity.getExecutionId(), key);
Object assigneeType = runtimeService.getVariable(taskEntity.getExecutionId(), type);
if (assigneeValue != null && assigneeType != null) {
LOGGER.info("回滚任务处理");
if (NextDefaultUserTaskRollbackOperateStrategy.class.getSimpleName().equals(assigneeType)
|| NextSubProcessRollbackOperateStrategy.class.getSimpleName().equals(assigneeType)
|| NextCallActivityRollbackOperateStrategy.class.getSimpleName().equals(assigneeType)
|| DefaultTaskNextGatewayRollbackOperateStrategy.class.getSimpleName().equals(assigneeType)) {
LOGGER.info("设置普通任务执行人");
taskService.setAssignee(taskEntity.getId(), (String)assigneeValue);
}
}
}
}
@Override
public boolean isFailOnException() {
return false;
}
@Override
public boolean isFireOnTransactionLifecycleEvent() {
return false;
}
@Override
public String getOnTransaction() {
return null;
}
}
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.entity;
import javax.persistence.*;
@Table(name = "act_assignee")
public class ActAssignee {
@Id
@Column(name = "id")
private String id;
/**
* 节点id
*/
private String sid;
/**
* 办理人
*/
private String assignee;
/**
* 候选组(角色)
*/
@Column(name = "role_id")
private String roleId;
/**
* 办理人类型1办理人2候选人3组
*/
@Column(name = "assignee_type")
private Integer assigneeType;
/**
* 节点名称
*/
@Column(name = "activti_name")
private String activtiName;
/**
* @return id
*/
public String getId() {
return id;
}
/**
* @param id
*/
public void setId(String id) {
this.id = id == null ? null : id.trim();
}
/**
* 获取节点id
*
* @return sid - 节点id
*/
public String getSid() {
return sid;
}
/**
* 设置节点id
*
* @param sid
* 节点id
*/
public void setSid(String sid) {
this.sid = sid == null ? null : sid.trim();
}
/**
* 获取办理人
*
* @return assignee - 办理人
*/
public String getAssignee() {
return assignee;
}
/**
* 设置办理人
*
* @param assignee
* 办理人
*/
public void setAssignee(String assignee) {
this.assignee = assignee == null ? null : assignee.trim();
}
/**
* 获取候选组(角色)
*
* @return role_id - 候选组(角色)
*/
public String getRoleId() {
return roleId;
}
/**
* 设置候选组(角色)
*
* @param roleId
* 候选组(角色)
*/
public void setRoleId(String roleId) {
this.roleId = roleId == null ? null : roleId.trim();
}
/**
* 获取办理人类型1办理人2候选人3组
*
* @return assignee_type - 办理人类型1办理人2候选人3组
*/
public Integer getAssigneeType() {
return assigneeType;
}
/**
* 设置办理人类型1办理人2候选人3组
*
* @param assigneeType
* 办理人类型1办理人2候选人3组
*/
public void setAssigneeType(Integer assigneeType) {
this.assigneeType = assigneeType;
}
/**
* 获取节点名称
*
* @return activti_name - 节点名称
*/
public String getActivtiName() {
return activtiName;
}
/**
* 设置节点名称
*
* @param activtiName
* 节点名称
*/
public void setActivtiName(String activtiName) {
this.activtiName = activtiName == null ? null : activtiName.trim();
}
public ActAssignee() {
}
public ActAssignee(String sid) {
this.sid = sid;
}
}
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.entity;
import java.io.Serializable;
import java.util.Date;
import lombok.Getter;
import lombok.Setter;
import org.activiti.engine.repository.Deployment;
/**
*
* @author 卫志强
*
*/
@Getter
@Setter
public class ActDeployment implements Serializable {
private static final long serialVersionUID = 5337694999055428654L;
private String id;
private String name;
private Date deploymentTime;
private String category;
private String tenantId;
public ActDeployment() {
}
public ActDeployment(Deployment deployment) {
this.id = deployment.getId();
this.name = deployment.getName();
this.deploymentTime = deployment.getDeploymentTime();
this.category = deployment.getCategory();
this.tenantId = deployment.getTenantId();
}
}
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.entity;
import java.util.Date;
import lombok.Getter;
import lombok.Setter;
import org.activiti.engine.repository.Model;
/**
*
* @author 卫志强 模型列表
*/
@Getter
@Setter
public class ActModel {
private String id;
private String name;
private String key;
private String category;
private Date createTime;
private Date lastUpdateTime;
private Integer version;
private String metaInfo;
private String deploymentId;
private String tenantId;
private boolean hasEditorSource;
public ActModel() {
}
public ActModel(Model model) {
this.id = model.getId();
this.name = model.getName();
this.key = model.getKey();
this.category = model.getCategory();
this.createTime = model.getCreateTime();
this.lastUpdateTime = model.getLastUpdateTime();
this.version = model.getVersion();
this.metaInfo = model.getMetaInfo();
this.deploymentId = model.getDeploymentId();
this.tenantId = model.getTenantId();
this.hasEditorSource = model.hasEditorSource();
}
}
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.entity;
import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
/**
*
* @ClassName: BaseTask
* @Description: 工作流基础任务类
* @author: skyeye云系列--卫志强
* @date: 2021/7/4 17:38
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
@MappedSuperclass
public abstract class BaseTask implements Serializable {
private static final long serialVersionUID = 4551215350498340711L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "JDBC")
protected String id;
/**
* @return id
*/
public String getId() {
return id;
}
/**
* @param id
*/
public void setId(String id) {
this.id = id == null ? null : id.trim();
}
@Column(name = "user_id")
protected String userId;
@Column(name = "user_name")
protected String userName;
@Column(name = "process_instance_Id")
protected String processInstanceId;
protected String status;
@Column(name = "create_date")
protected Date createDate;
@Column(name = "create_by")
protected String createBy;
@Column(name = "update_date")
protected Date updateDate;
@Column(name = "update_by")
protected String updateBy;
protected String reason;
/**
* 实时节点信息
*/
protected String taskName;
private String urlpath;
private Integer submittimes;
/**
* @return user_id
*/
public String getUserId() {
return userId;
}
/**
* @param userId
*/
public void setUserId(String userId) {
this.userId = userId == null ? null : userId.trim();
}
/**
* @return user_name
*/
public String getUserName() {
return userName;
}
/**
* @param userName
*/
public void setUserName(String userName) {
this.userName = userName == null ? null : userName.trim();
}
/**
* @return reason
*/
public String getReason() {
return reason;
}
/**
* @param reason
*/
public void setReason(String reason) {
this.reason = reason == null ? null : reason.trim();
}
/**
* @return process_instance_Id
*/
public String getProcessInstanceId() {
return processInstanceId;
}
/**
* @param processInstanceId
*/
public void setProcessInstanceId(String processInstanceId) {
this.processInstanceId = processInstanceId == null ? null : processInstanceId.trim();
}
/**
* @return status
*/
public String getStatus() {
return status;
}
/**
* @param status
*/
public void setStatus(String status) {
this.status = status == null ? null : status.trim();
}
/**
* @return create_date
*/
public Date getCreateDate() {
return createDate;
}
/**
* @param createDate
*/
public void setCreateDate(Date createDate) {
this.createDate = createDate;
}
/**
* @return create_by
*/
public String getCreateBy() {
return createBy;
}
/**
* @param createBy
*/
public void setCreateBy(String createBy) {
this.createBy = createBy == null ? null : createBy.trim();
}
/**
* @return update_date
*/
public Date getUpdateDate() {
return updateDate;
}
/**
* @param updateDate
*/
public void setUpdateDate(Date updateDate) {
this.updateDate = updateDate;
}
/**
* @return update_by
*/
public String getUpdateBy() {
return updateBy;
}
/**
* @param updateBy
*/
public void setUpdateBy(String updateBy) {
this.updateBy = updateBy == null ? null : updateBy.trim();
}
public String getTaskName() {
return taskName;
}
public void setTaskName(String taskName) {
this.taskName = taskName;
}
public String getUrlpath() {
return urlpath;
}
public void setUrlpath(String urlpath) {
this.urlpath = urlpath;
}
public Integer getSubmittimes() {
return submittimes;
}
public void setSubmittimes(Integer submittimes) {
this.submittimes = submittimes;
}
}
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.entity;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.activiti.engine.repository.Deployment;
import org.activiti.rest.common.util.DateToStringSerializer;
import java.util.Date;
/**
*
* @author 卫志强
*
*/
public class DeploymentResponse {
private String id;
private String name;
@JsonSerialize(using = DateToStringSerializer.class, as = Date.class)
private Date deploymentTime;
private String category;
private String tenantId;
public DeploymentResponse(Deployment deployment) {
setId(deployment.getId());
setName(deployment.getName());
setDeploymentTime(deployment.getDeploymentTime());
setCategory(deployment.getCategory());
setTenantId(deployment.getTenantId());
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getDeploymentTime() {
return deploymentTime;
}
public void setDeploymentTime(Date deploymentTime) {
this.deploymentTime = deploymentTime;
}
public String getCategory() {
return category;
}
public void setCategory(String category) {
this.category = category;
}
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
public String getTenantId() {
return tenantId;
}
}
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.entity;
import java.io.Serializable;
import java.util.Date;
import lombok.Getter;
import lombok.Setter;
/**
*
* @author 卫志强 请假流程 审批信息
*/
@Getter
@Setter
public class LeaveOpinion implements Serializable {
private static final long serialVersionUID = -6536860710977259314L;
// 审批人id
private String opId;
// 审批人姓名
private String opName;
// 审批意见
private String opinion;
// 审批时间
private Date createTime;
// 是否通过
private boolean flag;
// 流程id
private String taskId;
}
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.entity;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
*
* @author 卫志强 流程定义实体
*/
@Getter
@Setter
@ToString
public class ProcessDefinition {
private String id;
private String category;
private String name;
private String key;
private String description;
private int version;
private String resourceName;
private String deploymentId;
private String diagramResourceName;
private boolean hasStartFormKey;
private boolean hasGraphicalNotation;
private boolean isSuspended;
private String tenantId;
public ProcessDefinition() {
}
public ProcessDefinition(org.activiti.engine.repository.ProcessDefinition p) {
this.id = p.getId();
this.category = p.getCategory();
this.name = p.getName();
this.key = p.getKey();
this.description = p.getDescription();
this.version = p.getVersion();
this.resourceName = p.getResourceName();
this.deploymentId = p.getDeploymentId();
this.diagramResourceName = p.getDiagramResourceName();
this.hasStartFormKey = p.hasStartFormKey();
this.hasGraphicalNotation = p.hasGraphicalNotation();
this.isSuspended = p.isSuspended();
this.tenantId = p.getTenantId();
}
}
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.entity;
import java.util.Date;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
/**
*
* @author 卫志强 流程任务
*/
@Getter
@Setter
@ToString
public class Task {
private String id;
private String name;
private Date createTime;
private String assignee;
private String processInstanceId;// 流程实例id
private String processDefinitionId;// 流程定义id
private String description;
private String category;
private String userName;
private String reason;
private String urlpath;
public Task() {
}
public Task(org.activiti.engine.task.Task t) {
this.id = t.getId();
this.name = t.getName();
this.createTime = t.getCreateTime();
this.assignee = t.getAssignee();
this.processInstanceId = t.getProcessInstanceId();
this.processDefinitionId = t.getProcessDefinitionId();
this.description = t.getDescription();
this.category = t.getCategory();
}
}
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.entity;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.persistence.*;
/**
*
* @author 卫志强
*
*/
@Table(name = "user_leave")
public class UserLeave extends BaseTask {
private static final long serialVersionUID = 9219826375746625710L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO, generator = "JDBC")
protected String id;
/**
* @return id
*/
@Override
public String getId() {
return id;
}
/**
* @param id
*/
@Override
public void setId(String id) {
this.id = id == null ? null : id.trim();
}
private Integer days;
@Column(name = "begin_time")
private Date beginTime;
@Column(name = "end_time")
private Date endTime;
@Column(name = "process_instance_Id")
private String processInstanceId;
private String status;
@Column(name = "create_date")
private Date createDate;
@Column(name = "create_by")
private String createBy;
@Column(name = "update_date")
private Date updateDate;
@Column(name = "update_by")
private String updateBy;
// ***实时节点信息
@Transient
private String taskName;
// 请假单审核信息
private List<LeaveOpinion> opinionList = new ArrayList<>();
public void leaveOpAdd(LeaveOpinion leaveOpinion) {
this.opinionList.add(leaveOpinion);
}
public void leaveOpAddAll(List<LeaveOpinion> leaveOpinionList) {
this.opinionList.addAll(leaveOpinionList);
}
public List<LeaveOpinion> getOpinionList() {
return opinionList;
}
public void setOpinionList(List<LeaveOpinion> opinionList) {
this.opinionList = opinionList;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
/**
* @return days
*/
public Integer getDays() {
return days;
}
/**
* @param days
*/
public void setDays(Integer days) {
this.days = days;
}
public Date getBeginTime() {
return beginTime;
}
public void setBeginTime(Date beginTime) {
this.beginTime = beginTime;
}
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
}
......@@ -16,8 +16,8 @@ import com.skyeye.common.util.ToolUtil;
import com.skyeye.eve.dao.ActModelDao;
import com.skyeye.eve.dao.SysEnclosureDao;
import com.skyeye.exception.CustomException;
import org.activiti.engine.RuntimeService;
import org.apache.commons.lang3.StringUtils;
import org.flowable.engine.RuntimeService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......
package com.skyeye.activiti.flowimg;
import com.skyeye.activiti.flowimg.img.CustomProcessDiagramGenerator;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.FlowNode;
import org.flowable.bpmn.model.SequenceFlow;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.history.HistoricActivityInstance;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.runtime.Execution;
import org.flowable.image.ProcessDiagramGenerator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @Description: FlowImgService
* @Author: liyang
* @Date: 2019/10/15 0015 9:32
* @Version 1.0
*/
@Component
public class FlowImgService {
private static final Logger LOG = LoggerFactory.getLogger(FlowImgService.class);
@Autowired
private RuntimeService runtimeService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private HistoryService historyService;
/**
* 通过流程实例ID获取历史流程实例
*
* @param procInstId
* @return
*/
public HistoricProcessInstance getHistoricProcInst(String procInstId) {
return historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).singleResult();
}
/**
* 通过流程实例ID获取流程中已经执行的节点,按照执行先后顺序排序
*
* @param procInstId
* @return
*/
public List<HistoricActivityInstance> getHistoricActivityInstAsc(String procInstId) {
return historyService.createHistoricActivityInstanceQuery().processInstanceId(procInstId)
.orderByHistoricActivityInstanceId().asc().list();
}
/**
* 通过流程实例ID获取流程中正在执行的节点
*
* @param procInstId
* @return
*/
public List<Execution> getRunningActivityInst(String procInstId) {
return runtimeService.createExecutionQuery().processInstanceId(procInstId).list();
}
/**
* 通过流程实例ID获取已经完成的历史流程实例
*
* @param procInstId
* @return
*/
public List<HistoricProcessInstance> getHistoricFinishedProcInst(String procInstId) {
return historyService.createHistoricProcessInstanceQuery().processInstanceId(procInstId).finished().list();
}
/**
* 获取已流经的流程线,需要高亮显示高亮流程已发生流转的线id集合
*
* @param bpmnModel
* @param historicActivityInstanceList
* @return
*/
public List<String> getHighLightedFlows(BpmnModel bpmnModel,
List<HistoricActivityInstance> historicActivityInstanceList) {
// 已流经的流程线,需要高亮显示
List<String> highLightedFlowIdList = new ArrayList<>();
// 全部活动节点
List<FlowNode> allHistoricActivityNodeList = new ArrayList<>();
// 已完成的历史活动节点
List<HistoricActivityInstance> finishedActivityInstanceList = new ArrayList<>();
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
// 获取流程节点
FlowElement flowElement = bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true);
String className = flowElement.getClass().getSimpleName();
if(!"SequenceFlow".equals(className)){
FlowNode flowNode = (FlowNode) flowElement;
allHistoricActivityNodeList.add(flowNode);
// 结束时间不为空,当前节点则已经完成
if (historicActivityInstance.getEndTime() != null) {
finishedActivityInstanceList.add(historicActivityInstance);
}
}
}
FlowNode currentFlowNode = null;
FlowNode targetFlowNode = null;
HistoricActivityInstance currentActivityInstance;
// 遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的
for (int k = 0; k < finishedActivityInstanceList.size(); k++) {
currentActivityInstance = finishedActivityInstanceList.get(k);
// 获得当前活动对应的节点信息及outgoingFlows信息
currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance
.getActivityId(), true);
// 当前节点的所有流出线
List<SequenceFlow> outgoingFlowList = currentFlowNode.getOutgoingFlows();
/**
* 遍历outgoingFlows并找到已流转的 满足如下条件认为已流转:
* 1.当前节点是并行网关或兼容网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
* 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最早的流转节点视为有效流转
* (第2点有问题,有过驳回的,会只绘制驳回的流程线,通过走向下一级的流程线没有高亮显示)
*/
if ("parallelGateway".equals(currentActivityInstance.getActivityType()) || "inclusiveGateway".equals(
currentActivityInstance.getActivityType())) {
// 遍历历史活动节点,找到匹配流程目标节点的
for (SequenceFlow outgoingFlow : outgoingFlowList) {
// 获取当前节点流程线对应的下级节点
targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(outgoingFlow.getTargetRef(),
true);
// 如果下级节点包含在所有历史节点中,则将当前节点的流出线高亮显示
if (allHistoricActivityNodeList.contains(targetFlowNode)) {
highLightedFlowIdList.add(outgoingFlow.getId());
}
}
} else {
/**
* 2、当前节点不是并行网关或兼容网关
* 【已解决-问题】如果当前节点有驳回功能,驳回到申请节点,
* 则因为申请节点在历史节点中,导致当前节点驳回到申请节点的流程线被高亮显示,但实际并没有进行驳回操作
*/
List<Map<String, Object>> tempMapList = new ArrayList<>();
// 当前节点ID
String currentActivityId = currentActivityInstance.getActivityId();
int size = historicActivityInstanceList.size();
boolean ifStartFind = false;
boolean ifFinded = false;
HistoricActivityInstance historicActivityInstance;
// 循环当前节点的所有流出线
// 循环所有历史节点
LOG.info("【开始】-匹配当前节点-ActivityId=【{}】需要高亮显示的流出线:"+currentActivityId);
LOG.info("循环历史节点");
for (int i = 0; i < historicActivityInstanceList.size(); i++) {
// // 如果当前节点流程线对应的下级节点在历史节点中,则该条流程线进行高亮显示(【问题】有驳回流程线时,即使没有进行驳回操作,因为申请节点在历史节点中,也会将驳回流程线高亮显示-_-||)
// if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
// Map<String, Object> map = new HashMap<>();
// map.put("highLightedFlowId", sequenceFlow.getId());
// map.put("highLightedFlowStartTime", historicActivityInstance.getStartTime().getTime());
// tempMapList.add(map);
// // highLightedFlowIdList.add(sequenceFlow.getId());
// }
// 历史节点
historicActivityInstance = historicActivityInstanceList.get(i);
LOG.info("第【"+( i + 1)+"/"+size+"】个历史节点-ActivityId=["+historicActivityInstance.getActivityId()+"]");
// 如果循环历史节点中的id等于当前节点id,从当前历史节点继续先后查找是否有当前节点流程线等于的节点
// 历史节点的序号需要大于等于已完成历史节点的序号,防止驳回重审一个节点经过两次是只取第一次的流出线高亮显示,第二次的不显示
if (i >= k && historicActivityInstance.getActivityId().equals(currentActivityId)) {
LOG.info("第["+(i+1)+"]个历史节点和当前节点一致-ActivityId=["+historicActivityInstance.getActivityId()+"]");
ifStartFind = true;
// 跳过当前节点继续查找下一个节点
continue;
}
if (ifStartFind) {
LOG.info("[开始]-循环当前节点-ActivityId=【"+currentActivityId+"】的所有流出线");
ifFinded = false;
for (SequenceFlow sequenceFlow : outgoingFlowList) {
// 如果当前节点流程线对应的下级节点在其后面的历史节点中,则该条流程线进行高亮显示
// 【问题】
LOG.info("当前流出线的下级节点=[{}]:"+sequenceFlow.getTargetRef());
if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
LOG.info("当前节点["+currentActivityId+"]需高亮显示的流出线=["+sequenceFlow.getId()+"]");
highLightedFlowIdList.add(sequenceFlow.getId());
// 暂时默认找到离当前节点最近的下一级节点即退出循环,否则有多条流出线时将全部被高亮显示
ifFinded = true;
break;
}
}
LOG.info("[完成]-循环当前节点-ActivityId=【"+currentActivityId+"】的所有流出线");
}
if (ifFinded) {
// 暂时默认找到离当前节点最近的下一级节点即退出历史节点循环,否则有多条流出线时将全部被高亮显示
break;
}
}
LOG.info("【完成】-匹配当前节点-ActivityId=【"+currentActivityId+"】需要高亮显示的流出线");
// if (!CollectionUtils.isEmpty(tempMapList)) {
// // 遍历匹配的集合,取得开始时间最早的一个
// long earliestStamp = 0L;
// String highLightedFlowId = null;
// for (Map<String, Object> map : tempMapList) {
// long highLightedFlowStartTime = Long.valueOf(map.get("highLightedFlowStartTime").toString());
// if (earliestStamp == 0 || earliestStamp <= highLightedFlowStartTime) {
// highLightedFlowId = map.get("highLightedFlowId").toString();
// earliestStamp = highLightedFlowStartTime;
// }
// }
// highLightedFlowIdList.add(highLightedFlowId);
// }
}
}
return highLightedFlowIdList;
}
/**
* 根据流程实例Id,获取实时流程图片
*
* @param procInstId
* @return
* @throws Exception
*/
public byte[] generateImageByProcInstId(String procInstId) throws Exception {
if (StringUtils.isEmpty(procInstId)) {
LOG.error("[错误]-传入的参数procInstId为空!");
throw new Exception("[异常]-传入的参数procInstId为空!");
}
InputStream imageStream = null;
try {
// 通过流程实例ID获取历史流程实例
HistoricProcessInstance historicProcessInstance = getHistoricProcInst(procInstId);
// 通过流程实例ID获取流程中已经执行的节点,按照执行先后顺序排序
List<HistoricActivityInstance> historicActivityInstanceList = getHistoricActivityInstAsc(procInstId);
// 将已经执行的节点ID放入高亮显示节点集合
List<String> highLightedActivitiIdList = new ArrayList<>();
for (HistoricActivityInstance historicActivityInstance : historicActivityInstanceList) {
highLightedActivitiIdList.add(historicActivityInstance.getActivityId());
LOG.info("已执行的节点["+historicActivityInstance.getId()+"-"+historicActivityInstance.getActivityId()+"-"+historicActivityInstance.getActivityName()+"-"+historicActivityInstance.getAssignee()+"]");
}
// 通过流程实例ID获取流程中正在执行的节点
List<Execution> runningActivityInstanceList = getRunningActivityInst(procInstId);
List<String> runningActivitiIdList = new ArrayList<String>();
for (Execution execution : runningActivityInstanceList) {
if (StringUtils.isNotEmpty(execution.getActivityId())) {
runningActivitiIdList.add(execution.getActivityId());
LOG.info("执行中的节点["+execution.getId()+"-"+execution.getActivityId()+"-"+execution.getName()+"]");
}
}
// 通过流程实例ID获取已经完成的历史流程实例
List<HistoricProcessInstance> historicFinishedProcessInstanceList = getHistoricFinishedProcInst(procInstId);
// 定义流程画布生成器
ProcessDiagramGenerator processDiagramGenerator = null;
// 如果还没完成,流程图高亮颜色为绿色,如果已经完成为红色
// if (!CollectionUtils.isEmpty(historicFinishedProcessInstanceList)) {
// // 如果不为空,说明已经完成
// processDiagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
// } else {
processDiagramGenerator = new CustomProcessDiagramGenerator();
// }
// 获取流程定义Model对象
BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
// 获取已流经的流程线,需要高亮显示高亮流程已发生流转的线id集合
List<String> highLightedFlowIds = getHighLightedFlows(bpmnModel, historicActivityInstanceList);
// 使用默认配置获得流程图表生成器,并生成追踪图片字符流
imageStream = ((CustomProcessDiagramGenerator) processDiagramGenerator)
.generateDiagramCustom(bpmnModel, "png",
highLightedActivitiIdList, runningActivitiIdList, highLightedFlowIds,
"宋体", "微软雅黑", "黑体",
null, 2.0);
// 将InputStream数据流转换为byte[]
byte[] buffer = new byte[imageStream.available()];
imageStream.read(buffer);
return buffer;
} catch (Exception e) {
e.printStackTrace();
LOG.error("通过流程实例ID["+procInstId+"]获取流程图时出现异常!", e);
throw new Exception("通过流程实例ID" + procInstId + "获取流程图时出现异常!", e);
} finally {
if (imageStream != null) {
imageStream.close();
}
}
}
}
......@@ -4,9 +4,10 @@
package com.skyeye.activiti.listener;
import org.flowable.engine.delegate.DelegateExecution;
import org.flowable.engine.delegate.ExecutionListener;
import com.gexin.fastjson.JSON;
import org.activiti.engine.delegate.DelegateExecution;
import org.activiti.engine.delegate.ExecutionListener;
/**
* @ClassName: MultiInstanceloopListener
......@@ -19,7 +20,7 @@ import org.activiti.engine.delegate.ExecutionListener;
public class MultiInstanceloopListener implements ExecutionListener {
@Override
public void notify(DelegateExecution execution) throws Exception {
public void notify(DelegateExecution execution) {
System.out.println(JSON.toJSONString(execution));
}
......
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.mapper;
public interface ActAssigneeMapper {
public int deleteByNodeId(String nodeId) throws Exception;
}
package com.skyeye.activiti.mapper;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.flowable.engine.impl.persistence.entity.HistoricActivityInstanceEntityImpl;
import java.util.List;
/**
*
* @ClassName: HistoryActivityInstanceMapper
* @Description:
* @author: skyeye云系列--卫志强
* @date: 2021/12/18 0:32
*
* @Copyright: 2021 https://gitee.com/doc_wei01/skyeye Inc. All rights reserved.
* 注意:本内容仅限购买后使用.禁止私自外泄以及用于其他的商业目的
*/
@Mapper
public interface HistoryActivityInstanceMapper {
@Select("SELECT * FROM act_hi_actinst WHERE PROC_INST_ID_ = #{processInstanceId}")
List<HistoricActivityInstanceEntityImpl> findList(@Param("processInstanceId") String processInstanceId);
@Delete("DELETE FROM act_hi_actinst WHERE id_ = #{id}")
int delete(@Param("id") String id);
}
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.service;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import java.util.List;
public interface ActAssigneeService {
public int deleteByNodeId(String nodeId) throws Exception;
public List<ActivityImpl> getActivityList(String deploymentId) throws Exception;
public List<ActivityImpl> selectAllActivity(List<ActivityImpl> activities) throws Exception;
}
......@@ -6,7 +6,7 @@ package com.skyeye.activiti.service;
import com.skyeye.common.object.InputObject;
import com.skyeye.common.object.OutputObject;
import org.activiti.engine.task.Task;
import org.flowable.task.api.Task;
import java.util.List;
import java.util.Map;
......
......@@ -6,8 +6,7 @@ package com.skyeye.activiti.service;
import com.skyeye.common.object.InputObject;
import com.skyeye.common.object.OutputObject;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.flowable.bpmn.model.UserTask;
import java.util.Map;
......@@ -57,14 +56,6 @@ public interface ActivitiTaskService {
*/
UserTask getCurrentUserTaskByTaskId(String taskId);
/**
* 根据流程id获取当前节点信息
*
* @param processInstanceId 流程id
* @return 当前节点信息
*/
ActivityImpl getCurrentActivityNode(String processInstanceId);
/**
* 根据任务节点id判断该节点是否为会签节点
*
......
......@@ -6,10 +6,9 @@ package com.skyeye.activiti.service;
import com.skyeye.common.object.InputObject;
import com.skyeye.common.object.OutputObject;
import org.activiti.bpmn.model.MultiInstanceLoopCharacteristics;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.flowable.bpmn.model.MultiInstanceLoopCharacteristics;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.impl.bpmn.behavior.MultiInstanceActivityBehavior;
import java.util.List;
......@@ -54,24 +53,22 @@ public interface CounterSignService {
* 创建 多实例 行为解释器
*
* @param currentTask 当前任务节点
* @param activityImpl 流程节点信息
* @param sequential 是否串行
* @return
*/
MultiInstanceActivityBehavior createMultiInstanceBehavior(UserTask currentTask, ActivityImpl activityImpl, boolean sequential);
MultiInstanceActivityBehavior createMultiInstanceBehavior(UserTask currentTask, boolean sequential);
/**
* 创建多实例行为解释器
*
* @param currentTask 当前任务节点
* @param activityImpl 流程节点信息
* @param sequential 是否串行
* @param assigneeListExp 用户组表达
* @param assigneeExp 用户标识
* @return
*/
MultiInstanceActivityBehavior createMultiInstanceBehavior(UserTask currentTask, ActivityImpl activityImpl, boolean sequential,
String assigneeListExp, String assigneeExp);
MultiInstanceActivityBehavior createMultiInstanceBehavior(UserTask currentTask, boolean sequential,
String assigneeListExp, String assigneeExp);
/**
* 将 普通节点转换成为会签 任务
......
/*******************************************************************************
* Copyright 卫志强 QQ:598748873@qq.com Inc. All rights reserved. 开源地址:https://gitee.com/doc_wei01/skyeye
******************************************************************************/
package com.skyeye.activiti.service.impl;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.util.io.InputStreamSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.skyeye.activiti.mapper.ActAssigneeMapper;
import com.skyeye.activiti.service.ActAssigneeService;
@Service
public class ActAssigneeServiceImpl implements ActAssigneeService {
@Autowired
private ActAssigneeMapper actAssigneeMapper;
@Autowired
private RepositoryService repositoryService;
@Override
public int deleteByNodeId(String nodeId) throws Exception {
return actAssigneeMapper.deleteByNodeId(nodeId);
}
@Override
public List<ActivityImpl> getActivityList(String deploymentId) throws Exception {
org.activiti.engine.repository.ProcessDefinition processDefinition = repositoryService
.createProcessDefinitionQuery().deploymentId(deploymentId).singleResult();
ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
.getDeployedProcessDefinition(processDefinition.getId());
InputStream inputStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
processDefinition.getResourceName());
new BpmnXMLConverter().convertToBpmnModel(new InputStreamSource(inputStream), false, true);
return selectAllActivity(processDefinitionEntity.getActivities());
}
@Override
public List<ActivityImpl> selectAllActivity(List<ActivityImpl> activities) throws Exception {
List<ActivityImpl> list = new ArrayList<>(activities);
for (ActivityImpl activity : activities) {
List<ActivityImpl> childActivities = activity.getActivities();
if (!childActivities.isEmpty()) {
list.addAll(selectAllActivity(childActivities));
}
}
return list;
}
}
......@@ -9,8 +9,8 @@ import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.skyeye.activiti.flowimg.FlowImgService;
import com.skyeye.activiti.mapper.ActivityMapper;
import com.skyeye.activiti.service.ActAssigneeService;
import com.skyeye.activiti.service.ActivitiModelService;
import com.skyeye.activiti.service.ActivitiTaskService;
import com.skyeye.annotation.transaction.ActivitiAndBaseTransaction;
......@@ -23,26 +23,21 @@ import com.skyeye.common.util.ToolUtil;
import com.skyeye.eve.dao.ActModelDao;
import com.skyeye.eve.dao.ActUserProcessInstanceIdDao;
import com.skyeye.jedis.JedisClientService;
import org.activiti.bpmn.converter.BpmnXMLConverter;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.editor.constants.ModelDataJsonConstants;
import org.activiti.editor.language.json.converter.BpmnJsonConverter;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ModelQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.activiti.image.ProcessDiagramGenerator;
import org.apache.commons.lang3.StringUtils;
import org.flowable.bpmn.converter.BpmnXMLConverter;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.editor.constants.ModelDataJsonConstants;
import org.flowable.editor.language.json.converter.BpmnJsonConverter;
import org.flowable.engine.ProcessEngine;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ModelQuery;
import org.flowable.engine.repository.ProcessDefinition;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -51,7 +46,10 @@ import org.springframework.stereotype.Service;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
import java.util.stream.Collectors;
......@@ -79,12 +77,6 @@ public class ActivitiModelServiceImpl implements ActivitiModelService{
@Autowired
private RepositoryService repositoryService;
/**
* 查询历史信息的类。在一个流程执行完成后,这个对象为我们提供查询历史信息
*/
@Autowired
private HistoryService historyService;
/**
* 任务服务类。可以从这个类中获取任务的信息
*/
......@@ -94,12 +86,6 @@ public class ActivitiModelServiceImpl implements ActivitiModelService{
@Autowired
private RuntimeService runtimeService;
@Autowired
private ProcessEngineConfigurationImpl processEngineConfiguration;
@Autowired
private ActAssigneeService actAssigneeService;
@Autowired
private ActUserProcessInstanceIdDao actUserProcessInstanceIdDao;
......@@ -118,6 +104,9 @@ public class ActivitiModelServiceImpl implements ActivitiModelService{
@Autowired
private ActivitiTaskService activitiTaskService;
@Autowired
private FlowImgService flowImgService;
/**
* @Title: insertNewActivitiModel
* @Description: 新建一个空模型
......@@ -128,11 +117,11 @@ public class ActivitiModelServiceImpl implements ActivitiModelService{
* @throws
*/
@Override
@ActivitiAndBaseTransaction(value = {"activitiTransactionManager", "transactionManager"})
@ActivitiAndBaseTransaction(value = {"transactionManager"})
public void insertNewActivitiModel(InputObject inputObject, OutputObject outputObject) throws Exception {
Map<String, Object> map = inputObject.getParams();
RepositoryService repositoryService = processEngine.getRepositoryService();
//初始化一个空模型
// 初始化一个空模型
Model model = repositoryService.newModel();
//设置一些默认信息
String name = "new-process";
......@@ -192,6 +181,7 @@ public class ActivitiModelServiceImpl implements ActivitiModelService{
row.put("processKey", processDefinition.getKey());
}
}
row.put("id", model.getId());
rows.add(row);
}
outputObject.setBeans(rows);
......@@ -400,7 +390,7 @@ public class ActivitiModelServiceImpl implements ActivitiModelService{
* @throws Exception
*/
@Override
@ActivitiAndBaseTransaction(value = {"activitiTransactionManager", "transactionManager"})
@ActivitiAndBaseTransaction(value = {"transactionManager"})
public void editActivitiModelToStartProcessByMap(Map<String, Object> map, Map<String, Object> user, String id, String approvalId) throws Exception {
// 流程定义的key
String keyName = map.get("keyName").toString();
......@@ -438,27 +428,8 @@ public class ActivitiModelServiceImpl implements ActivitiModelService{
*/
@Override
public void queryProHighLighted(String processInstanceId) throws Exception {
// 获取历史流程实例
HistoricProcessInstance processInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult();
// 获取流程图
BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId());
ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator();
ProcessDefinitionEntity definitionEntity = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(processInstance.getProcessDefinitionId());
//获取历史流程节点
List<HistoricActivityInstance> highLightedActivitList = historyService.createHistoricActivityInstanceQuery().processInstanceId(processInstanceId).list();
// 高亮环节id集合
List<String> highLightedActivitis = new ArrayList<String>();
// 高亮线路id集合
List<String> highLightedFlows = getHighLightedFlows(definitionEntity, highLightedActivitList);
for (HistoricActivityInstance tempActivity : highLightedActivitList) {
String activityId = tempActivity.getActivityId();
highLightedActivitis.add(activityId);
}
// 配置字体
InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", highLightedActivitis, highLightedFlows, "宋体", "微软雅黑", "黑体", null, 2.0);
byte[] b = flowImgService.generateImageByProcInstId(processInstanceId);
ByteArrayInputStream imageStream = new ByteArrayInputStream(b);
BufferedImage bi = ImageIO.read(imageStream);
File fileFolder = new File(tPath + "upload/activiti/");
if(!fileFolder.isDirectory())//目录不存在
......@@ -472,46 +443,6 @@ public class ActivitiModelServiceImpl implements ActivitiModelService{
imageStream.close();
}
/**
* 获取需要高亮的线
*
* @param processDefinitionEntity
* @param historicActivityInstances
* @return
*/
private List<String> getHighLightedFlows(ProcessDefinitionEntity processDefinitionEntity, List<HistoricActivityInstance> historicActivityInstances) {
List<String> highFlows = new ArrayList<String>();// 用以保存高亮的线flowId
for (int i = 0; i < historicActivityInstances.size() - 1; i++) {// 对历史流程节点进行遍历
ActivityImpl activityImpl = processDefinitionEntity.findActivity(historicActivityInstances.get(i).getActivityId());// 得到节点定义的详细信息
List<ActivityImpl> sameStartTimeNodes = new ArrayList<ActivityImpl>();// 用来保存后需开始时间相同的节点
ActivityImpl sameActivityImpl1 = processDefinitionEntity.findActivity(historicActivityInstances.get(i + 1).getActivityId());
// 将后面第一个节点放在时间相同节点的集合里
sameStartTimeNodes.add(sameActivityImpl1);
for (int j = i + 1; j < historicActivityInstances.size() - 1; j++) {
HistoricActivityInstance activityImpl1 = historicActivityInstances.get(j);// 后续第一个节点
HistoricActivityInstance activityImpl2 = historicActivityInstances.get(j + 1);// 后续第二个节点
if (activityImpl1.getStartTime().equals(activityImpl2.getStartTime())) {
// 如果第一个节点和第二个节点开始时间相同保存
ActivityImpl sameActivityImpl2 = processDefinitionEntity.findActivity(activityImpl2.getActivityId());
sameStartTimeNodes.add(sameActivityImpl2);
} else {
// 有不相同跳出循环
break;
}
}
List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();// 取出节点的所有出去的线
for (PvmTransition pvmTransition : pvmTransitions) {
// 对所有的线进行遍历
ActivityImpl pvmActivityImpl = (ActivityImpl) pvmTransition.getDestination();
// 如果取出的线的目标节点存在时间相同的节点里,保存该线的id,进行高亮显示
if (sameStartTimeNodes.contains(pvmActivityImpl)) {
highFlows.add(pvmTransition.getId());
}
}
}
return highFlows;
}
/**
* @Title: deleteActivitiModelById
* @Description: 删除模型
......@@ -554,17 +485,6 @@ public class ActivitiModelServiceImpl implements ActivitiModelService{
Map<String, Object> map = inputObject.getParams();
String deploymentId = map.get("deploymentId").toString();
try{
List<ActivityImpl> activityList = actAssigneeService.getActivityList(deploymentId);
if(activityList != null){
for (ActivityImpl activity : activityList) {
String nodeId = activity.getId();
if (StringUtils.isEmpty(nodeId) || "start".equals(nodeId) || "end".equals(nodeId)) {
continue;
}
/**接触节点和代办关联*/
actAssigneeService.deleteByNodeId(nodeId);
}
}
repositoryService.deleteDeployment(deploymentId, true);
}catch(Exception e){
outputObject.setreturnMessage("存在正在进行的流程,无法取消发布。");
......@@ -725,7 +645,7 @@ public class ActivitiModelServiceImpl implements ActivitiModelService{
* @throws Exception
*/
@Override
@ActivitiAndBaseTransaction(value = {"activitiTransactionManager", "transactionManager"})
@ActivitiAndBaseTransaction(value = {"transactionManager"})
public void copyModelByModelId(InputObject inputObject, OutputObject outputObject) throws Exception {
Map<String, Object> map = inputObject.getParams();
String modelId = map.get("modelId").toString();
......
......@@ -16,11 +16,11 @@ import com.skyeye.common.object.OutputObject;
import com.skyeye.eve.dao.ActGroupDao;
import com.skyeye.eve.dao.ActGroupUserDao;
import net.sf.json.JSONObject;
import org.activiti.engine.IdentityService;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.impl.persistence.entity.GroupEntity;
import org.activiti.engine.impl.persistence.entity.UserEntity;
import org.flowable.engine.IdentityService;
import org.flowable.idm.api.Group;
import org.flowable.idm.api.User;
import org.flowable.idm.engine.impl.persistence.entity.GroupEntityImpl;
import org.flowable.idm.engine.impl.persistence.entity.UserEntityImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
......@@ -221,7 +221,7 @@ public class ActivitiUserServiceImpl implements ActivitiUserService {
// 同步用户组信息
List<Map<String, Object>> groupList = actGroupDao.queryActGroupList(map);
for(Map<String, Object> bean : groupList){
Group group = new GroupEntity();
Group group = new GroupEntityImpl();
group.setId(bean.get("id").toString());
group.setName(bean.get("name").toString());
identityService.deleteGroup(group.getId());
......@@ -230,7 +230,7 @@ public class ActivitiUserServiceImpl implements ActivitiUserService {
// 同步用户信息
List<Map<String, Object>> userList = actGroupUserDao.queryActUserList(map);
for(Map<String, Object> bean : userList){
User user = new UserEntity();
User user = new UserEntityImpl();
user.setId(bean.get("id").toString());
user.setFirstName(bean.get("firstName").toString());
user.setLastName(bean.get("lastName").toString());
......@@ -258,7 +258,7 @@ public class ActivitiUserServiceImpl implements ActivitiUserService {
* @throws Exception
*/
@Override
@ActivitiAndBaseTransaction(value = {"activitiTransactionManager", "transactionManager"})
@ActivitiAndBaseTransaction(value = {"transactionManager"})
public void addOrEditToSubmit(InputObject inputObject, OutputObject outputObject,
int subType, String key, String dataId, String approvalId) throws Exception {
if(subType == 1){
......
......@@ -62,7 +62,7 @@ public class DsFormActivitiServiceImpl implements DsFormActivitiService {
* @throws
*/
@Override
@ActivitiAndBaseTransaction(value = {"activitiTransactionManager", "transactionManager"})
@ActivitiAndBaseTransaction(value = {"transactionManager"})
public void insertDSFormProcess(InputObject inputObject, OutputObject outputObject) throws Exception {
Map<String, Object> map = inputObject.getParams();
Map<String, Object> user = inputObject.getLogParams();
......
......@@ -17,11 +17,11 @@ import com.skyeye.eve.dao.ActModleTypeDao;
import com.skyeye.eve.dao.DsFormPageDataDao;
import com.skyeye.eve.service.ActModleTypeService;
import com.skyeye.jedis.JedisClientService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.repository.Model;
import org.activiti.engine.repository.ProcessDefinition;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.repository.Model;
import org.flowable.engine.repository.ProcessDefinition;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
......
boolValue=1
blobType=BINARY
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部