Workflow learning log (basic concepts, basic api usage)

Workflow learning log (basic concepts, basic api usage)


When developing OA human resource management system, workflow needs to be used in personnel transfer, leave approval, etc. as a learning opportunity.

1, What is workflow?

1. Concept

Workflow is the automatic execution and management of business processes through computers. It mainly solves "the process of automatically transferring documents, information or tasks among multiple participants according to some predefined rules, so as to achieve a certain business goal or promote the realization of this goal."

2. Specific use in actual development

  1. Key business processes: order, quotation processing, contract review, customer telephone processing, supply chain management, etc
  2. Administrative management: travel application, overtime application, leave application, vehicle application, various office supplies application, purchase application, date weekly report and other administrative forms that were originally processed manually
  3. Personnel management: employee training arrangement, performance evaluation, position change processing, employee file information management, etc
  4. Finance related categories: payment request, accounts payable processing, daily reimbursement processing, business trip reimbursement, budget and plan application, etc
  5. Customer service: customer information management, customer complaints, request handling, after-sales service management, etc
  6. Special services: ISO series corresponding processes, quality management corresponding processes, product data information management, customs declaration processing of trading companies, cargo tracking of logistics companies and other tasks completed by gradual manual flow through forms can be implemented automatically and standardized by workflow software.

3. Implementation mode

  • Before workflow is not used, in order to realize process control, the value of status field is usually used to track the change of process. In this way, users with different roles can determine whether records are displayed through the value of the status field.
  • For records that can be viewed with permission, the current user determines whether the approval is qualified according to his role. If qualified, set a value in the rigid status field to indicate qualified; If it is unqualified, a corresponding value is also set.
  • This is the most primitive way. Although process control can be achieved through the status field, when our process changes, the code written in this way also needs to be adjusted.
  • Therefore, we use a professional way to realize the management of workflow, and after the business process can be changed, our program can not be changed. At this time, we need to use the workflow system, which can greatly improve the adaptability of our business system.

2, Activiti7 overview

1. Introduction

Alfresco software announced the official launch of activiti business process management (BPM) open source project on May 17, 2010. jbpm is a very famous workflow engine, and activiti is also a workflow engine. Activiti can extract complex services from the business system and use special modeling voice BPMN2 0, and the business process is executed according to the pre-defined process, which realizes that the process of the system is managed by activit, and reduces the workload of system upgrading and transformation of the business system due to process change, so as to improve the robustness of the system and reduce the cost of system development and maintenance.
Activiti official website:

2. BPM

BPM (Business Process Management), that is, business process management, is a standardized end-to-end business process to continuously improve the business efficiency of the organization. BPM is included in common business management education such as EMBA and MBA.

3. BPM software

BPM software is an IT tool that promotes the integration and adjustment of business methods and solutions between people, between people and systems and between systems according to the changes of business environment in enterprises.

Through BPM software, the whole life cycle of internal and external business processes of the enterprise is modeled, automated, managed, monitored and optimized, so as to reduce the cost and greatly improve the profit of the enterprise.

BPM software is widely used in enterprises. Where there are business processes, BPM software can be used for management, such as enterprise personnel office management, procurement process management, document approval process management, financial management, etc.


BPMN (business process model and notation) - business process models and symbols are a set of standard business process modeling symbols developed by BPMI (business process management initiative). Business processes can be created using the symbols provided by BPMN.
The code is as follows (example):

III Use of Activiti7

1. Development preparation

  • jdk1.8
  • MySQL5.5
  • idea
  • tomcat8.5
  • maven

2. Download process designer

  • You can directly search for actiBPM in the plugins of IDEA for installation
  • If no results can be found in plugins. In the IDEA plug-in Market: Search and download, and then install offline in plugins

3. Create activiti database


4. Use Activiti7 to create the required database tables

Create preparation

  1. Create a maven foundation project
  2. Add relevant maven dependencies required by Activiti7 (the test version is used here and can be replaced with a stable version later)

        <!-- bpmn Model processing -->
        <!-- bpmn transformation -->
        <!-- bpmn json data conversion -->
        <!-- bpmn layout -->
        <!-- activiti Cloud support -->
        <!-- mysql drive -->
        <!-- mybatis -->
        <!-- Link pool -->
        <!-- log start -->
  1. configuration
