Workflow Overview

In a company, the beginning and end of each business can be understood as a workflow. For example, the basic process of expense reimbursement is as follows:

Workflow as shown in the figure: The employee first submits the application for expense reimbursement and submits the application to the department leader, who then submits the application to the financial department for approval. After the approval is completed, the employee who submits the application can be reimbursed, that is, the reimbursement process ends. The whole process is completed step by step in the normal way of working, which is a simple and complete workflow. Workflow can be understood as the whole process of initiating the process from the start node, then passing through multiple nodes, completing the action, and finally reaching the end node

Workflow system

If a software system has workflow system, we call it workflow system. The function of workflow in a system is to automate the management of system business processes. The core of a software system is fundamentally business process, workflow is just to assist the management of business process, even if there is no workflow business can be carried out as usual, but using workflow can better manage business process, improve the scalability of the system

The specific applications of workflow are:

  1. Key business: order, quotation processing, contract review, supply chain management, etc
  2. Administration: business trip application, leave application, daily and weekly reports, etc
  3. Personnel management: staff training arrangement, change handling, etc
  4. Financial related: receipt and payment processing, reimbursement processing, budget application, etc
  5. Customer service: customer information management, customer complaints, request processing, after-sales service and so on


Workflow engine

Prior to workflow engines, it was common practice to use the value of a status field to track changes in the process for process control. For example, a field is set with an initial value of 0, which becomes 1 and 2 after some processes. Finally, the state is judged according to this value and corresponding processing is given

Obviously, the flow of work is highly coupled to the business, and when our flow changes, the code we write must adapt. Our business systems would be much more adaptable if we had a tool that could help us manage our workflows so that when business processes change, applications don’t have to change

Activit7 is a workflow engine that extracts complex business processes from business systems and defines them using a specialized modeling language, BPMN2.0. Business processes are executed according to predefined processes. The process of the system is managed by Activit, so as to reduce the workload of the business system caused by process changes and improve the robustness of the system

Official website: www.activiti.org/

BPM

BPM (Business Process Management) is a standardized way to construct end-to-end Business processes to continuously improve the Business efficiency of an organization

BPM software is an IT tool that promotes the reorganization and adjustment of business methods and solutions among people, between people and systems and between systems according to the changes of business environment in enterprises. Using BPM software to model, automate, manage, monitor and optimize the entire life cycle of internal and external business processes can reduce enterprise costs and increase profits

The Business Process Model AndNotation (BPMN) is a set of standard Business Process modeling notation. You can create a Business Process using the BPMN notation. Activit uses BPMN for process modeling and process execution management

BPMN2.0, short for Business Process modeling notation 2.0, was created and developed by the Business Process Management Initiative, a non-profit association. BPMN2.0 is a set of symbolic specifications that use notations to clarify business process design flowcharts to improve communication efficiency during business modeling. Currently BPMN2.0 is the latest version and is used for layout and visual communication in a BPM context

The basic symbols of BPMN2.0 mainly include:

  • Events in the Event

  • Activities in the Activity

    Activity is a generic term for a job or task. An activity can be a task or a subprocess of the current process; Second, you can specify different types of activities. Common activities are as follows:

  • The GateWay of GateWay

    Gateways are used to process decisions. There are several common gateways to know:

    • Exclusive gateway

      Only one path will be selected. When the flow reaches the gateway, the flow is calculated one by one according to the sequence of output streams. When the calculation result of the condition is true, the flow of the current gateway is continued to be executed. If multiple lines are evaluated to true, the first line with the value true is executed. The engine throws an exception if none of the gateways evaluates to true. The exclusive gateway needs to be used in conjunction with conditional order flow. The default attribute specifies the default order flow that will be executed when all conditions are not met

    • A parallel gateway

      All paths will be selected simultaneously

      • Split: Execute all output sequential streams in parallel, creating a parallel execution line for each sequential stream

      • Merge: All lines split and executed from the parallel gateway wait here until all lines are executed

    • Inclusive gateway

      Multiple lines can be executed simultaneously or conditions can be set on the gateway

      • Split: Evaluates the expression on each line, and when the expression evaluates to true, creates a parallel line and continues execution
      • Merge: All lines split and executed from the parallel gateway wait here until all lines are executed
    • The event gateway

      Specifically set for intermediate capture events, allowing multiple output streams to be set to point to multiple different intermediate capture events. When the process executes to the event gateway, the process is in a wait state and needs to wait for events to be thrown to change the wait state to an active state

  • Flow to the Flow

    A flow is a wire connecting two process nodes. Common flows include the following:

Activit deployment process

Activiti is a workflow engine that enables business systems to easily integrate workflow environments with business systems environments by accessing the interface provided by Activiti to manipulate process-related data

