A BPMN process example takes you to the life cycle of the process in the project

Posted by jay7981 on Thu, 20 Jan 2022 13:47:14 +0100

Absrtact: This paper describes in detail the BPMN process in the workflow Activiti framework to define the whole running life cycle.

This article is shared from Huawei cloud community< This article describes in detail the BPMN process in the workflow Activiti framework to define the entire running life cycle >, by Chova the siege lion.

BPMN 2.0 introduction

  • Business process modeling notation (BPMN) is a standard graphical annotation of business process model This standard is maintained by the object management group (OMG)
  • Version 2.0 of BPMN specification allows to add precise technical details in BPMN graphics and elements, and formulate the execution syntax of BPMN elements By using XML language to specify the executable syntax of business process, BPMN specification has evolved into the language of business process, which can be executed in any BPMN2 compatible process engine, and powerful graphical annotations can still be used
  • In short, BPMN is a combination of icons and labels

Define a process

  • Create a new XML file and name it. Make sure the file suffix is bpmn20.xml or BPMN, otherwise the engine cannot publish
  • The root node of BPMN 2.0 is the definitions node Multiple process definitions can be defined in this element (however, it is recommended that each file contain only one process definition, which can simplify the maintenance difficulty in the development process)
  • An empty process definition is as follows: note that the definitions element should at least contain the declarations of xmlns and targetNamespace
    • targetNamespace can be any value and is used to classify process instances
<definitions
  xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  xmlns:activiti="http://activiti.org/bpmn"
  targetNamespace="Examples">

  <process id="myProcess" name="My First Process">
    ..
  </process>

</definitions>
  • You can choose to add BPMN 2.0 format location on the line:
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.omg.org/spec/BPMN/20100524/MODEL
                    http://www.omg.org/spec/BPMN/2.0/20100501/BPMN20.xsd
  • ==The process element has two attributes:==
  • id: this attribute is required and corresponds to the key attribute of the Activiti ProcessDefinition object id can be used to start the process instance of the process definition through the startProcessInstanceByKey method of RuntimeService
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myProcess");

