Activiti7 結束/終止流程

廢物大師兄發表於2021-08-05

1.  結束/終止 正在執行的流程例項

思路:跟回退一樣的思路一樣,直接從當前節點跳到結束節點(EndEvent) 

/**
 * 結束任務
 * @param taskId    當前任務ID
 */
public void endTask(String taskId) {
    //  當前任務
    Task task = taskService.createTaskQuery().taskId(taskId).singleResult();

    BpmnModel bpmnModel = repositoryService.getBpmnModel(task.getProcessDefinitionId());
    List endEventList = bpmnModel.getMainProcess().findFlowElementsOfType(EndEvent.class);
    FlowNode endFlowNode = endEventList.get(0);
    FlowNode currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());

    //  臨時儲存當前活動的原始方向
    List originalSequenceFlowList = new ArrayList<>();
    originalSequenceFlowList.addAll(currentFlowNode.getOutgoingFlows());
    //  清理活動方向
    currentFlowNode.getOutgoingFlows().clear();

    //  建立新方向
    SequenceFlow newSequenceFlow = new SequenceFlow();
    newSequenceFlow.setId("newSequenceFlowId");
    newSequenceFlow.setSourceFlowElement(currentFlowNode);
    newSequenceFlow.setTargetFlowElement(endFlowNode);
    List newSequenceFlowList = new ArrayList<>();
    newSequenceFlowList.add(newSequenceFlow);
    //  當前節點指向新的方向
    currentFlowNode.setOutgoingFlows(newSequenceFlowList);

    //  完成當前任務
    taskService.complete(task.getId());

    //  可以不用恢復原始方向,不影響其它的流程
//        currentFlowNode.setOutgoingFlows(originalSequenceFlowList);
}

補充1:關於BUSINESS_KEY_

BUSINESS_KEY_ 欄位是用於將業務系統與Actititi工作流關聯的關鍵欄位,通常我們用它來存放業務表的ID,比如:請假ID、報銷ID等等。

但是,通常我們們系統不可能只有一個流程,假設我們做的是一個OA系統,那麼公司的流程有請假、採購、報銷等等流程,那這一個欄位如何區分到底是哪個業務流程的ID呢,換言之,假設BUSINESS_KEY_這個欄位現在是2,那麼我怎麼知道這個2是請假表的ID,還是採購表的ID呢?因此,要想通過這個一個欄位區分不同的型別就要求這個欄位是唯一的,比如我們可以加上業務標識,比如:holiday:2,purchase:3等等。還有一種方式,利用另外一個空閒欄位TENANT_ID_,我們可以把業務型別存到TENANT_ID_欄位中,這樣TENANT_ID_和BUSINESS_KEY_兩個欄位就能唯一確定是哪個業務的那個ID。

/**
 * 7.1.0.M6的act_ru_task表中有BUSINESS_KEY_欄位,因此可以直接task.getBusinessKey()
 * 而7.1.0.M5中沒有這個欄位,因此要想獲取BUSINESS_KEY_必須從act_ru_execution表中取
 */
@Test
public void testBusinessKey() {
    List<Task> taskList = taskService.createTaskQuery().taskCandidateOrAssigned("lisi").taskTenantId("11").list();
    Set<String> processInstanceIds = taskList.stream().map(Task::getProcessInstanceId).collect(Collectors.toSet());
    List<ProcessInstance> processInstances = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIds).list();
    
    List<String> businessKeyList = processInstances.stream().map(ProcessInstance::getBusinessKey).collect(Collectors.toList());
    System.out.println(businessKeyList);

    Pattern pattern = Pattern.compile("^(\\w+):(\\d+)$");
    
    List<Integer> businessIds = new ArrayList<>();
    businessKeyList.forEach(businessKey->{
        Matcher matcher = pattern.matcher(businessKey);
        if (matcher.find()) {
            String id = matcher.group(2);
            businessIds.add(Integer.valueOf(id));
        }
    });
}

補充2:Activiti不同版本的Bug

首先,我發現不同版本的表結構不一樣,當用 7.1.0.M5 版本時,啟動就報錯,缺少欄位

org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: java.sql.SQLSyntaxErrorException: Unknown column 'VERSION_' in 'field list'
### The error may exist in org/activiti/db/mapping/entity/Deployment.xml
### The error may involve org.activiti.engine.impl.persistence.entity.DeploymentEntityImpl.insertDeployment-Inline
### The error occurred while setting parameters
### SQL: insert into ACT_RE_DEPLOYMENT(ID_, NAME_, CATEGORY_, KEY_, TENANT_ID_, DEPLOY_TIME_, ENGINE_VERSION_, VERSION_, PROJECT_RELEASE_VERSION_)     values(?, ?, ?, ?, ?, ?, ?, ?, ?)
### Cause: java.sql.SQLSyntaxErrorException: Unknown column 'VERSION_' in 'field list'
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30) ~[mybatis-3.5.0.jar:3.5.0]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:200) ~[mybatis-3.5.0.jar:3.5.0]
    at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:185) ~[mybatis-3.5.0.jar:3.5.0]
    at org.activiti.engine.impl.db.DbSqlSession.flushRegularInsert(DbSqlSession.java:787) ~[activiti-engine-7.1.0.M5.jar:na]
    at org.activiti.engine.impl.db.DbSqlSession.flushInsertEntities(DbSqlSession.java:662) ~[activiti-engine-7.1.0.M5.jar:na]
    at org.activiti.engine.impl.db.DbSqlSession.flushInserts(DbSqlSession.java:642) ~[activiti-engine-7.1.0.M5.jar:na]
    at org.activiti.engine.impl.db.DbSqlSession.flush(DbSqlSession.java:525) ~[activiti-engine-7.1.0.M5.jar:na]

解決辦法也很簡單,將缺失的欄位加上即可:

ALTER TABLE `act_re_deployment` 
ADD COLUMN `VERSION_` int(11) NULL DEFAULT NULL,
ADD COLUMN `PROJECT_RELEASE_VERSION_` varchar(255) NULL DEFAULT NULL;

其次,我發現在啟動流程例項查詢流程定義時,7.1.0.M5是按版本升序取第一個,而7.1.0.M6是降序

同時,還發現7.1.0.M6有一個明顯的Bug,這個Bug會導致當有多個部署的時候,即當act_re_deployment表中的記錄多於1條時,就無法使用processRuntime.start()啟動流程例項

 

本著用新不用舊的原則,還是建議用7.1.0.M6

補充3:任務監聽器

@Slf4j
@Component
public class TaskCreateListener implements TaskRuntimeEventListener<TaskCreatedEvent> {
    @Override
    public void onEvent(TaskCreatedEvent event) {
    	System.out.println("任務被建立");
    }
}

@Slf4j
@Component
public class TaskAssignedListener implements TaskRuntimeEventListener<TaskAssignedEvent> {
    @Override
    public void onEvent(TaskAssignedEvent event) {
	System.out.println("任務被指派");
    }
}

@Slf4j
@Component
public class TaskCompletedListener implements TaskRuntimeEventListener<TaskCompletedEvent> {
    @Override
    public void onEvent(TaskCompletedEvent event) {
	System.out.println("任務被完成");
    }
}

關於Activiti就到此為止了,以後也不想再碰這玩意兒了,太難用了

 

相關文章