Activiti7 結束/終止流程


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

還有一個bug,這個bug發生在當使用原生的taskService完成任務時,多次設置同一個流程變量的值后者不會覆蓋前者。即,ACT_RU_VARIABLE表中變量的值沒有更新。

為了說明這個問題,看下面這個圖:

 

節點“1”完成任務時設置result==3,於是后面的流程永遠是1->3->1->3->...  ,即使下一次執行時result==1,流程也不會走到2。經過分析,我猜測對同一個變量多次賦值,后者沒有覆蓋前者,也就是說第2次賦值沒有生效,查看ACT_RU_VARIABLE表果然是這樣,變量的值沒有更新。經過反復試驗,我發現用taskRuntime.complete()完成任務時就不會出現這個問題,流程變量的值會正常更新。


Map<String, Object> variables = new HashMap<>();
variables.put("result", 3);

//	這樣寫的話,多次對同一個流程變量賦值時,流程變量的值不會更新,即后面的賦值永遠是不生效的
Task task = taskService.createTaskQuery().taskId("1234").singleResult();
taskService.complete(task.getId(), variables);

//	這樣寫的話,就很完美,ACT_RU_VARIABLE表的流程變量的值正常更新
taskRuntime.complete(TaskPayloadBuilder.complete().withTaskId("1234").withVariables(variables).build());

補充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就到此為止了,以后也不想再碰這玩意兒了,太難用了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM