Create a process

  • To the Activiti engine operation, need to through the org. Activiti. Engine. The ProcessEngine instance exposed service. You can operate a org. Activiti. Engine. ProcessEngine
  • Create a work business process for requesting leave:

Release process

  • Any data related to a “static” resource, such as a process definition, can be accessed through RepositoryService, which conceptually makes all static data Activiti’s resource content
  • In the SRC/test/resources/org/activiti/test directory. To create a new XML file VacationRequest bpmn20. XML:

      
<definitions id="definitions"
             targetNamespace="http://activiti.org/bpmn20"
             xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xmlns:activiti="http://activiti.org/bpmn">

  <process id="vacationRequest" name="Vacation request">

    <startEvent id="request" activiti:initiator="employeeName">
      <extensionElements>
        <activiti:formProperty id="numberOfDays" name="Number of days" type="long" value="1" required="true"/>
        <activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
        <activiti:formProperty id="vacationMotivation" name="Motivation" type="string" />
      </extensionElements>
    </startEvent>
    <sequenceFlow id="flow1" sourceRef="request" targetRef="handleRequest" />

    <userTask id="handleRequest" name="Handle vacation request" >
      <documentation>
        ${employeeName} would like to take ${numberOfDays} day(s) of vacation (Motivation: ${vacationMotivation}).
      </documentation>
      <extensionElements>
         <activiti:formProperty id="vacationApproved" name="Do you approve this vacation" type="enum" required="true">
          <activiti:value id="true" name="Approve" />
          <activiti:value id="false" name="Reject" />
        </activiti:formProperty>
        <activiti:formProperty id="managerMotivation" name="Motivation" type="string" />
      </extensionElements>
      <potentialOwner>
        <resourceAssignmentExpression>
          <formalExpression>management</formalExpression>
        </resourceAssignmentExpression>
      </potentialOwner>
    </userTask>
    <sequenceFlow id="flow2" sourceRef="handleRequest" targetRef="requestApprovedDecision" />

    <exclusiveGateway id="requestApprovedDecision" name="Request approved?" />
    <sequenceFlow id="flow3" sourceRef="requestApprovedDecision" targetRef="sendApprovalMail">
      <conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'true'}</conditionExpression>
    </sequenceFlow>

    <task id="sendApprovalMail" name="Send confirmation e-mail" />
    <sequenceFlow id="flow4" sourceRef="sendApprovalMail" targetRef="theEnd1" />
    <endEvent id="theEnd1" />

    <sequenceFlow id="flow5" sourceRef="requestApprovedDecision" targetRef="adjustVacationRequestTask">
      <conditionExpression xsi:type="tFormalExpression">${vacationApproved == 'false'}</conditionExpression>
    </sequenceFlow>

    <userTask id="adjustVacationRequestTask" name="Adjust vacation request">
      <documentation>
        Your manager has disapproved your vacation request for ${numberOfDays} days.
        Reason: ${managerMotivation}
      </documentation>
      <extensionElements>
        <activiti:formProperty id="numberOfDays" name="Number of days" value="${numberOfDays}" type="long" required="true"/>
        <activiti:formProperty id="startDate" name="First day of holiday (dd-MM-yyy)" value="${startDate}" datePattern="dd-MM-yyyy hh:mm" type="date" required="true" />
        <activiti:formProperty id="vacationMotivation" name="Motivation" value="${vacationMotivation}" type="string" />
        <activiti:formProperty id="resendRequest" name="Resend vacation request to manager?" type="enum" required="true">
          <activiti:value id="true" name="Yes" />
          <activiti:value id="false" name="No" />
        </activiti:formProperty>
      </extensionElements>
      <humanPerformer>
        <resourceAssignmentExpression>
          <formalExpression>${employeeName}</formalExpression>
        </resourceAssignmentExpression>
      </humanPerformer>
    </userTask>
    <sequenceFlow id="flow6" sourceRef="adjustVacationRequestTask" targetRef="resendRequestDecision" />

    <exclusiveGateway id="resendRequestDecision" name="Resend request?" />
    <sequenceFlow id="flow7" sourceRef="resendRequestDecision" targetRef="handleRequest">
      <conditionExpression xsi:type="tFormalExpression">${resendRequest == 'true'}</conditionExpression>
    </sequenceFlow>

     <sequenceFlow id="flow8" sourceRef="resendRequestDecision" targetRef="theEnd2">
      <conditionExpression xsi:type="tFormalExpression">${resendRequest == 'false'}</conditionExpression>
    </sequenceFlow>
    <endEvent id="theEnd2" />

  </process>

