This is the 9th day of my participation in Gwen Challenge
Use the Activiti service
As mentioned above, and the Activiti engine interaction way is through the org. Activiti engine. The ProcessEngine instance of the class public service. The following code snippet assumes that you have a available Activiti environment, which means you can access a valid org. Activiti. Engine. The ProcessEngine. If you just want to try the code below, you can download or clone the Activiti unit test template, import it into your IDE and testUserguideCode() add a method for the org.activiti.MyUnitTest unit test.
The ultimate goal of this little tutorial is to create a work business process that mimics a simple leave application process for a company:
Deployment process
Everything related to static data, such as process definitions, is accessed through RepositoryService. Conceptually, each such static data is the content of the Activiti engine repository.
Use the following VacationRequest. Bpmn20. XML in SRC/test/resources/org/activiti/test resources folder (or any other place, if you do not use the unit test template) to create a new XML file. Note that this section does not explain the XML constructs used in the example above. If necessary, read the BPMN 2.0 chapter to familiarize yourself with these structures.
<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>
Copy the code
In order for the Activiti engine to know about this process, we must first deploy it. Deployment means that the engine parses the BPMN 2.0 XML into an executable and adds a new database record for each process definition included in the deployment. This way, when the engine restarts, it will still know all the deployed processes:
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());
Copy the code
Start process instance
Once the process definition is deployed to the Activiti engine, we can launch new process instances from it. There are usually many process instances for each process definition. A process definition is the blueprint, and a process instance is its runtime execution.
Everything related to the run-time state of a process can be found in RuntimeService. There are several ways to start a new process instance. In the following code snippet, we start the process instance using the keys we defined in the process definition XML. We also provide some process variables when the process instance starts, because the description of the first user task will use these variables in its expression. Process variables are often used because they give meaning to process instances defined by a particular process. In general, process variables make process instances different from each other.
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());
Copy the code
To complete the task
When the process begins, the first step will be the user task. This is a step that system users must perform. Typically, such a user has a task inbox that lists all the tasks that the user needs to complete. The following code snippet shows how to perform such a query:
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
for (Task task : tasks) {
Log.info("Task available: " + task.getName());
}
Copy the code
To continue with the process instance, we need to complete this task. For the Activiti engine, this means that you need to complete the task. The following code snippet shows how this is done:
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);
Copy the code
The process instance will now proceed to the next step. In this example, the next step is to allow the employee to fill out a form that adjusts their original leave request. The employee can resubmit the leave request, which causes the process to loop back to the start task.
Pause and activate processes
You can pause the process definition. When a process definition is suspended, new process instances cannot be created (an exception is thrown). A pause process definition is RepositoryService done by:
repositoryService.suspendProcessDefinitionByKey("vacationRequest");
try {
runtimeService.startProcessInstanceByKey("vacationRequest");
} catch (ActivitiException e) {
e.printStackTrace();
}
Copy the code