activiti工作流退回問題研究
近期由於業務需求,需要一個開源的工作流。研究了一下activiti工作流版本5.13 .在研究過程中發現,activiti工作流現有的功能中不能滿足中國式的駁回。如果工作流不能駁回,那對於咱們來說基本上是用不了。後來在網上找了一個退回到上一節點的例子。現在改了一下,可以從當前節點退回的以前走過的人工節點。廢話少說直接上例子。
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:activiti="http://activiti.org/bpmn
<process id="helloworld" name="helloworldProcess" isExecutable="true">
<startEvent id="startevent1" name="Start"></startEvent>
<endEvent id="endevent1" name="End"></endEvent>
<userTask id="usertask1" name="提交申請" activiti:assignee="張三"></userTask>
<userTask id="usertask2" name="審批【部門經理】" activiti:assignee="李四"></userTask>
<userTask id="usertask3" name="審批【總經理】" activiti:assignee="王五"></userTask>
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
<sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow>
<sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow>
<sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow>
</process>
以上是最簡單的審批流程
退回到上一級提交人的程式碼如下:
public class ModelRollBack {
private Logger log = LogManager.getLogger(ModelRollBack.class);//日誌檔案
private RuntimeService runtimeService;//
private TaskService taskService;
private RepositoryService repositoryService;
private HistoryService historyService;
private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//退回上一個節點
public String rollBackWorkFlow(String taskId) {
this.taskService=processEngine.getTaskService();
this.historyService = processEngine.getHistoryService();
this.repositoryService = processEngine.getRepositoryService();
this.runtimeService = processEngine.getRuntimeService();
try {
Map<String, Object> variables;
// 取得當前任務.當前任務節點
HistoricTaskInstance currTask = historyService
.createHistoricTaskInstanceQuery().taskId(taskId)
.singleResult();
// 取得流程例項,流程例項
ProcessInstance instance = runtimeService
.createProcessInstanceQuery()
.processInstanceId(currTask.getProcessInstanceId())
.singleResult();
if (instance == null) {
log.info("流程結束");
log.error("出錯啦!流程已經結束");
return "ERROR";
}
variables = instance.getProcessVariables();
// 取得流程定義
ProcessDefinitionEntity definition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
.getDeployedProcessDefinition(currTask
.getProcessDefinitionId());
if (definition == null) {
log.info("流程定義未找到");
log.error("出錯啦!流程定義未找到");
return "ERROR";
}
// 取得上一步活動
ActivityImpl currActivity = ((ProcessDefinitionImpl) definition)
.findActivity(currTask.getTaskDefinitionKey());
//也就是節點間的連線
List<PvmTransition> nextTransitionList = currActivity
.getIncomingTransitions();
// 清除當前活動的出口
List<PvmTransition> oriPvmTransitionList = new ArrayList<PvmTransition>();
//新建一個節點連線關係集合
List<PvmTransition> pvmTransitionList = currActivity
.getOutgoingTransitions();
//
for (PvmTransition pvmTransition : pvmTransitionList) {
oriPvmTransitionList.add(pvmTransition);
}
pvmTransitionList.clear();
// 建立新出口
List<TransitionImpl> newTransitions = new ArrayList<TransitionImpl>();
for (PvmTransition nextTransition : nextTransitionList) {
PvmActivity nextActivity = nextTransition.getSource();
ActivityImpl nextActivityImpl = ((ProcessDefinitionImpl) definition)
.findActivity(nextActivity.getId());
TransitionImpl newTransition = currActivity
.createOutgoingTransition();
newTransition.setDestination(nextActivityImpl);
newTransitions.add(newTransition);
}
// 完成任務
List<Task> tasks = taskService.createTaskQuery()
.processInstanceId(instance.getId())
.taskDefinitionKey(currTask.getTaskDefinitionKey()).list();
for (Task task : tasks) {
taskService.complete(task.getId(), variables);
historyService.deleteHistoricTaskInstance(task.getId());
}
// 恢復方向
for (TransitionImpl transitionImpl : newTransitions) {
currActivity.getOutgoingTransitions().remove(transitionImpl);
}
for (PvmTransition pvmTransition : oriPvmTransitionList) {
pvmTransitionList.add(pvmTransition);
}
log.info("OK");
log.info("流程結束");
return "SUCCESS";
} catch (Exception e) {
log.error("失敗");
log.error(e.getMessage());
return "ERROR";
}
}
//回退到指定節點
public String rollBackToAssignWorkFlow(String taskId,String destTaskkey) {
this.taskService=processEngine.getTaskService();
this.historyService = processEngine.getHistoryService();
this.repositoryService = processEngine.getRepositoryService();
this.runtimeService = processEngine.getRuntimeService();
try {
Map<String, Object> variables;
// 取得當前任務.當前任務節點
HistoricTaskInstance currTask = historyService
.createHistoricTaskInstanceQuery().taskId(taskId)
.singleResult();
// 取得流程例項,流程例項
ProcessInstance instance = runtimeService
.createProcessInstanceQuery()
.processInstanceId(currTask.getProcessInstanceId())
.singleResult();
if (instance == null) {
log.info("流程結束");
log.error("出錯啦!流程已經結束");
return "ERROR";
}
variables = instance.getProcessVariables();
// 取得流程定義
ProcessDefinitionEntity definition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
.getDeployedProcessDefinition(currTask
.getProcessDefinitionId());
if (definition == null) {
log.info("流程定義未找到");
log.error("出錯啦!流程定義未找到");
return "ERROR";
}
//取得當前活動節點
ActivityImpl currActivity = ((ProcessDefinitionImpl) definition)
.findActivity(currTask.getTaskDefinitionKey());
log.info("currActivity"+currActivity);
// 取得上一步活動
//也就是節點間的連線
//獲取來源節點的關係
List<PvmTransition> nextTransitionList = currActivity.getIncomingTransitions();
// 清除當前活動的出口
List<PvmTransition> oriPvmTransitionList = new ArrayList<PvmTransition>();
//新建一個節點連線關係集合
//獲取出口節點的關係
List<PvmTransition> pvmTransitionList = currActivity
.getOutgoingTransitions();
//
for (PvmTransition pvmTransition : pvmTransitionList) {
oriPvmTransitionList.add(pvmTransition);
}
pvmTransitionList.clear();
// 建立新出口
List<TransitionImpl> newTransitions = new ArrayList<TransitionImpl>();
for (PvmTransition nextTransition : nextTransitionList) {
PvmActivity nextActivity = nextTransition.getSource();
log.info("nextActivity"+nextActivity);
log.info("nextActivity.getId()"+nextActivity.getId());
//destTaskkey
ActivityImpl nextActivityImpl = ((ProcessDefinitionImpl) definition)
// .findActivity(nextActivity.getId());
.findActivity(destTaskkey);
TransitionImpl newTransition = currActivity
.createOutgoingTransition();
newTransition.setDestination(nextActivityImpl);
newTransitions.add(newTransition);
}
// 完成任務
List<Task> tasks = taskService.createTaskQuery()
.processInstanceId(instance.getId())
.taskDefinitionKey(currTask.getTaskDefinitionKey()).list();
for (Task task : tasks) {
taskService.complete(task.getId(), variables);
historyService.deleteHistoricTaskInstance(task.getId());
}
// 恢復方向
for (TransitionImpl transitionImpl : newTransitions) {
currActivity.getOutgoingTransitions().remove(transitionImpl);
}
for (PvmTransition pvmTransition : oriPvmTransitionList) {
pvmTransitionList.add(pvmTransition);
}
log.info("OK");
log.info("流程結束");
return "SUCCESS";
} catch (Exception e) {
log.error("失敗");
log.error(e.getMessage());
return "ERROR";
}
}
public static void main(String []args){
ModelRollBack back = new ModelRollBack();
//back.rollBackWorkFlow("1102");
back.rollBackToAssignWorkFlow("2402", "usertask1");
}
}
以上程式碼是退回到上一節點,和退回到提交人節點的程式碼
程式碼解析 : 例如 流程開始 走到張三 ,張三提交 ,走到李四 ,李四提交走到王五 。現在王五發現有問題,需要直接退回到 張三,讓張三修改之後再次提交 。
這個過程中當前節點在王五 也就是usertask3 在此過程中我們要理清 節點之間的關係
usertask1----->usertask2
usertask2------>usertask3
usertask3------->endevent
目前對於uesrtask3來說來源 是usertask2------>usertask3
出口usertask3------>enendevent
所以我們只需要根據流程引擎中的定義將出口替換成usertask1就可以。
在此過程中 PvmTransition 只工作流引擎中 的節點關係維護
ActivityImpl是具體的節點。
ProcessDefinitionEntity是當前流程的定義
目前只研究到這個階段如果需要交流,可以給我留言哦