</definitions>
Copy the code
  • In order for the Activiti engine to know about the process, we must first [publish], which means that the engine parses the BPMN 2.0 XML into something that can be executed, and all the process definitions in the release package are added to the database. This way, when the engine restarts, it can still get the [published] flow:
ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
RepositoryService repositoryService = processEngine.getRepositoryService();
repositoryService.createDeployment()
  .addClasspathResource("org/activiti/test/VacationRequest.bpmn20.xml")
  .deploy();

Log.info("Number of process definitions: " + repositoryService.createProcessDefinitionQuery().count());
Copy the code

Start a process instance

  • Once the process definition is published to the Activiti engine, new process instances can be initiated based on it.
  • For each process definition, there can be many process instances. A process definition is a “blueprint” and a process instance is a running execution of it
  • Everything related to the running state of the process can pass throughRuntimeServiceThere are many ways to start a new process instance.
    • You can add some process variables when the process instance starts because they are required for the expression of the first user task. Process variables are often used because they give special meaning to different process instances from the same process definition
    • Process variables are key to distinguishing process instances
    • Start the process instance using the key defined in the process definition XML:
Map<String, Object> variables = new HashMap<String, Object>();
variables.put("employeeName"."Kermit");
variables.put("numberOfDays".new Integer(4));
variables.put("vacationMotivation"."I'm really tired!");

RuntimeService runtimeService = processEngine.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("vacationRequest", variables);

// Verify that we started a new process instance
Log.info("Number of process instances: " + runtimeService.createProcessInstanceQuery().count());
Copy the code

To complete the task

  • Once the process starts, the first step is the user task. This is a step that must be handled by system users.
  • The user has a “task list” that shows all the tasks that must be handled by the entire user. Here is the corresponding query:
// Fetch all tasks for the management group
TaskService taskService = processEngine.getTaskService();
List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("management").list();
for (Task task : tasks) {
  Log.info("Task available: " + task.getName());
}
Copy the code
  • In order for the process instance to continue running, we ** need to complete the entire task.** For Activiti, we need to complete the task:
Task task = tasks.get(0);

Map<String, Object> taskVariables = new HashMap<String, Object>();
taskVariables.put("vacationApproved"."false");
taskVariables.put("managerMotivation"."We have a tight deadline!");
taskService.complete(task.getId(), taskVariables);
Copy the code
  • The process instance then moves on to the next step
  • The next step allows the employee to adjust the original leave request through the form. Employees can resubmit leave requests, which redirects the process to the first task

Suspends or activates a process

  • A process definition can be suspended, and when the process definition is suspended, a new process cannot be created and an exception is thrown. A process can be suspended using RepositoryService:
repositoryService.suspendProcessDefinitionByKey("vacationRequest");
try {
  runtimeService.startProcessInstanceByKey("vacationRequest");
} catch (ActivitiException e) {
  e.printStackTrace();
}
Copy the code
  • To reactivate a process definition, you can call repositoryService. ActivateProcessDefinitionXXX method
  • You can also suspend a process instance:
    • When suspended, the process cannot continue: for example, an exception is thrown when a task is completed, and asynchronous operations (such as timers) do not execute. Suspend the process instance can call runtimeService. SuspendProcessInstance method
    • Activation process instances can be called runtimeService activateProcessInstanceXXX method