package com.yussion;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.ProcessEngineConfiguration;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricActivityInstance;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
public class RollBackTaskTest {
public static void main(String[] args) throws ParseException {
excuteTask();
rollBackTask2("9"); //taskId 刚完成的任务ID,即需要回退的任务对应任务ID
rollBackTask("15"); //taskId 当前任务ID,即需要回退的任务ID的下一步任务ID
}
private static void excuteTask() throws ParseException {
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
//.setJdbcUrl("jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000").setJdbcUsername("sa").setJdbcPassword("")
//.setJdbcDriver("org.h2.Driver")
.setJdbcUrl("jdbc:mysql://localhost:3306/activiti?serverTimezone=UTC").setJdbcUsername("root").setJdbcPassword("123456")
.setJdbcDriver("com.mysql.jdbc.Driver")
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
ProcessEngine processEngine = cfg.buildProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
Deployment deployment = repositoryService.createDeployment().addClasspathResource("onboarding.bpmn20.xml")
.deploy();
repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).singleResult();
RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("onboarding");
//startOnboarding - enterOnboardingData - personalizedIntro - endOnboarding
//执行完成enterOnboardingData后,需要回退该已完成的任务,此处构造出enterOnboardingData任务完成的数据
if (processInstance != null && !processInstance.isEnded()) {
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("managers").list();
Task task = tasks.get(0);
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("fullName", "张三");
variables.put("yearsOfExperience", 11);
taskService.complete(task.getId(), variables);
//variables.clear();
//variables.put("personalWelcomeTime", "1/1/2021");
//task = tasks.get(1);
//taskService.complete(task.getId(), variables);
}
}
//lastHiTaskId: 刚完成的任务ID,即需要回退的任务对应任务ID
private static void rollBackTask2(String lastHiTaskId) {
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
//.setJdbcUrl("jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000").setJdbcUsername("sa").setJdbcPassword("")
//.setJdbcDriver("org.h2.Driver")
.setJdbcUrl("jdbc:mysql://localhost:3306/activiti?serverTimezone=UTC").setJdbcUsername("root").setJdbcPassword("123456")
.setJdbcDriver("com.mysql.jdbc.Driver")
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
ProcessEngine processEngine = cfg.buildProcessEngine();
// https://www.itdaan.com/blog/2017/10/26/a24659ba5fa8e821ce9bc9267ca96107.html
// 按照完成时间排序取第一个, 即需要回退到该节点
HistoricTaskInstance hstTask = processEngine.getHistoryService().createHistoricTaskInstanceQuery()
.taskId(lastHiTaskId).singleResult();
List<HistoricTaskInstance> htiList = processEngine.getHistoryService().createHistoricTaskInstanceQuery()
.processInstanceId(hstTask.getProcessInstanceId()).finished().orderByTaskCreateTime().desc().list();
if (htiList == null || htiList.size() < 2) {
//回退到开始节点,这种情况清空hi和RU表数据即可
return;
}
String lastTaskId = htiList.get(0).getId(); // 从taskId对应节点回退到parentTaskId对应节点
String execId = hstTask.getExecutionId();
System.out.println(lastTaskId+" "+execId);
}
// taskId 当前任务ID,即需要回退的任务ID的下一步任务ID, 以完成enterOnboardingData后需要回退enterOnboardingData为例 当前任务ID为15,上一步任务ID为9, execId为6
private static void rollBackTask(String taskId) {
ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration()
//.setJdbcUrl("jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000").setJdbcUsername("sa").setJdbcPassword("")
//.setJdbcDriver("org.h2.Driver")
.setJdbcUrl("jdbc:mysql://localhost:3306/activiti?serverTimezone=UTC").setJdbcUsername("root").setJdbcPassword("123456")
.setJdbcDriver("com.mysql.jdbc.Driver")
.setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE);
ProcessEngine processEngine = cfg.buildProcessEngine();
// https://www.itdaan.com/blog/2017/10/26/a24659ba5fa8e821ce9bc9267ca96107.html
// 按照完成时间排序取第一个, 即需要回退到该节点
HistoricTaskInstance hstTask = processEngine.getHistoryService().createHistoricTaskInstanceQuery()
.taskId(taskId).singleResult();
List<HistoricTaskInstance> htiList = processEngine.getHistoryService().createHistoricTaskInstanceQuery()
.processInstanceId(hstTask.getProcessInstanceId()).finished().orderByTaskCreateTime().desc().list();
if (htiList == null || htiList.size() < 2) {
//回退到开始节点,这种情况清空hi和RU表数据即可
return;
}
String lastTaskId = htiList.get(0).getId(); // 从taskId对应节点回退到parentTaskId对应节点
String execId = hstTask.getExecutionId();
System.out.println(lastTaskId+" "+execId);
// 删除待回退的历史任务
// DELETE from ACT_HI_TASKINST where EXECUTION_ID_=#{execId} and ID_=#{taskId}
// DELETE from ACT_HI_TASKINST where EXECUTION_ID_='6' and ID_='15';
// 更新跳转任务的完成时间 和状态
// update ACT_HI_TASKINST set END_TIME_=NULL,DURATION_=NULL,DELETE_REASON_=NULL where EXECUTION_ID_=#{execId} and id_=#{lastTaskId}
// update ACT_HI_TASKINST set END_TIME_=NULL,DURATION_=NULL,DELETE_REASON_=NULL where EXECUTION_ID_='6' and id_='9';
// 更新taskId 解除关联 ACT_RU_IDENTITYLINK
// String linkId: select ID_ from ACT_RU_IDENTITYLINK where TASK_ID_=#{taskId} select ID_ from ACT_RU_IDENTITYLINK where TASK_ID_='15' -> 16
// update ACT_RU_IDENTITYLINK set TASK_ID_=NULL where ID_=#{linkId} update ACT_RU_IDENTITYLINK set TASK_ID_=NULL where ID_='16'
// 更新当前任务 名称 fromKey id
/*
UPDATE ACT_RU_TASK a, ( SELECT TASK_DEF_KEY_, FORM_KEY_, NAME_, ID_ FROM
ACT_HI_TASKINST WHERE EXECUTION_ID_ = #{execId} AND ID_ = #{lastTaskId} ) b
SET a.ID_ = b.ID_, a.TASK_DEF_KEY_ = b.TASK_DEF_KEY_, a.NAME_ = b.NAME_,
a.FORM_KEY_ = b.FORM_KEY_ WHERE a.EXECUTION_ID_ = #{execId} AND a.id_ =
#{taskId}
-----------------------------------
UPDATE ACT_RU_TASK a, ( SELECT TASK_DEF_KEY_, FORM_KEY_, NAME_, ID_ FROM
ACT_HI_TASKINST WHERE EXECUTION_ID_ = '6' AND ID_ = '9' ) b
SET a.ID_ = b.ID_, a.TASK_DEF_KEY_ = b.TASK_DEF_KEY_, a.NAME_ = b.NAME_,
a.FORM_KEY_ = b.FORM_KEY_ WHERE a.EXECUTION_ID_ = '6' AND a.id_ = '15'
*/
// 更新ACT_RU_IDENTITYLINK 的taskid
// update ACT_RU_IDENTITYLINK set TASK_ID_=#{lastTaskId} where ID_=#{linkId} update ACT_RU_IDENTITYLINK set TASK_ID_='9' where ID_='16'
// 更新execu的 act_id_
// UPDATE ACT_RU_EXECUTION a, ( SELECT TASK_DEF_KEY_ FROM ACT_RU_TASK WHERE ID_ = #{lastTaskId} ) b SET a.ACT_ID_ = b.TASK_DEF_KEY_ WHERE ID_ = #{execId}
// UPDATE ACT_RU_EXECUTION a, ( SELECT TASK_DEF_KEY_ FROM ACT_RU_TASK WHERE ID_ = '9' ) b SET a.ACT_ID_ = b.TASK_DEF_KEY_ WHERE ID_ = '6'
}
}
-----------------流程各阶段数据库表数据变化----------------------