Start by using the Activiti process Modeling tool (Activiti process Designer) to define the business process through the BPMN2.0 notation, generating a.bPMn file. The.bPMn file is the business process definition file, which defines the business process through XML

Once you have the.bPMn file, use the Api provided by Activiti to store the process definition content. A ProcessInstance is then started, indicating the start of a business process

Now that the system’s business processes are managed by Activiti, you can use Activiti to see where the current process is and what tasks the current user needs to do. Activiti manages these operations for us without requiring developers to write their own SQL statement queries

After the user finds a to-do task, the user can start processing a task. If the task is completed and other users need to continue to handle it, for example, the purchase order is created and submitted to the department manager for review, then Activiti also completes this process for us. In short, the process can continue until there is no next task node, and the process instance is completed

Use Activit

1. Install the database

Note that Activiti must run with database support, including H2, mysql, Oracle, Postgres, MSSQL, and DB2

2. Activit process definition tool plug-in installation

I don’t need to tell you more about how to Install the plugin. Search for the actiBPM plugin, which is the IDEA version of Activit Designer, and click Install to Install it. The Activiti BPMN Visualizer plugin is not supported any more than IDEA 2020.3

3. Create a Maven project and add dependencies

First you need the dependencies required by ProcessEngine in the Java project, including:

  1. Activiti related packages
  2. Other toolkits, such as Mybatis, ALf4J, Log4j, etc
  3. The Spring package that Activiti relies on
  4. Mysql database driver
  5. Third-party data connection pool DBCP
  6. Unit test Junit
<properties>
    <slf4j.version>1.6.6</slf4j.version>
    <log4j.version>1.2.12</log4j.version>
    <activiti.version>7.0.0. Walk</activiti.version>