==Note: = = it is different from the startProcessInstanceById method: this method expects to use the id automatically generated by the Activiti engine when publishing. You can call ProcessDefinition The getid () method obtains this value. The format of the generated id is {key:version, and the maximum length is limited to 64 characters. If an activitieexception is thrown during startup, it indicates that the generated id is too long, and the length of the process key needs to be limited

  • Name: this attribute is optional and corresponds to the name attribute of ProcessDefinition This attribute is not used by the engine itself. It is used to display easy to read names in the user interface

BPMN process example prerequisites

  • Activiti is already installed and can run the Activiti Demo
  • H2 server running independently is used
  • Modify dB Properties to set JDBC url=jdbc:h2: tcp://localhost/activiti , and then start the stand-alone server

target

  • Learn Activiti and some basic BPMN 2.0 concepts
  • The end result is a simple Java SE program that can publish process definitions and operate processes through the Activiti engine API
  • Use some Activiti related tools to build your own business process web application

Use case

  • Every month, the company's leaders should be given a financial statement, which is in the charge of the accounting department
  • When the report is completed, a superior leader needs to approve the document before sending it to all leaders

flow chart

  • Graphical BPMN 2.0 tags for processes:

Empty start event (circle on the left), followed by two user tasks: making monthly financial report and verifying monthly financial report, and finally empty end event (thick circle on the right)

XML content

  • It is easy to find the main elements of the process in the XML of the business process:
    • (empty) the start event is the entry of the process
    • User task is the task statement related to the operator in the process:
      • The first task is assigned to the accounting group
      • The second task is assigned to the management group
    • When the process reaches null end, the event will end
    • These elements are connected by wires. These wires have source and target attributes, which define the direction of the wires
<definitions id="definitions"
  targetNamespace="http://activiti.org/bpmn20"
  xmlns:activiti="http://activiti.org/bpmn"
  xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL">

        <process id="financialReport" name="Monthly financial report reminder process">

          <startEvent id="theStart" />

          <sequenceFlow id='flow1' sourceRef='theStart' targetRef='writeReportTask' />

          <userTask id="writeReportTask" name="Write monthly financial report" >
            <documentation>
              Write monthly financial report for publication to shareholders.
            </documentation>
            <potentialOwner>
              <resourceAssignmentExpression>
                <formalExpression>accountancy</formalExpression>
              </resourceAssignmentExpression>
            </potentialOwner>
          </userTask>

          <sequenceFlow id='flow2' sourceRef='writeReportTask' targetRef='verifyReportTask' />

          <userTask id="verifyReportTask" name="Verify monthly financial report" >
            <documentation>
              Verify monthly financial report composed by the accountancy department.
              This financial report is going to be sent to all the company shareholders.
            </documentation>
            <potentialOwner>
              <resourceAssignmentExpression>
                <formalExpression>management</formalExpression>
              </resourceAssignmentExpression>
            </potentialOwner>
          </userTask>

          <sequenceFlow id='flow3' sourceRef='verifyReportTask' targetRef='theEnd' />

          <endEvent id="theEnd" />

        </process>

</definitions>

Start a process instance

  • After creating the process definition of the business process, you can create a process instance
  • A process instance corresponds to the creation and approval of a specific monthly financial report. All process instances share the same process definition
  • To create a process instance using a process definition, first publish the business process:
    • The process definition is saved in the persistent data store, which is specially configured for the Activiti engine Therefore, after the business process is deployed, the process definition can be found after the engine is restarted
    • The BPMN 2.0 process file will be parsed into a memory object model, which can be operated through the Activiti API
  • Through the following API publishing process, all interactions with the Activiti engine are through services
Deployment deployment = repositoryService.createDeployment()
  .addClasspathResource("FinancialReportProcess.bpmn20.xml")
  .deploy();
  • Start a new process instance and use the ID defined in the process definition (corresponding to the process element in the XML file)== Note that for Activiti, the ID here should be called Key = =. Generally, the ID used in the process model is Key in Activiti: such as task ID
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("financialReport");
  • This creates a process instance:
    • Enter the start event first
    • After starting the event, it will execute along all outgoing lines and reach the first task ("making monthly financial report")
    • Activiti saves a task to the database At this time, the users or groups assigned to this task will be resolved and saved to the database
    • It should be noted that the Activiti engine will continue to execute the process unless it encounters a waiting state: such as user task
    • In the wait state, the status of the current process instance will be saved to the database This state cannot be changed until the user decides to complete the task
    • At this time, the engine will continue to execute until the next waiting state is encountered or the process ends
    • If the intermediate engine restarts or crashes, the process state will also be safely saved in the database
  • After the task is created, startProcessInstanceByKey will not return until it reaches the waiting state of the user task At this time, the task is assigned to a group, which means that the group is a candidate group to perform the task
  • Now put everything together to create a simple java program:
    • Create a Java project and put the Activiti jar and dependencies under the classpath: these can be found in the libs directory of the Activiti distribution package
    • Before calling the Activiti service, we must construct a ProcessEngine that allows us to access the service
    • Here we use the [run alone] configuration, which uses the database at the time of demo installation to build the process engine
public static void main(String[] args) {

  // Create Activiti process engine
  ProcessEngine processEngine = ProcessEngineConfiguration
    .createStandaloneProcessEngineConfiguration()
    .buildProcessEngine();

  // Get Activiti services
  RepositoryService repositoryService = processEngine.getRepositoryService();
  RuntimeService runtimeService = processEngine.getRuntimeService();

  // Deploy the process definition
  repositoryService.createDeployment()
    .addClasspathResource("FinancialReportProcess.bpmn20.xml")
    .deploy();

  // Start a process instance
  runtimeService.startProcessInstanceByKey("financialReport");
}

task list

  • You can obtain tasks through TaskService. Add the following logic:
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit").list();
  • Note that the incoming user must be a member of the accounting group, corresponding to the process definition:
<potentialOwner>
  <resourceAssignmentExpression>
    <formalExpression>accountancy</formalExpression>
  </resourceAssignmentExpression>
</potentialOwner>
  • You can also use the group name to obtain relevant results through the task query API Add the following logic to the code:
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();
  • Because the configured ProcessEngine uses the same data as the demo, you can log in to the Activiti Explorer By default, there is no one in the accounting group:
    • Sign in
    • Click Group
    • Create a new group
    • Click user
    • Assign groups to fozzie
    • Log in using fozzie/fozzie
  • You can start our business process. Select the Processes page and click Start Process in the [operation] column of [monthly financial report]

  • The process proceeds to the first user task Because we log in with kermit, we can see a new pending task after starting the process instance Select the task page to view this new task Note that even if the process is started by others, the task will still be seen as a candidate task by everyone in the accounting group

Receive task

  • Now an accountant wants to claim this task
  • After claiming, the user will become the executor of the task, and the task will disappear from the task list of other members of the accounting group Code of claim task:
taskService.claim(task.getId(), "fozzie");
  • The task will enter the personal task list of the person claiming the task:
List<Task> tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();
  • Click the claim button in the Activiti Explorer UI to perform the same operation The task is moved to the login user's personal task list You will also see that the executor of the task has become the currently logged in user:

Complete the task

  • Now the accountant can start the work of financial reporting
  • After the report is completed, he can complete the task, which means that all the work required by the task is completed
taskService.complete(task.getId());
  • For Activiti engine:
    • An external information is required to allow the process instance to continue execution
    • The task removes itself from the runtime
    • The process will be executed along a single outgoing line and moved to the second task (approval report)
    • The same mechanism as the first task will be used for the second task, except that the task is assigned to the management group
  • In the demo:
    • Complete the task by clicking the finish button in the task list
    • Because Fozzie is not an accountant, let's log out of Activiti Explorer first
    • Then log in (Manager) with kermit, and the second task will enter the unassigned task list

End process

  • The approval task is queried and collected as before
  • Completing the second task will make the process execute to the end event, which will end the process instance
  • The process instance and all related running data are deleted from the database
  • You can log in to Activiti Explorer to verify. You can see that there is no data in the table where the process running data is saved:

  • You can use historyService to determine whether the process has ended:
HistoryService historyService = processEngine.getHistoryService();
HistoricProcessInstance historicProcessInstance =
historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());

