Table of contents
3.1, what is a process instance
3.2. Associate the actual business with the activiti table (BusinessKey)
3.3. Suspend and activate the process instance
3.3.1. All process instances are suspended
3.3.2. A single process instance hangs
5.1, what is a process variable
5.2, the scope of process variables
5.3. How to use process variables
5.4, set the global variable
5.4.1. Set variables when starting the process
5.4.2. Set process variables when handling tasks
5.4.3, through the current process instance settings
6.1, Candidate-users candidates
6.2. Group task handling process
6.3.3. Query personal to-do tasks
3. Process example
Basic operation reference: Basic use of Activiti_Relievedz's Blog-CSDN Blog
3.1, what is a process instance
Process definition ProcessDefinition and process instance ProcessInstance are important concepts of Activiti, similar to the relationship between Java classes and Java instances
Starting a process instance means starting a business process operation. For example, the deployment of the employee leave process is completed. If Zhang San wants to ask for leave, he can start a process instance. If Li Si wants to ask for leave, he can also start a process instance. The execution of the two processes does not affect each other. , just like defining a java class and instantiating two objects, the deployment process is like a java class, starting a process instance is like new a java object
3.2. Associate the actual business with the activiti table (BusinessKey)
For example, if we fill out a leave form, there must be a unique identification of the leave form. We usually use this identification to associate activiti. This identification is called businesskey in activiti
BusinessKey: business identifier, usually the primary key of the business, the business identifier and the process identifier correspond one-to-one, the business identifier comes from the business system, and the storage of the business identifier is to associate and query the data of the business system according to the business identifier
For example: when the leave process starts a process instance, the id of the leave request can be stored in activiti as a business identifier. In the future, the id of the leave request can be obtained by querying the process instance information of activiti, so as to query the business system database to obtain the leave request information
/** * Start the process instance, add businessKey */ @Test public void startUpProcessAddBusinessKey(){ String businessKey = "1"; // Start the process instance, specify the business identifier businessKey, which is the leave application form id ProcessInstance processInstance = runtimeService.startProcessInstanceByKey ("qingjia",businessKey); // output System.out.println("business id:"+processInstance.getBusinessKey()); }
3.3. Suspend and activate the process instance
In some cases, it may be necessary to suspend the currently running process instead of directly deleting it due to process changes. After the process is suspended, it will not be executed;
3.3.1. All process instances are suspended
The operation process definition is in a suspended state, and all process instances under the process definition are suspended: The process definition is in a suspended state, and the process definition will not allow new process instances to be started, and at the same time, all process instances under the process definition will be suspended suspend execution
//Suspend all process instances @Test public void suspendProcessInstanceAll() { //1 Get the process definition object ProcessDefinition qingjia = repositoryService.createProcessDefinitionQuery() .processDefinitionKey("qingjia").singleResult(); //2 Call the process definition object The method to judge the current state: suspend activation boolean suspended = qingjia.isSuspended(); //3 judge if suspended, realize activation if(suspended) { //The first parameter process definition id //The second parameter is activated true //The third parameter time point repositoryService .activateProcessDefinitionById(qingjia.getId(), true,null); System.out.println(qingjia.getId()+"activated"); } else { //If activated, implement suspension repositoryService .suspendProcessDefinitionById(qingjia.getId(), true,null); System.out.println(qingjia.getId()+"suspend"); } }
3.3.2. A single process instance hangs
Operate the process instance object, execute the suspend operation for a single process, if a process instance is suspended, the process will not continue to execute, and an exception will be reported when the current task of the process instance is completed;
//单个流程实例挂起 @Test public void SingleSuspendProcessInstance() { String processInstanceId = "b98e42b3-df27-11ed-b184-005056c00001"; ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() .processInstanceId(processInstanceId) .singleResult(); boolean suspended = processInstance.isSuspended(); if (suspended) { //激活 runtimeService.activateProcessInstanceById(processInstanceId); System.out.println(processInstanceId + "激活"); } else { runtimeService.suspendProcessInstanceById(processInstanceId); System.out.println(processInstanceId + "Pending"); } }
4. Task assignment
There are three ways to assign tasks
-
fixed allocation
-
UEL expression assignment
-
listener assignment
4.1. Fixed distribution
Specify a fixed task leader in the previous business process modeling, such as: Assignee: zhangsan/lisi
4.2. Expression assignment
activiti uses UEL expressions. UEL is part of the java EE6 specification. UEL is the unified expression language. activiti supports two UEL expressions: UEL-value and UEL-method.
4.2.1、UEL-value
New: an overtime process
As shown in the picture:
assignee1 This variable is a process variable of activiti
We start the process instance. The method of starting the instance is basically the same as the previous method. The only difference is that a parameter is added at startup
@Test public void deployProcess01() { // Process deployment Deployment deploy = repositoryService.createDeployment() .addClasspathResource("process/jiaban.bpmn20.xml") .name("Overtime application process") .deploy(); System.out .println(deploy.getId()); System.out.println(deploy.getName()); } /** * Start process instance */ @Test public void startUpProcess01() { Map<String, Object> map = new HashMap<>(); map.put("assignee1","lucy"); map.put("assignee2","mary"); //To create a process instance, we need to know the key of the process definition ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("jiaban", map); //Output instance related information System.out.println("process definition id:" + processInstance.getProcessDefinitionId()); System.out.println("process instance id:" + processInstance. getId()); }
4.2.2, UEL-method
As shown in the picture:
userBean is a bean in the spring container, which means calling the bean's getUsername(int id) method.
Manager approval: ${userBean.getUsername(1)}
Personnel approval: ${userBean.getUsername(2)}
package com.atguigu.auth.activiti; import org.springframework.stereotype.Component; /** * @program: guigu-oa-perent * @description: userBean is a bean in the spring container, which means calling the bean's getUsername( int id) method. * @author: Mr.Zhang * @create: 2023-04-20 11:42 **/ @Component public class UserBean { public String getUsername(int id) { if(id == 1) { return "lilei"; } if(id == 2) { return "wyz"; } return "admin"; } }
Deploy and start
/ //uel-method @Test public void deployProcess01() { Deployment deployment = repositoryService.createDeployment() .addClasspathResource("process/jiaban01.bpmn20.xml") .name("加班申请流程01") .deploy(); System.out.println(deployment.getId()); System.out.println(deployment.getName()); } @Test public void startProcessInstance01() { ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("jiaban01"); System.out.println(processInstance.getProcessDefinitionId()); System.out.println(processInstance.getId()); }
When the process instance is started, the bean method will be called, the parameter is: 1, after the manager approves, then the bean method is called, the parameter is: 2
4.3. Listener assignment
Use the listener method to specify the person in charge, so you don't need to specify the assignee when designing the process.
The task listener is to execute custom java logic or expression when the corresponding task-related event occurs
Event options include:
Create: Triggered after the task is created Assignment: Triggered after the task is assigned Delete: Triggered after the task is completed All: Triggered when all events occur
Define the task listening class, and the class must implement the org.activiti.engine.delegate.TaskListener interface
package com.atguigu.auth.activiti; import org.activiti.engine.delegate.DelegateTask; import org.activiti.engine.delegate.TaskListener; /** * @program: guigu-oa-perent * @description: Define task listener class * @author: Mr.Zhang * @create: 2023-04-21 08:55 **/ public class MyTaskListener implements TaskListener { @Override public void notify(DelegateTask task) { if(task.getName().equals(" Manager Approval")){ // Assign task task.setAssignee("jack"); } else if (task.getName().equals("Personnel Approval")) { task.setAssignee("tom"); } } }
Configure the listener
Both manager approval and personnel approval can be set to the same monitor
Deploy and test
// //监听器分配任务 @Test public void deployProcess02() { Deployment deployment = repositoryService.createDeployment() .addClasspathResource("process/jiaban02.bpmn20.xml") .name("加班申请流程02") .deploy(); System.out.println(deployment.getId()); System.out.println(deployment.getName()); } @Test public void startProcessInstance02() { ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("jiaban02"); System.out.println(processInstance.getProcessDefinitionId()); System.out.println(processInstance.getId()); }
When the process instance is started, the MyTaskListener listening method will be called
5. Process variables
5.1, what is a process variable
Process variables play a very important role in activiti. Process operation sometimes depends on process variables. When combining business systems and activiti, process variables are indispensable. Process variables are variables that activiti sets according to management needs when managing workflow. For example: when the leave application process flows, if the number of days of leave is more than 2 days, it will be reviewed by the general manager, otherwise it will be directly reviewed by the department manager. The number of days of leave can be set as a process variable and used during process flow.
5.2, the scope of process variables
The role of a process variable can be a process instance, but it can also be a task (task) or an execution instance
5.2.1, global variables
The default scope of process variables is the process instance. When the scope of a process variable is the process instance, it can be called a global variable
The variable name in the global variable is not allowed to be repeated. If you set a variable with the same name, the value set later will overwrite the variable value set before.
5.2.2, local variables
Tasks and execution instances are only for one task and one execution instance range, and the scope is not as large as the process instance, which is called local variables.
Because the scope of Local variables does not affect each other in different tasks or different execution instances, the variable names can be the same without any influence. The local variable name can also be the same as the global variable name, it has no effect.
5.3. How to use process variables
Using process variables through UEL expressions
1. We have also used UEL expressions to set the task handler before, such as ${assignee1}, activiti obtains the value of the UEL expression, that is, the value of the process variable assignee1, and assigns the value as the person in charge of the task. 2. We You can also use UEL expressions on the connection between tasks to determine the direction of the process, such as ${day > 2 } and ${day <= 2}, day is a process variable name, and the execution result of the UEL expression is Boolean type
5.4, set the global variable
5.4.1. Set variables when starting the process
Set the process variable when starting the process, and the scope of the variable is the entire process instance. Set the process variable through Map<key,value>, multiple variables can be set in the map, this key is the name of the process variable
This is the previous example code
@Test public void startUpProcess() { Map<String, Object> variables = new HashMap<>(); variables.put("assignee1", "zhangsan"); variables.put("assignee2", "lisi"); / /To create a process instance, we need to know the key of the process definition ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("qingjia", variables); //Output related information of the instance System.out.println("process definition id:" + processInstance.getProcessDefinitionId( )); System.out.println("Process instance id: " + processInstance.getId()); }
5.4.2. Set process variables when handling tasks
Its scope is the entire process instance . If the key of the set process variable already has the same name in the process instance, the variable set later will replace the variable set earlier.
Simulation example code:
@Test public void completTask() { Task task = taskService.createTaskQuery() .taskAssignee("zhangsan") //The person in charge to be queried.singleResult ();//Return a Map <String, Object> variables = new HashMap <>(); variables.put("assignee2", "zhao"); //Complete the task, parameter: task id taskService.complete(task.getId(), variables); }
5.4.3, through the current process instance settings
The global variable is set through the process instance id, and its scope is the entire process instance , which must not be completed.
Simulation example code:
@Test public void processInstanceIdSetVariables() { Map<String, Object> variables = new HashMap<>(); variables.put("assignee2", "wang"); runtimeService.setVariables("1c347a90-82c6-11ed-96ca-7c57581a7819", variables); }
5.5. Set Local variables
The scope of local process variables is only available under the current task node
When a task is processed, a local process variable is set. The currently running process instance can only be used before the end of the task. The variable cannot be used in the current process instance after the task ends.
Simulation example code:
@Test public void completLocalTask() { Task task = taskService.createTaskQuery() .taskAssignee("zhangsan") //The person in charge to be queried.singleResult ();//Return an item // Set the local variable, the scope is this Task taskService.setVariableLocal(task.getId(),"assignee2","li"); // View local variables System.out.println(taskService.getVariableLocal(task.getId(), "assignee2")); //Complete Task, parameter: task id taskService.complete(task.getId()); }
6. Task group
6.1, Candidate-users candidates
1. Requirements In the process definition, the task leader is fixed in the assignee of the task node, and the participants are fixed in the .bpmn file when the process is defined. If you want to temporarily change the task leader, you need to modify the process definition. System scalability Very poor, for this situation, we can set multiple candidates for the task, and select participants from the candidates to complete the task
2. Set task candidates
6.2. Group task handling process
Step 1: Query Group Tasks
Designate a candidate and query the candidate's current to-do tasks Candidates cannot handle tasks Step 2: Claim tasks
All candidates for this group of tasks can be picked up. Turn the candidate's group task into a personal task, and the original candidate becomes the person in charge of the task. If you do not want to handle the task after picking it up, you need to pick it up Step 3 : Query personal tasks
The query method is the same as the personal task part, and the personal task that the user is responsible for is queried according to the assignee. Step 4: Handle personal tasks
6.3. Key code
6.3.1, deployment and start
@Test public void deployProcess04() { // 流程部署 Deployment deploy = repositoryService.createDeployment() .addClasspathResource("process/jiaban04.bpmn20.xml") .name("请假申请流程") .deploy(); System.out.println(deploy.getId()); System.out.println(deploy.getName()); ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("jiaban04"); System.out.println(processInstance.getId()); }
6.3.2. Query group tasks
@Test public void findGroupTaskList() { //Query group task List<Task> list = taskService.createTaskQuery() .taskCandidateUser("zhangsan01")//Query based on candidate.list (); for (Task task : list) { System.out.println("----------------------------"); System.out.println("Process instance id:" + task.getProcessInstanceId()); System.out.println("Task id: " + task.getId()); System.out.println("Task owner: " + task.getAssignee()); System.out .println("Task name: " + task.getName()); } }
6.3.2. Pick up group tasks
@Test public void claimTask(){ //Pick up a task, even if the user is not a candidate (it is recommended to check whether the user is eligible) //Check whether the user is eligible to pick up the task Task task = taskService.createTaskQuery () .taskCandidateUser("zhangsan01")//Query according to the candidate.singleResult (); if(task!=null){ //Pick up the task taskService.claim(taskId, "zhangsan01"); System.out.println(" Task picked up successfully"); } }
Zhang San 01 has picked up the task, but Zhang San 02 cannot pick it up
6.3.3. Query personal to-do tasks
The query method is the same as personal task query
@Test public void findGroupPendingTaskList() { //Task leader String assignee = "zhangsan01"; List<Task> list = taskService.createTaskQuery() .taskAssignee(assignee)//Only query the tasks of the task leader.list () ; for (Task task : list) { System.out.println("Process instance id: " + task.getProcessInstanceId()); System.out.println("Task id: " + task.getId()); System. out.println("Task owner: " + task.getAssignee()); System.out.println("Task name: " + task.getName()); } }
6.3.4. Handle personal tasks
with personal tasks
@Test public void completGroupTask() { Task task = taskService.createTaskQuery() .taskAssignee("zhangsan01") //The person in charge to be queried.singleResult ();//Return a taskService.complete(task.getId()); }
6.3.5. Return group tasks
If an individual does not want to handle the group task, he can return the group task, after which the user is no longer the person in charge of the task
@Test public void assigneeToGroupTask() { String taskId = "d96c3f28-825e-11ed-95b4-7c57581a7819"; // Task leader String userId = "zhangsan01"; // Check whether userId is the person in charge of taskId, if it is responsible Talents can return group tasks Task task = taskService .createTaskQuery() .taskId(taskId) .taskAssignee(userId) .singleResult(); if (task != null) { // If set to null, return group tasks, the task does not Assignee taskService.setAssignee(taskId, null); } }
6.3.6. Task handover
Task handover, the task leader hands over the task to other candidates to handle the task
@Test public void assigneeToCandidateUser() { // Current to-do task String taskId = "d96c3f28-825e-11ed-95b4-7c57581a7819"; // Check whether zhangsan01 is the person in charge of the taskId, and if so, can return the group task Task task = taskService .createTaskQuery() .taskId(taskId) .taskAssignee("zhangsan01") .singleResult(); if (task != null) { // Give this task to other candidate zhangsan02 to handle the task taskService.setAssignee( taskId, "zhangsan02"); } }
7. Gateway
Gateways are used to control the flow of processes and are usually used together with process variables.
7.1. Exclusive Gateway
-
Exclusive gateway: only one path will be chosen
When there is such a scenario in your process: leave application, within two days, the approval process of the department manager is over, and the general manager needs to approve it directly after more than two days. At this time, an exclusive gateway is needed.
7.2. Parallel Gateway
-
Parallel (parallel) gateways: all paths will be selected at the same time
When such a scenario occurs: the leave application needs to be approved by both the department manager and the general manager. If there is no before and after the two, both people need to approve it before proceeding to the next node for personnel approval. At this time, a parallel gateway is required
The main difference from exclusive gateways is that parallel gateways do not resolve conditions. Even if a condition is defined in the sequence flow, it will be ignored.
7.3, including the gateway
Inclusive gateway: Multiple routes can be executed at the same time, and conditions can also be set on the gateway, which can be regarded as a combination of exclusive gateway and parallel gateway. When such a scenario occurs: the leave application must be approved by the general manager of the department for more than or equal to 2 days, and the department manager for less than 2 days, and the leave application must be approved by the HR manager. At this time, the gateway needs to be included