</properties>
<dependencies>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-engine</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-spring</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <! -- BPMN model processing -->
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-bpmn-model</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <! -- BPMN -->
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-bpmn-converter</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <! -- BPMN json data conversion -->
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-json-converter</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <! -- BPMN layout -->
    <dependency>
        <groupId>org.activiti</groupId>
        <artifactId>activiti-bpmn-layout</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <! -- Activiti Cloud support -->
    <dependency>
        <groupId>org.activiti.cloud</groupId>
        <artifactId>activiti-cloud-services-api</artifactId>
        <version>${activiti.version}</version>
    </dependency>
    <! -- Mysql driver -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.17</version>
    </dependency>
    <! -- mybatis -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.4.5</version>
    </dependency>
    <! -- Link pool -->
    <dependency>
        <groupId>commons-dbcp</groupId>
        <artifactId>commons-dbcp</artifactId>
        <version>1.4</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    <! -- log start -->
    <dependency>
        <groupId>log4j</groupId>
        <artifactId>log4j</artifactId>
        <version>${log4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-log4j12</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
</dependencies>
Copy the code

4. Configure log4J logs

Since log4j is used, configure the log as well, creating log4j.properties in the resource directory

# 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.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE
# CONSOLE is set to be a ConsoleAppender using a PatternLayout.
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.layout=org.apache.log4j.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=org.apache.log4j.FileAppender
log4j.appender.LOGFILE.File=f:\act\activiti.log
log4j.appender.LOGFILE.Append=true
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r[%15.15t] %-5p % 30.30C %x - %m\n
Copy the code

5. Write the Activit configuration file

We use the default method provided by Activit to create mysql tables. The default method requires the activit.cfg. XML file to be created in the Resources directory. The path and file name cannot be changed. The default way of activiti. CFG. XML bean name to call processEngineConfiguration inside, can’t modify


      
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/contex http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <! - the default id corresponds to the value of processEngineConfiguration - >
    <! -- processEngine Activiti processEngine -->
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <! -- Configure database information -->
        <property name="jdbcDriver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/activit? useSSL=false&amp;serverTimezone=UTC&amp;allowPublicKeyRetrieval=true&amp;useAffectedRows=true"/>
        <property name="jdbcUsername" value="root"/>
        <property name="jdbcPassword" value="123"/>
        <! -- Activiti database table processing policy, true if the corresponding table exists in the database, then directly use, otherwise create -->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>
</beans>
Copy the code

You can also use connection pooling to improve performance


      
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/contex http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">

    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/activit? useSSL=false&amp;serverTimezone=UTC&amp;allowPublicKeyRetrieval=true&amp;useAffectedRows=true"/>
        <property name="username" value="root"/>
        <property name="password" value="123"/>
        <property name="maxActive" value="3"/>
        <property name="maxIdle" value="1"/>
    </bean>

    <! - the default id corresponds to the value of processEngineConfiguration - >
    <! -- processEngine Activiti processEngine -->
    <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
        <! Import the link pool configured above -->
        <property name="dataSource" ref="dataSource"/>
        <! -- Activiti database table processing policy, true if the corresponding table exists in the database, then directly use, otherwise create -->
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>
</beans>
Copy the code

6. Write Java classes to generate tables

Create a test class that calls Activiti’s utility classes to generate the database tables acitivti needs. Using ProcessEngines directly from activiti will, by default, read the activiti.cfg. XML file in your CLASspath, read the database configuration, and create ProcessEngine. The tables are created automatically when ProcessEngine is created.

public class testCreate {

    @Test
    public void testCreateTable(a) {
        // Read the activiti.cfg. XML configuration file and create the table along with ProcessEngineProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine(); System.out.println(processEngine); }}Copy the code

By default, the activiti.cfg. XML configuration file in the resource directory is read. You can also customize the configuration file and specify a path to read it

/ / build ProcessEngineConfiguration first
ProcessEngineConfiguration configuration = ProcessEngineConfiguration.createProcessEngineConfigurationFromResource("activiti.cfg.xml");
/ / create ProcessEngine through ProcessEngineConfiguration, will create the database
ProcessEngine processEngine = configuration.buildProcessEngine();
Copy the code

During the execution of the test program, the IDEA console outputs a log indicating that the program is creating a data table. After executing, we look at the database and create 25 tables. The result is as follows:

At this point, we have created the database and tables needed to run Activiti

Activiti table structure

Activiti is supported by these 25 tables, which record information about the participants and groups of users in the process, as well as the definition of the process, information about the execution of the process, and the history of the process

1. Table naming rules and functions

Looking at the created tables, we see that Activiti’s tables all start with act_, followed by a two-letter identifier indicating the purpose of the table, which also corresponds to the apis provided by Activiti:

  • ACT_RE: RE stands for repository, a prefixed table containing process definitions and process static resources (images, rules, and so on)
  • ACT_RU: RU stands for runtime. When these tables are running, they contain the data of process instances, tasks, variables, asynchronous tasks, and other processes in progress. Activiti saves this data only during the process instance execution and deletes the records at the end of the process. This keeps the watch small and fast
  • ACT_HI: HI stands for history, and these tables contain historical data such as historical process instances, variables, tasks, and so on
  • ACT_GE: GE indicates general data

2. Activiti data table introduction

Classification table The name of the table explain
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 illustrative information
[ACT_HI_DETAIL] Details of the process execution in history
[ACT_HI_IDENTITYLINK] History of user relationships during process runs
[ACT_HI_PROCINST] Historical process instances
[ACT_HI_TASKINST] Historical task instances
[ACT_HI_VARINST] Historical information about variables in a process run
Process definition table
[ACT_RE_DEPLOYMENT] Deployment Unit Information
[ACT_RE_MODEL] Model information
[ACT_RE_PROCDEF] Deployed process definitions
Run instance table
[ACT_RU_EVENT_SUBSCR] Run time event
[ACT_RU_EXECUTION] Runtime process execution instance
[ACT_RU_IDENTITYLINK] Runtime user relationship information, which stores information about task nodes and participants
[ACT_RU_JOB] Run time job
[ACT_RU_TASK] Runtime task
[ACT_RU_VARIABLE] Runtime variable

Activiti Architecture

Once the Activiti database tables are generated, you can call Activiti’s utility classes in Your Java code. Let’s look at the Activiti class relationships

1. Class diagram

IdentityService (FormService) and FormService (FormService) have both been removed from the IdentityService and FormService versions

2. Service Indicates the Service interface

A Service is a Service interface provided by a workflow engine for workflow deployment, execution, and management. We use these interfaces to operate the corresponding tables of the Service

RuntimeService runtimeService = processEngine.getRuntimeService();
RepositoryService repositoryService = processEngine.getRepositoryService();
TaskService taskService = processEngine.getTaskService();
Copy the code

A brief introduction to each Service implementation class:

  • RepositoryService

    Activiti’s resource management class, which is responsible for deploying process definitions and managing process resources. With Activiti, you start by deploying the process RepositoryService to the business process diagrams designed using the modeling tool

  • RuntimeService

    Activiti’s Process Run Management class is used to start a new process instance and get information about process execution. A process definition is used to determine the structure and inter-node behavior of a process, and a process instance is an execution of the corresponding process definition, which can be understood as the relationship between classes and objects in Java

  • TaskService

    Activiti’s task management class handles various tasks in business operations, such as querying tasks assigned to users or groups, creating new tasks, assigning tasks, and determining and completing a task

  • HistoryService

    Activiti history management class, you can query history information. When a process is executed, the engine stores a lot of data, such as when the process instance was started, the participants of the task, when the task was completed, the execution path of each process instance, and so on. The service obtains this data mainly through the query function

  • ManagementService

    Activiti’s Engine Management class provides management and maintenance capabilities for the Activiti process engine, which are not used in workflow-driven applications and are primarily used for routine maintenance of the Activiti system