Source code

  • Considering that you may start some process instances in the Activiti Explorer UI, it will get multiple tasks instead of one, so the code can run normally all the time:
public class TenMinuteTutorial {

  public static void main(String[] args) {

    // Create Activiti process engine
    ProcessEngine processEngine = ProcessEngineConfiguration
      .createStandaloneProcessEngineConfiguration()
      .buildProcessEngine();

    // Get Activiti services
    RepositoryService repositoryService = processEngine.getRepositoryService();
    RuntimeService runtimeService = processEngine.getRuntimeService();

    // Deploy the process definition
    repositoryService.createDeployment()
      .addClasspathResource("FinancialReportProcess.bpmn20.xml")
      .deploy();

    // Start a process instance
    String procId = runtimeService.startProcessInstanceByKey("financialReport").getId();

    // Get the first task
    TaskService taskService = processEngine.getTaskService();
    List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("accountancy").list();
    for (Task task : tasks) {
      System.out.println("Following task is available for accountancy group: " + task.getName());

      // claim it
      taskService.claim(task.getId(), "fozzie");
    }

    // Verify Fozzie can now retrieve the task
    tasks = taskService.createTaskQuery().taskAssignee("fozzie").list();
    for (Task task : tasks) {
      System.out.println("Task for fozzie: " + task.getName());

      // Complete the task
      taskService.complete(task.getId());
    }

    System.out.println("Number of tasks for fozzie: "
            + taskService.createTaskQuery().taskAssignee("fozzie").count());

    // Retrieve and claim the second task
    tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
    for (Task task : tasks) {
      System.out.println("Following task is available for accountancy group: " + task.getName());
      taskService.claim(task.getId(), "kermit");
    }

    // Completing the second task ends the process
    for (Task task : tasks) {
      taskService.complete(task.getId());
    }

    // verify that the process is actually finished
    HistoryService historyService = processEngine.getHistoryService();
    HistoricProcessInstance historicProcessInstance =
      historyService.createHistoricProcessInstanceQuery().processInstanceId(procId).singleResult();
    System.out.println("Process instance end time: " + historicProcessInstance.getEndTime());
  }

}

summary

  • Through the BPMN 2.0 structure in Activiti, the following aspects of business processes can be:
    • Define the gateway to realize the decision-making process: the manager can reject the financial report and re create a task for the accountant
    • Consider using variables: you can save or reference the report and display it in the form
    • Add service task at the end of the process: send the report to each leader

 

Click focus to learn about Huawei cloud's new technologies for the first time~

Topics: Activiti