# Set root category priority to INFO and its only appender to CONSOLE.
#log4j.rootCategory=INFO, CONSOLE debug info warn error fatal
log4j.rootCategory=debug, CONSOLE, LOGFILE
# Set the enterprise logger category to FATAL and its only appender to CONSOLE., CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x - %m\n
# LOGFILE is set to be a File appender using a PatternLayout.
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p %30.30c %x - %m\n
  1. Activiti7 requires activiti cfg. XML (file name must be consistent, activiti default file name) configuration
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""

    <!-- By default, bean of id fixed processEngineConfiguration -->
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!-- Configuration database related information -->
        <!--Database driven-->
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver"/>
        <!--Database connection can be abbreviated"jdbc:mysql:///activiti"-->
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti"/>
        <!--Database user name-->
        <property name="jdbcUsername" value="root"/>
        <!--Database password-->
        <property name="jdbcPassword" value="root"/>
        <!--activiti Strategy of database table generation  true->If the corresponding table already exists in the database, it can be used directly. If it does not exist, it will be created.-->
        <property name="databaseSchemaUpdate" value="true"/>
  1. Use the tool classes provided by Activiti7 to create the required database tables
     * Use the default method provided by activiti to create MySQL tables
    public void testCreateDbTable(){
        //You need to use the tool class ProcessEngines provided by activiti and the method getDefaultProcessEngine provided by activiti.
        //getDefaultProcessEngine will read the name activiti. From resources by default cfg. XML (so the name cannot be wrong when creating the file)
        //When you create a processEngine, MySQL tables are created
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

Introduction to activiti table structure

  • The database tables created are based on ACT_ Beginning, easy to identify. A total of 25 tables were created.
  • The second part is a two letter identification indicating the purpose of the table. The purpose also corresponds to the API of the service. ACT_RE:'RE 'means repository. This prefix table contains the process definition and process static resources (images, rules, etc.). ACT_RU: 'RU' means runtime. These runtime tables contain process instances, tasks, variables, asynchronous tasks, and other running data. These data records will only be deleted at the end of the process when the process is saved. In this way, the runtime table can always be small and fast. ACT_HI: 'HI' indicates history. These tables contain historical data, such as historical process instances, variables, tasks, and so on. ACT_GE: GE stands for general. Common data for different scenarios.
Table classificationTable nameexplain
General data
[ACT_GE_BYTEARRAY]Common process definitions and process resources
[ACT_GE_PROPERTY]System related attributes
Process history
[ACT_HI_ACTINST]Historical process instances
[ACT_HI_ATTACHMENT]Historical process attachments
[ACT_HI_COMMENT]Historical explanatory information
[ACT_HI_DETAIL]Details of historical process operation
[ACT_HI_IDENTITYLINK]User relationship during historical process operation
[ACT_HI_PROCINST]Historical process instances
[ACT_HI_TASKINST]Historical task instances
[ACT_HI_VARINST]Variable information in historical process operation
Process definition table
[ACT_RE_DEPLOYMENT]Deployment unit information
[ACT_RE_MODEL]Model information
[ACT_RE_PROCDEF]Deployed process definition
Run instance table
[ACT_RU_EVENT_SUBSCR]Runtime events
[ACT_RU_EXECUTION]Process execution instance
[ACT_RU_IDENTITYLINK]The runtime user relationship information stores the relevant information of task nodes and participants
[ACT_RU_JOB]Runtime job
[ACT_RU_TASK]Runtime tasks
[ACT_RU_VARIABLE]Runtime variable table

5. Activiti relationship

Process engine configuration class

The main categories are as follows:

1. StandaloneProcessEngineConfiguration

Using StandaloneProcessEngineConfigurationActiviti, you can run it separately to create a ProcessEngine, and Activiti will handle transactions by itself.

Usually in activiti cfg. Define a bean with id processEngineConfiguration in the XML configuration file

    <!-- By default, bean of id fixed processEngineConfiguration -->
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!-- Configuration database related information -->
        <!--Database driven-->
        <property name="jdbcDriver" value="com.mysql.jdbc.Driver"/>
        <!--Database connection can be abbreviated"jdbc:mysql:///activiti"-->
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activiti"/>
        <!--Database user name-->
        <property name="jdbcUsername" value="root"/>
        <!--Database password-->
        <property name="jdbcPassword" value="root"/>
        <!--activiti Strategy of database table generation  true->If the corresponding table already exists in the database, it can be used directly. If it does not exist, it will be created.-->
        <property name="databaseSchemaUpdate" value="true"/>

You can also create a connection pool:

<!--use dbcp Create a connection pool-->
    <bean id="dataSources" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <!--Database connection can be abbreviated"jdbc:mysql:///activiti"-->
        <property name="url" value="jdbc:mysql://localhost:3306/activiti"/>
        <!--Database user name-->
        <property name="username" value="root"/>
        <!--Database password-->
        <property name="password" value="root"/>
        <!--dbcp Unique configuration-->
        <property name="maxActive" value="3"/>
        <property name="maxIdle" value="1"/>

    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <!--Configure by referencing the connection pool-->
        <property name="dataSource" ref="dataSources"/>
        <!--activiti Strategy of database table generation  true->If the corresponding table already exists in the database, it can be used directly. If it does not exist, it will be created.-->
        <property name="databaseSchemaUpdate" value="true"/>

2. SpringProcessEngineConfiguration

Work engine creation method

  1. Create using the default method
//---------------------Configure processEngine by default
//You need to use the tool class ProcessEngines provided by activiti and the method getDefaultProcessEngine provided by activiti.
 //getDefaultProcessEngine will read the name activiti. From resources by default cfg. XML (so the name cannot be wrong when creating the file)
 //When you create a processEngine, MySQL tables are created
 ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
 RepositoryService repositoryService = processEngine.getRepositoryService();
  1. Create in a custom way
//--------------------Create a processEngine in a customized way
//The name of the configuration file can be customized. The id in the bean can also be customized
ProcessEngineConfiguration processEngineConfiguration = ProcessEngineConfiguration
        .createProcessEngineConfigurationFromResource("activiti.cfg.xml", "processEngineConfiguration");
//Get process engine object
ProcessEngine processEngine = processEngineConfiguration.buildProcessEngine();

Servcie service interface

  • The services that the process engine class can operate on are as follows: (in the old version, for example, IdentityService and FormService in Activiti6 have been abolished in 7)

    service interface:
    |Service name | service function|
    | ------------------ | ---------------------------- |
    |Resource management class of RepositoryService | activiti|
    |RuntimeService | activiti's process operation management class|
    |Taskservice | task management class of activiti|
    |Historyservice | history management class of activiti|
    |Managerservice | engine management class of activiti|

Introduction to common interfaces

  • RepositoryService
    • It is the resource management class of activiti, which provides operations for managing and controlling process release packages and process definitions. The business process diagram designed with workflow modeling tool needs to use this service to deploy the content of the process definition file to the computer.
    • In addition to deploying process definitions, you can also: query the publishing package and process definitions in the engine.
    • Pause or activate the release package, corresponding to all and specific process definitions. Pause means that they can no longer perform any operation, and activation is the corresponding reverse operation. Obtain a variety of resources, such as files contained in the release package, or flow charts automatically generated by the engine.
    • Get the pojo version of the process definition, which can be used to parse the process through java instead of xml.
  • RuntimeService
    • Activiti's process operation management class. You can get a lot of information about process execution from this service class
  • TaskService
    • Activiti's task management class. You can get the information of the task from this class.
  • HistoryService
    • Activiti's history management class can query historical information. When executing a process, the engine will save a lot of data (according to the configuration), such as the start time of the process instance, the participants of the task, the time to complete the task, the execution path of each process instance, and so on. This service mainly obtains these data through the query function.
  • ManagementService
    • Activiti's engine management class provides the management and maintenance functions of activiti process engine. These functions are not used in workflow driven applications, but mainly used for the daily maintenance of activiti system.

6. Use of actibpm plug-in

1. Set the work flow chart

Using the plug-in can easily design the workflow. It is a bpmn file, and the bottom layer is an xml file. The plug-in is an xml file that graphically displays the workflow. It is convenient for developers to design.

When creating a bpmn file, as shown in the figure: for a general bpmn file, the id of the canvas (existing in the database as a key) and the name of the whole workflow must be set

Set up tasks in the workflow diagram

2. Export flow chart as png picture

  1. Set the created bpmn file to xml file format
  2. Right click on the xml file page to generate a process graph
  3. Use the export function to obtain png files
  4. Store the obtained png file in the folder of bpmn in resource.
  5. Finally, rename the xml file to bpmn file.

7. Activiti7 basic use

1. Process deployment

  1. Use the process designer and process symbols to draw the flow chart
    • Get bpmn file and png file
    • They are all process resource files, which are used to describe the process, the nodes required in the process and the person in charge of the node
    • Travel application process, leave application process and reimbursement application process
  2. Deploy the resource files of the process
    • Upload to the database and use java code for process deployment
    • One deployment operation:
      • ACT_ RE_ Deploy generates a record
      • ACT_RE_PROCDEF generates process definition information
  3. One to many relationship between deployment and procdef tables
    • There can be multiple records in the procdef table, and each record corresponds to the definition information of a process

The code is as follows:

//Get processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

//Get the repositoryService instance
RepositoryService repositoryService = processEngine.getRepositoryService();

//Deploy using repository service
Deployment deployment = repositoryService.createDeployment()
        .name("Travel application process")

//Output deployment information
System.out.println("Deployed id="+deployment.getId());
System.out.println("Name of the deployment=="+deployment.getName());

Deploy using zip files:

//1. Get processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

//2. Obtain repositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();

//Get the input stream to zip
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream("bpmn/");
ZipInputStream zipInputStream = new ZipInputStream(inputStream);

//3. Use the method in the repository service for deployment, and use the zip file. In the way of using compressed package, the name is generally not set.
Deployment deploy = repositoryService.createDeployment()

System.out.println("Process deployment id="+deploy.getId());
System.out.println("Process deployment name name="+deploy.getName());

2. Process startup

//Get processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
//Get RuntimeService instance
RuntimeService runtimeService = processEngine.getRuntimeService();
//Use the method in RuntimeService to start the process
ProcessInstance instance = runtimeService.startProcessInstanceByKey("myBusinessTrip");

//Output content
System.out.println("Process definition ID="+instance.getProcessDefinitionId());
System.out.println("Process instance ID="+instance.getId());
System.out.println("current activity ID="+instance.getActivityId());

After the process is started, the following tables in the database will be added and modified:

  • act_hi_actinst process instance execution history
  • act_ hi_ History information of participating users in the identitylink process
  • act_hi_procinst process instance history information
  • act_hi_taskinst process task history information
  • act_ru_execution process execution information
  • act_ ru_ Participating user information of identitylink process
  • act_ru_task task information

3. Query personal task list

//Select the person in charge
String assignee = "zhangsan";

//Get processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

//Get taskService
TaskService taskService = processEngine.getTaskService();

//Use TaskService to query tasks according to the process key and task leader
List<Task> list = taskService.createTaskQuery()
        .processDefinitionKey("myBusinessTrip")//key of process
        .taskAssignee(assignee)//Query the task of the person in charge

//Traverse to get task content
for (Task task : list) {
    System.out.println("Process example:"+task.getProcessInstanceId());
    System.out.println("task id: "+task.getId());
    System.out.println("Task leader:"+task.getAssignee());
    System.out.println("Task name:"+task.getName());

4. Execute the selected task

String assignee = "zhaoliu";

//1. Create processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

//2. Get TaskService
TaskService taskService = processEngine.getTaskService();

//3. Use the method in TaskService (use task id) to complete the task
//        taskService.complete("2505");

//4. Obtain the corresponding task id according to the key of the process and the name of the person in charge, and complete the task dynamically
Task task = taskService.createTaskQuery()
        .processDefinitionKey("myBusinessTrip")//key of process
        .taskAssignee(assignee)//Name of task leader
        .singleResult();//Get a single task

System.out.println("Task id="+task.getProcessDefinitionId());
System.out.println("task id="+task.getId());
System.out.println("Name of the task="+task.getName());
System.out.println("Person in charge of the task="+task.getAssignee());

//5. Dynamically obtain the task id and complete the task

Tables involved in execution:


5. View process definition query

//1. Get processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

//2. Get the repositoryService object
RepositoryService repositoryService = processEngine.getRepositoryService();

//3. Use the method in the repository service to query the process definition
List<ProcessDefinition> myBusinessTrip = repositoryService
        .createProcessDefinitionQuery()//Create process definition query
        .processDefinitionKey("myBusinessTrip")//Get process definition according to key
        .orderByProcessDefinitionVersion()//According to database act_ re_ Sort the version in procdef (process definition database)
        .desc()//Reverse sort
        .list();//Encapsulate the results of the process definition query with a list

//Traversal output information
for (ProcessDefinition processDefinition : myBusinessTrip) {
    System.out.println("Process definition ID="+processDefinition.getId());
    System.out.println("Process definition name="+processDefinition.getName());
    System.out.println("Process definition key="+processDefinition.getKey());
    System.out.println("Process definition version="+processDefinition.getVersion());

6. Process deletion

  • Delete process deployment information
    • It can be said that the content act in the database after the deployment operation is deleted_ ge_ bytearray/act_ re_ deployment/act_ re_ procdef
    • When the process is started, you cannot use repositoryservice deleteDeployment(deploymentId); Delete directly
    • You must use repositoryservice deleteDeployment(deploymentId´╝îtrue); Method can be cascaded to delete the starting process
//1. Get processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

//2. Get the repositoryService
RepositoryService repositoryService = processEngine.getRepositoryService();

//3. Use repositoryService to obtain and delete development information
String deploymentId = "1";//For example, we want to delete the process deployment information with deployment id 1
//        repositoryService.deleteDeployment(deploymentId);

7. Obtain the process deployment resource file

  • Download Database act_ ge_ Binary deployment files in bytearray
    • Method 1:
      • Use the api (repository service) provided by activiti to download the resource file and save it to the file directory
    • Method 2:
      • Write your own code, download files from the database, use jdbc to read out blob type and blob type data, and save them to the file directory
    • Solve IO operation: commons io jar
//1. Get processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

//2. Get the repository service
RepositoryService repositoryService = processEngine.getRepositoryService();

//3. Get the process definition query object ProcessDefinitionQuery and query the process definition information
String processDefinitionKey = "myBusinessTrip";
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()

//4. Obtain the deployment ID through the process definition information
String deploymentId = processDefinition.getDeploymentId();

//5. Pass the deployment id parameter through the repository service and read the resource information (bpmn, png)
//5.1 use ProcessDefinitionQuery to query the names of corresponding bpmn files and png files
String pngName = processDefinition.getDiagramResourceName();
String bpmnName = processDefinition.getResourceName();
//5.2 get the input stream of png and bpmn files
InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, pngName);
InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, bpmnName);

//6. Construct outputStream
File pngFile = new File("D:\\study\\Activiti7place\\businessTrip.png");
File bpmnFile = new File("D:\\study\\Activiti7place\\businessTrip.bpmn");
FileOutputStream pngOutput = null;
FileOutputStream bpmnOutput = null;
try {
    pngOutput = new FileOutputStream(pngFile);
    bpmnOutput = new FileOutputStream(bpmnFile);
    //7. Use inputStream and output stream for conversion
    //8. Close flow
} catch (IOException e) {

8. Query historical messages

Main query database act_ hi_ Records in actinst

//1. Get processEngine
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

//2. Get historyService
HistoryService historyService = processEngine.getHistoryService();

//3. Get HistoricActivityInstanceQuery historical activity instance query
HistoricActivityInstanceQuery processInstanceQuery = historyService.createHistoricActivityInstanceQuery();

//4. Use the method of historical processinstancequery to query the database act_ hi_ The data in act Inst can be queried according to processDefinitionId/processInstanceId
List<HistoricActivityInstance> list = processInstanceQuery
//                .processDefinitionId("myBusinessTrip:1:5004")

//5. Traverse to get content
for (HistoricActivityInstance historicActivityInstance : list) {
    System.out.println("activity id="+historicActivityInstance.getActivityId());
    System.out.println("Name of the activity="+historicActivityInstance.getActivityName());
    System.out.println("Task leader="+historicActivityInstance.getAssignee());
    System.out.println("Process definition id="+historicActivityInstance.getProcessDefinitionId());
    System.out.println("Process instance ID="+historicActivityInstance.getProcessInstanceId());


Here, I understand the basic use of workflow Activiti7. Next, Activiti7 needs to be integrated with the work business.

Keywords: Java Back-end

Added by cunoodle2 on Wed, 09 Mar 2022 16:26:24 +0200