The use of Activiti is mainly divided into three steps:
1, Define process
Define a process according to the bpmn specification,
template file
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns: xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg. org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg. org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace ="http://www.activiti.org/test"> <process id="myProcess" name="My process" isExecutable="true"> <startEvent id="startevent1" name="Start"></startEvent> <userTask id="usertask1" name="Create leave request"></userTask> <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow> <userTask id="usertask2" name="Department Manager Review"></userTask> <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="usertask2"></sequenceFlow> <userTask id="usertask3" name="Personnel Review"></userTask> <sequenceFlow id="flow3" sourceRef="usertask2" targetRef="usertask3"></sequenceFlow> <endEvent id="endevent1" name="End"></endEvent> <sequenceFlow id="flow4" sourceRef="usertask3" targetRef="endevent1"></sequenceFlow> </process> <bpmndi:BPMNDiagram id="BPMNDiagram_myProcess"> <bpmndi:BPMNPlane bpmnElement="myProcess" id="BPMNPlane_myProcess"> <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1"> <omgdc:Bounds height="35.0" width="35.0" x="130.0" y="160.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1"> <omgdc:Bounds height="55.0" width="105.0" x="210.0" y="150.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2"> <omgdc:Bounds height="55.0" width="105.0" x="360.0" y="150.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="usertask3" id="BPMNShape_usertask3"> <omgdc:Bounds height="55.0" width="105.0" x="510.0" y="150.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1"> <omgdc:Bounds height="35.0" width="35.0" x="660.0" y="160.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1"> <omgdi:waypoint x="165.0" y="177.0"></omgdi:waypoint> <omgdi:waypoint x="210.0" y="177.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2"> <omgdi:waypoint x="315.0" y="177.0"></omgdi:waypoint> <omgdi:waypoint x="360.0" y="177.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3"> <omgdi:waypoint x="465.0" y="177.0"></omgdi:waypoint> <omgdi:waypoint x="510.0" y="177.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4"> <omgdi:waypoint x="615.0" y="177.0"></omgdi:waypoint> <omgdi:waypoint x="660.0" y="177.0"></omgdi:waypoint> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions>
Process symbols in BPMN specification
1. Event
- start
- middle
- Finish
2.Activity
- User tasks
- Service tasks
- Task sub-process
An activity can be a task or a word processing process of the current process. The activity can also specify different types.
3.GateWay
The gateway is used to handle decisions
- exclusive gateway
Only one path will be selected. When the process is executed to the gateway, it will be executed one by one according to the output order. When the condition is true, the current gateway will continue to be executed.
If there are multiple paths, the first line with a value of true will be executed. If all are true, an exception will be reported.
The exclusive gateway needs to be used in conjunction with the conditional sequence flow. The default attribute specifies the default sequence flow. When all conditions are not met, the sequence flow specified by default will be used.
- Parallel gateway
All paths will be selected simultaneously
Split—–Execute all output streams in parallel, creating a parallel execution line for each sequence six
Merge—-All lines split and executed by parallel gateways are waiting here, and execution will not continue until all lines are completed.
- inclusive gateway
Multiple lines can be executed at the same time, or conditions can be set on the gateway
Split—-calculate the expression on the line, if the result is true, create a parallel line for execution
Merge—-All lines split and executed by parallel gateways are waiting here, and execution will not continue until all lines are completed.
-
Integrated gateway
-
event gateway
It is used to capture event settings, allowing multiple output streams to execute multiple different intermediate capture events. When the process is executed to the event gateway, the process is in a waiting state and needs to wait until an event is thrown to convert the waiting state to the active state.
Create process file
Download the actiBPM plug-in in idea. The plug-in may not be found in the plug-in library.
actiBPMN plug-in download
Create a process file **.bmpn file in the resource folder, and then use the plug-in to draw the business process
Add each process-related person (applicant, approver…) to the process
Then we look at the event.bpmn file
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http: //www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http: //www.omg.org/spec/DD/20100524/DI" xmlns:tns="http://www.activiti.org/test" xmlns:xsd="http://www.w3. org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" expressionLanguage="http://www.w3.org/1999/XPath" id ="m1696900343930" name="" targetNamespace="http://www.activiti.org/test" typeLanguage="http://www.w3.org/2001/XMLSchema"> <process activiti:candidateStarterGroups="employee" activiti:candidateStarterUsers="Gavin" id="MyEvection" isClosed="false" isExecutable="true" name="Travel Application" processType ="None"> <startEvent id="_2" name="StartEvent"/> <userTask activiti:assignee="zhangsan" activiti:exclusive="true" id="_3" name="Travel Application"/> <userTask activiti:assignee="jerry" activiti:exclusive="true" id="_4" name="Department Manager Approval"/> <userTask activiti:assignee="tom" activiti:exclusive="true" id="_5" name="General Manager Approval"/> <userTask activiti:assignee="gavin" activiti:exclusive="true" id="_6" name="Financial Approval"/> <sequenceFlow id="_7" sourceRef="_2" targetRef="_3"/> <sequenceFlow id="_8" sourceRef="_3" targetRef="_4"/> <sequenceFlow id="_9" sourceRef="_4" targetRef="_5"/> <sequenceFlow id="_10" sourceRef="_5" targetRef="_6"/> <endEvent id="_11" name="EndEvent"/> <sequenceFlow id="_12" sourceRef="_6" targetRef="_11"/> </process> <bpmndi:BPMNDiagram documentation="background=#FFFFFF;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0" id="Diagram-_1" name="New Diagram"> <bpmndi:BPMNPlane bpmnElement="MyEvection"> <bpmndi:BPMNShape bpmnElement="_2" id="Shape-_2"> <omgdc:Bounds height="32.0" width="32.0" x="165.0" y="25.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_3" id="Shape-_3"> <omgdc:Bounds height="55.0" width="85.0" x="150.0" y="135.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_4" id="Shape-_4"> <omgdc:Bounds height="55.0" width="100.0" x="155.0" y="255.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="100.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_5" id="Shape-_5"> <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="355.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_6" id="Shape-_6"> <omgdc:Bounds height="55.0" width="85.0" x="160.0" y="450.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="55.0" width="85.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="_11" id="Shape-_11"> <omgdc:Bounds height="32.0" width="32.0" x="190.0" y="585.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="32.0" width="32.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="_12" id="BPMNEdge__12" sourceElement="_6" targetElement="_11"> <omgdi:waypoint x="206.0" y="505.0"/> <omgdi:waypoint x="206.0" y="585.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_7" id="BPMNEdge__7" sourceElement="_2" targetElement="_3"> <omgdi:waypoint x="181.0" y="57.0"/> <omgdi:waypoint x="181.0" y="135.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_8" id="BPMNEdge__8" sourceElement="_3" targetElement="_4"> <omgdi:waypoint x="195.0" y="190.0"/> <omgdi:waypoint x="195.0" y="255.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_9" id="BPMNEdge__9" sourceElement="_4" targetElement="_5"> <omgdi:waypoint x="202.5" y="310.0"/> <omgdi:waypoint x="202.5" y="355.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="_10" id="BPMNEdge__10" sourceElement="_5" targetElement="_6"> <omgdi:waypoint x="202.5" y="410.0"/> <omgdi:waypoint x="202.5" y="450.0"/> <bpmndi:BPMNLabel> <omgdc:Bounds height="0.0" width="0.0" x="0.0" y="0.0"/> </bpmndi:BPMNLabel> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions>
We can see that the .bpmn file is actually a file in xml format. Let’s try changing the suffix to .xml
Since the .xml file suffix is used instead of the native .bpmn file, how to generate a flow chart?
Right-click the file->>
After that, a picture will be generated: This picture is more beautiful and can be used to show to customers (it is not necessary for internal use)
Of course, you can also take screenshots. Anyway, there are many ways, so don’t worry too much;
If the process name is in Chinese, garbled characters may occur. Don’t worry.
If the code is still garbled, you need to modify the following two files:
Refer to this article-Three steps to solve the Chinese garbled problem of the .bpmn file of the IDEA actiBPM plug-in
Chinese version process
2, Deployment process
Load the process definition file into the database
@Test public void Test02() {<!-- --> //1, create processEngine ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2, Get the deployed service RepositoryService RepositoryService repositoryService = processEngine.getRepositoryService(); //3, use the RepositoryService instance to deploy the process, define a process name and then deploy it to the database DeploymentBuilder deployment = repositoryService.createDeployment(); //4, load deployment information into the database table Deployment deploy = deployment.name("Business trip application process").disableSchemaValidation().addClasspathResource("bpmn/evection.bpmn").addClasspathResource("bpmn/evection.png").deploy(); System.out.println("Process deployment id" + deploy.getId()); System.out.println("Process deployment name" + deploy.getName()); System.out.println("Process Deployment Catalog" + deploy.getCategory()); System.out.println("Process Deployment" + deploy.getTenantId()); System.out.println("Process Deployment" + deploy.getKey()); System.out.println("Process deployment time" + deploy.getDeploymentTime()); }
After the deployment is completed, we can see that there is data in the re table
The tables operated during deployment are:
- ACT_RE_DEPLOYMENT
Store deployment process information (name, deployment time, etc.)
DeploymentEntity[id=1, name=Business trip application process] 2023-10-10 11:45:14,089 2510 [main] DEBUG entEntityImpl.insertDeployment - ==> Preparing: insert into ACT_RE_DEPLOYMENT(ID_, NAME_, CATEGORY_, KEY_, TENANT_ID_, DEPLOY_TIME_, ENGINE_VERSION_) values(?, ?, ?, ?, ?, ?, ?) 2023-10-10 11:45:14,100 2521 [main] DEBUG entEntityImpl.insertDeployment - ==> Parameters: 1(String), Business trip application process (String), null, null, (String), 2023-10-10 11 :45:14.01(Timestamp), null 2023-10-10 11:45:14,102 2523 [main] DEBUG entEntityImpl.insertDeployment - <== Updates: 1
- ACT_GE_BYTEARRAY
Store deployment file information
Preparing: INSERT INTO ACT_GE_BYTEARRAY(ID_, REV_, NAME_, BYTES_, DEPLOYMENT_ID_, GENERATED_) VALUES (?, 1, ?, ?, ?, ?) , (?, 1, ?, ?, ?, ?) 2023-10-10 11:45:14,121 2542 [main] DEBUG eEntityImpl.bulkInsertResource - ==> Parameters: 2(String), bpmn/evection.png(String), java.io.ByteArrayInputStream@7a11c4c7(ByteArrayInputStream), 1 (String), false(Boolean), 3(String), bpmn/evection.bpmn(String), java.io.ByteArrayInputStream@4cc547a(ByteArrayInputStream), 1(String), false(Boolean) 2023-10-10 11:45:14,132 2553 [main] DEBUG eEntityImpl.bulkInsertResource - <== Updates: 2
ACT_RE_PROCDEF
process definition table
ACT_GE_PROPERTY
3, Start the process
The startup process requires the use of runtimeService,
@Test public void Test03() {<!-- --> //process engine ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //Get runtime service RuntimeService runtimeService = processEngine.getRuntimeService(); //Open an instance through key ProcessInstance myEvection = runtimeService.startProcessInstanceByKey("MyEvection"); System.out.println(myEvection.getProcessDefinitionId()); System.out.println(myEvection.getId()); System.out.println(myEvection.getActivityId()); }
At startup, an instance is started based on the key in the act_re_procdef table;
Tables used/operated when creating process instances
Mainly the following tables
Recorded process history table
Record the current process
Recorded the process time of the operation (start time and end time)
The entire process code for completing the task is as follows:
package gavin.test; import org.activiti.engine.*; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.DeploymentBuilder; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.junit.Test; import java.util.List; public class ActTest { //Create data table @Test public void Test01() { ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); System.out.println(engine); } /** * Deployment process * 1, create processEngine * 2. Get the deployed service RepositoryService * 3. Use the RepositoryService instance to deploy the process, define a process name and then deploy it to the database. * 4. Input the deployment information (.bpmn file and .png file) into the database table and output the deployment information */ @Test public void Test02() {<!-- --> //1, create processEngine ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //2, Get the deployed service RepositoryService RepositoryService repositoryService = processEngine.getRepositoryService(); //3, use the RepositoryService instance to deploy the process, define a process name and then deploy it to the database DeploymentBuilder deployment = repositoryService.createDeployment(); //4, load deployment information into the database table Deployment deploy = deployment.name("Business trip application process").disableSchemaValidation().addClasspathResource("bpmn/evection.bpmn").addClasspathResource("bpmn/evection.png").deploy(); System.out.println("Process deployment id" + deploy.getId()); System.out.println("Process deployment name" + deploy.getName()); System.out.println("Process Deployment Catalog" + deploy.getCategory()); System.out.println("Process Deployment" + deploy.getTenantId()); System.out.println("Process Deployment" + deploy.getKey()); System.out.println("Process deployment time" + deploy.getDeploymentTime()); } /** * hi_actinst process instance execution history * hi_identitylink process participation user history * hi_procinst process instance historical information * hi_taskinst process task history * ru_execution process execution information * ru_identitylink route participating user information * ru_task process task */ @Test public void Test03() {<!-- --> //process engine ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); //Get runtime service RuntimeService runtimeService = processEngine.getRuntimeService(); //Open an instance through key ProcessInstance myEvection = runtimeService.startProcessInstanceByKey("MyEvection"); System.out.println(myEvection.getProcessDefinitionId()); System.out.println(myEvection.getId()); System.out.println(myEvection.getActivityId()); } /** * Query the tasks performed by individuals */ @Test public void Test04() { ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = engine.getTaskService(); Listlist = taskService.createTaskQuery().processDefinitionKey("MyEvection").taskAssignee("zhangsan").list(); for (Task task: list) { System.out.println(task.getProcessInstanceId()); System.out.println(task.getId()); System.out.println(task.getAssignee()); System.out.println(task.getName()); } } /** *Complete task id */ @Test public void Test05() { ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = defaultProcessEngine.getTaskService(); taskService.complete("10005"); } /** * Query the tasks performed by individuals */ @Test public void Test06() { ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = engine.getTaskService(); List list = taskService.createTaskQuery().processDefinitionKey("MyEvection").taskAssignee("jerry").list(); for (Task task: list) { System.out.println(task.getProcessInstanceId()); System.out.println(task.getId()); System.out.println(task.getAssignee()); System.out.println(task.getName()); } } /** *Complete task id */ @Test public void Test07() { ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = defaultProcessEngine.getTaskService(); taskService.complete("17502"); } /** * Query the tasks performed by individuals */ @Test public void Test08() { ProcessEngine engine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = engine.getTaskService(); List list = taskService.createTaskQuery().processDefinitionKey("MyEvection").taskAssignee("tom").list(); for (Task task: list) { System.out.println(task.getProcessInstanceId()); System.out.println(task.getId()); System.out.println(task.getAssignee()); System.out.println(task.getName()); } } /** *Complete task id */ @Test public void Test09() { ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = defaultProcessEngine.getTaskService(); taskService.complete("20002"); } /** *Complete task id */ @Test public void Test10() { ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine(); TaskService taskService = defaultProcessEngine.getTaskService(); taskService.complete("22502"); } }
summary:
1. Get processengine-to generate data table
2. Deploy the corresponding workflow
Obtain the deployment service (deployment file *.bpmn and flow chart) repositoryService through processengine
3. Start the process instance
Get runtime after getting runtimeservice
4. Processing workflow
Obtain the taskservice completion process instance to proceed to the next step.
Packaging and deployment
@Test public void deployProcessZip() {<!-- --> ProcessEngine defaultProcessEngine = ProcessEngines.getDefaultProcessEngine(); RepositoryService repositoryService = defaultProcessEngine.getRepositoryService(); //Get stream---read resources InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/evection.zip"); //Flow into the constructor ZipInputStream zipInputStream = new ZipInputStream(inputStream); Deployment deploy = repositoryService.createDeployment().disableSchemaValidation().addZipInputStream(zipInputStream).deploy(); System.out.println(deploy.getId()); System.out.println(deploy.getName()); }