建立流程
- 要想操作Activiti引擎,需要透過org.activiti.engine.ProcessEngine例項暴露的服務.就可以操作一個org.activiti.engine.ProcessEngine
建立一個請假申請的工作業務流程:
釋出流程
- 任何與“靜態”資源有關的資料(比如流程定義)都可以透過RepositoryService訪問,從概念上講,所有靜態資料都是Activiti的資源內容
在src/test/resources/org/activiti/test目錄下建立一個新的xml檔案 VacationRequest.bpmn20.xml:
<?xml version="1.0" encoding="UTF-8" ?> <definitions id="definitions" targetNamespace="http://activiti.org/bpmn20" 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="vacationRequest" name="Vacation request"> <startEvent id="request" activiti:initiator="employeeName"> <extensionElements> <activiti:formProperty id="numberOfDays" name="Number of days" type="long" value="1" required="true"/> <activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" /> <activiti:formProperty id="vacationMotivation" name="Motivation" type="string" /> </extensionElements> </startEvent> <sequenceFlow id="flow1" sourceRef="request" targetRef="handleRequest" /> <userTask id="handleRequest" name="Handle vacation request" > <documentation> ${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}). </documentation> <extensionElements> <activiti:formProperty id="vacationApproved" name="Do you approve this vacation" type="enum" required="true"> <activiti:value id="true" name="Approve" /> <activiti:value id="false" name="Reject" /> </activiti:formProperty> <activiti:formProperty id="managerMotivation" name="Motivation" type="string" /> </extensionElements> <potentialOwner> <resourceAssignmentExpression> <formalExpression>management</formalExpression> </resourceAssignmentExpression> </potentialOwner> </userTask> <sequenceFlow id="flow2" sourceRef="handleRequest" targetRef="requestApprovedDecision" /> <exclusiveGateway id="requestApprovedDecision" name="Request approved?" /> <sequenceFlow id="flow3" sourceRef="requestApprovedDecision" targetRef="sendApprovalMail"> <conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'true'}</conditionExpression> </sequenceFlow> <task id="sendApprovalMail" name="Send confirmation e-mail" /> <sequenceFlow id="flow4" sourceRef="sendApprovalMail" targetRef="theEnd1" /> <endEvent id="theEnd1" /> <sequenceFlow id="flow5" sourceRef="requestApprovedDecision" targetRef="adjustVacationRequestTask"> <conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'false'}</conditionExpression> </sequenceFlow> <userTask id="adjustVacationRequestTask" name="Adjust vacation request"> <documentation> Your manager has disapproved your vacation request for ${numberOfDays} days. Reason: ${managerMotivation} </documentation> <extensionElements> <activiti:formProperty id="numberOfDays" name="Number of days" value="${numberOfDays}" type="long" required="true"/> <activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" value="${startDate}" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" /> <activiti:formProperty id="vacationMotivation" name="Motivation" value="${vacationMotivation}" type="string" /> <activiti:formProperty id="resendRequest" name="Resend vacation request to manager?" type="enum" required="true"> <activiti:value id="true" name="Yes" /> <activiti:value id="false" name="No" /> </activiti:formProperty> </extensionElements> <humanPerformer> <resourceAssignmentExpression> <formalExpression>${employeeName}</formalExpression> </resourceAssignmentExpression> </humanPerformer> </userTask> <sequenceFlow id="flow6" sourceRef="adjustVacationRequestTask" targetRef="resendRequestDecision" /> <exclusiveGateway id="resendRequestDecision" name="Resend request?" /> <sequenceFlow id="flow7" sourceRef="resendRequestDecision" targetRef="handleRequest"> <conditionExpression xsi:type="tFormalExpression">${resendRequest == 'true'}</conditionExpression> </sequenceFlow> <sequenceFlow id="flow8" sourceRef="resendRequestDecision" targetRef="theEnd2"> <conditionExpression xsi:type="tFormalExpression">${resendRequest == 'false'}</conditionExpression> </sequenceFlow> <endEvent id="theEnd2" /> </process> </definitions>
為了讓Activiti引擎知道這個流程,我們必須先進行[釋出],釋出意味著引擎會把BPMN 2.0 xml解析成可以執行的東西,釋出包中的所有流程定義都會新增到資料庫中.這樣,當引擎重啟時,它依然可以獲得[已釋出]的流程:
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); repositoryService.createDeployment() .addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml") .deploy(); Log.info("Number of process definitions: " + repositoryService.createProcessDefinitionQuery().count());
啟動一個流程例項
- 把流程定義釋出到Activiti引擎後,可以基於它發起新流程例項.
- 對每個流程定義,都可以有很多流程例項.流程定義是"藍圖",流程例項是它的一個執行的執行
所有與流程執行狀態相關的東西都可以透過RuntimeService獲得.有很多方法可以啟動一個新流程例項.
- 可以在流程例項啟動時新增一些流程變數, 因為第一個使用者任務的表示式需要這些變數.流程變數經常會被用到,因為它們賦予來自同一個流程定義的不同流程例項的特別含義
- 流程變數是區分流程例項的關鍵
下面使用定義在流程定義xml 中的key來啟動流程例項:
Map<String, Object> variables = new HashMap<String, Object>(); variables.put("employeeName", "Kermit"); variables.put("numberOfDays", new Integer(4)); variables.put("vacationMotivation", "I'm really tired!"); RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacationRequest", variables); // Verify that we started a new process instance Log.info("Number of process instances: " + runtimeService.createProcessInstanceQuery().count());
完成任務
- 流程啟動後,第一步就是使用者任務.這是必須由系統使用者處理的一個環節.
使用者會有一個"任務列表",展示了所有必須由整個使用者處理的任務.下面是對應的查詢:
// Fetch all tasks for the management group TaskService taskService = processEngine.getTaskService(); List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("management").list(); for (Task task : tasks) { Log.info("Task available: " + task.getName()); }
為了讓流程例項繼續執行,我們需要完成整個任務.對Activiti來說,就是需要complete任務:
Task task = tasks.get(0); Map<String, Object> taskVariables = new HashMap<String, Object>(); taskVariables.put("vacationApproved", "false"); taskVariables.put("managerMotivation", "We have a tight deadline!"); taskService.complete(task.getId(), taskVariables);
- 然後流程例項就會進入到下一個環節
下一環節允許員工透過表單調整原始的請假申請.員工可以重新提交請假申請,這會使流程重新進入到第一個任務
掛起或啟用一個流程
可以掛起一個流程定義,當掛起流程定義時,就不能建立新流程了,會丟擲一個異常.可以透過RepositoryService掛起一個流程:
repositoryService.suspendProcessDefinitionByKey("vacationRequest"); try { runtimeService.startProcessInstanceByKey("vacationRequest"); } catch (ActivitiException e) { e.printStackTrace(); }
- 要想重新啟用一個流程定義,可以呼叫repositoryService.activateProcessDefinitionXXX方法
也可以掛起一個流程例項:
- 掛起時,流程不能繼續執行:比如,完成任務會丟擲異常,非同步操作(比如定時器)也不會執行.掛起流程例項可以呼叫runtimeService.suspendProcessInstance方法
- 啟用流程例項可以呼叫runtimeService.activateProcessInstanceXXX方法