Deployment process definition
We are now ready to add additional BPM logic to the Activiti engine.
To do this, as the name of our OnboardingRequest Java class shows, we will use a simple induction process. In this example, we will enter the data, and then, if the number of years of experience exceeds 3, we will publish the task of personalizing the entry welcome message. In this task, the user will manually input the data into a pseudo-back-end system. If the work experience is 3 years or less, the data can be simply, generally and automatically integrated into a pseudo-back-end system.
Activiti's process engine is compatible with BPMN 2.0 standard. Visually, the above process can be modeled as follows:
This example is very simple, and according to the requirements, it can be modeled in several different ways. Although it can also coordinate simple processes, please note that Activiti can handle very complex processes, including dozens, hundreds or even thousands of steps.
The bottom layer of the above visual process model is the XML structure of BPMN. In this case, the XML document is onboarding.bpmn20.xml. This quick start will not go deep into the depth of the underlying XML BPMN structure, focusing on the mechanism developed for the Activiti API and embedding Activiti into your application. However, in order to support the following logic, here is a summary of the definition logic associated with BPMN shapes and encoding in underlying XML:
BPMN shape | Onboarding.bpmn20.xml line | Notes |
---|---|---|
4 | Beginning event | |
5-10 | User tasks collect two form attributes: "fullName" and "yearsOfExperience"; Note that the candidate group in line 9 is set to Administrator. |
|
14-18 | User task collects 1 form attribute: "personal WelcomeTime"; Note that the candidate group in line 22 is set to Administrator. |
|
21-24 | The script task indicates that the data is automatically input to the pseudo back end. Note that, although simple, there is a simple script to set a process variable autoWelcomeTime |
|
2526-2825,26 | Define the "years of experience" exclusive gateway; (Decides to produce one or another path.) Use the yearsOfExperience variable to represent the logic of "> 3": ${yearsOfExperience > 3} on the proprietary gateway, note the default section pointing to "automated IntroPath" to indicate the logical "else" of condition "> 3". |
|
19 | end event |
Download the onboarding.bpmn20.xml file, the entire XML structure below, and copy the onboarding.bpmn20.xml file to the path $mvnProject/src/main/resources/.
Document: $mvnProject/src/main/resources/onboarding.bpmn20.xml
<?xml version="1.0" encoding="UTF-8"?> <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef"> <process id="onboarding" name="Onboarding" isExecutable="true"> <startEvent id="startOnboarding" name="Start" activiti:initiator="initiator"></startEvent> <userTask id="enterOnboardingData" name="Enter Data" activiti:assignee="${initiator}" activiti:candidateGroups="managers"> <extensionElements> <activiti:formProperty id="fullName" name="Full Name" type="string"></activiti:formProperty> <activiti:formProperty id="yearsOfExperience" name="Years of Experience" type="long" required="true"></activiti:formProperty> </extensionElements> </userTask> <sequenceFlow id="sid-1337EA98-7364-4198-B5D9-30F5341D6918" sourceRef="startOnboarding" targetRef="enterOnboardingData"></sequenceFlow> <exclusiveGateway id="decision" name="Years of Experience" default="automatedIntroPath"></exclusiveGateway> <sequenceFlow id="sid-42BE5661-C3D5-4DE6-96F5-73D34822727A" sourceRef="enterOnboardingData" targetRef="decision"></sequenceFlow> <userTask id="personalizedIntro" name="Personalized Introduction and Data Entry" activiti:assignee="${initiator}" activiti:candidateGroups="managers"> <extensionElements> <activiti:formProperty id="personalWelcomeTime" name="Personal Welcome Time" type="date" datePattern="MM-dd-yyyy hh:mm"></activiti:formProperty> </extensionElements> </userTask> <endEvent id="endOnboarding" name="End"></endEvent> <sequenceFlow id="sid-37A73ACA-2E23-400B-96F3-71F77738DAFA" sourceRef="automatedIntro" targetRef="endOnboarding"></sequenceFlow> <scriptTask id="automatedIntro" name="Generic and Automated Data Entry" scriptFormat="javascript" activiti:autoStoreVariables="false"> <script><![CDATA[var dateAsString = new Date().toString(); execution.setVariable("autoWelcomeTime", dateAsString);]]></script> </scriptTask> <sequenceFlow id="automatedIntroPath" sourceRef="decision" targetRef="automatedIntro"></sequenceFlow> <sequenceFlow id="personalizedIntroPath" name=">3" sourceRef="decision" targetRef="personalizedIntro"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${yearsOfExperience > 3}]]></conditionExpression> </sequenceFlow> <sequenceFlow id="sid-BA6F061B-47B6-428B-8CE6-739244B14BD6" sourceRef="personalizedIntro" targetRef="endOnboarding"></sequenceFlow> </process> <bpmndi:BPMNDiagram id="BPMNDiagram_onboarding"> <bpmndi:BPMNPlane bpmnElement="onboarding" id="BPMNPlane_onboarding"> <bpmndi:BPMNShape bpmnElement="startOnboarding" id="BPMNShape_startOnboarding"> <omgdc:Bounds height="30.0" width="30.0" x="155.0" y="145.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="enterOnboardingData" id="BPMNShape_enterOnboardingData"> <omgdc:Bounds height="80.0" width="100.0" x="240.0" y="120.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="decision" id="BPMNShape_decision"> <omgdc:Bounds height="40.0" width="40.0" x="385.0" y="140.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="personalizedIntro" id="BPMNShape_personalizedIntro"> <omgdc:Bounds height="80.0" width="100.0" x="519.0" y="15.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="endOnboarding" id="BPMNShape_endOnboarding"> <omgdc:Bounds height="28.0" width="28.0" x="725.0" y="165.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNShape bpmnElement="automatedIntro" id="BPMNShape_automatedIntro"> <omgdc:Bounds height="80.0" width="100.0" x="520.0" y="255.0"></omgdc:Bounds> </bpmndi:BPMNShape> <bpmndi:BPMNEdge bpmnElement="sid-37A73ACA-2E23-400B-96F3-71F77738DAFA" id="BPMNEdge_sid-37A73ACA-2E23-400B-96F3-71F77738DAFA"> <omgdi:waypoint x="570.0" y="255.0"></omgdi:waypoint> <omgdi:waypoint x="570.0" y="179.0"></omgdi:waypoint> <omgdi:waypoint x="725.0" y="179.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-1337EA98-7364-4198-B5D9-30F5341D6918" id="BPMNEdge_sid-1337EA98-7364-4198-B5D9-30F5341D6918"> <omgdi:waypoint x="185.0" y="160.0"></omgdi:waypoint> <omgdi:waypoint x="240.0" y="160.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="automatedIntroPath" id="BPMNEdge_automatedIntroPath"> <omgdi:waypoint x="405.0" y="180.0"></omgdi:waypoint> <omgdi:waypoint x="405.0" y="295.0"></omgdi:waypoint> <omgdi:waypoint x="520.0" y="295.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="personalizedIntroPath" id="BPMNEdge_personalizedIntroPath"> <omgdi:waypoint x="405.0" y="140.0"></omgdi:waypoint> <omgdi:waypoint x="405.0" y="55.0"></omgdi:waypoint> <omgdi:waypoint x="519.0" y="55.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-42BE5661-C3D5-4DE6-96F5-73D34822727A" id="BPMNEdge_sid-42BE5661-C3D5-4DE6-96F5-73D34822727A"> <omgdi:waypoint x="340.0" y="160.0"></omgdi:waypoint> <omgdi:waypoint x="385.0" y="160.0"></omgdi:waypoint> </bpmndi:BPMNEdge> <bpmndi:BPMNEdge bpmnElement="sid-BA6F061B-47B6-428B-8CE6-739244B14BD6" id="BPMNEdge_sid-BA6F061B-47B6-428B-8CE6-739244B14BD6"> <omgdi:waypoint x="619.0" y="55.0"></omgdi:waypoint> <omgdi:waypoint x="739.0" y="55.0"></omgdi:waypoint> <omgdi:waypoint x="739.0" y="165.0"></omgdi:waypoint> </bpmndi:BPMNEdge> </bpmndi:BPMNPlane> </bpmndi:BPMNDiagram> </definitions>
Add to OnboardingRequest.java as shown below:
Document: $mvnProject/src/main/java/com/example/OnboardingRequest.java
package com.example; import java.text.ParseException; import org.activiti.engine.ProcessEngine; import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.RepositoryService; import org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration; import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; public class OnboardingRequest { public static void main(String[] args) throws ParseException { ProcessEngineConfiguration cfg = new StandaloneProcessEngineConfiguration() .setJdbcUrl("jdbc:h2:mem:activiti;DB_CLOSE_DELAY=1000") .setJdbcUsername("sa") .setJdbcPassword("") .setJdbcDriver("org.h2.Driver") .setDatabaseSchemaUpdate(ProcessEngineConfiguration.DB_SCHEMA_UPDATE_TRUE); ProcessEngine processEngine = cfg.buildProcessEngine(); String pName = processEngine.getName(); String ver = ProcessEngine.VERSION; System.out.println("ProcessEngine [" + pName + "] Version: [" + ver + "]"); RepositoryService repositoryService = processEngine.getRepositoryService(); Deployment deployment = repositoryService.createDeployment() .addClasspathResource("onboarding.bpmn20.xml").deploy(); ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() .deploymentId(deployment.getId()).singleResult(); System.out.println( "Found process definition [" + processDefinition.getName() + "] with id [" + processDefinition.getId() + "]"); } }
Document: $mvnProject/src/main/java/com/example/OnboardingRequest.java
add rows | Explain |
---|---|
25-27 | Load the provided BPMN model and deploy it to the Activiti process engine. |
28-33 | Retrieve the deployed model and prove that it is in the Activiti repository. |
For more information about BPMN and its use in Activiti, see the sections in the Activiti User Guide.
Package the code by running "mvn package".
Run the Java program as before, and the sample output is shown below.
Command: java-jar target/ActivitiDeveloper QuickStart-0.0.1-SNAPSHOT-jar-with-dependencies.jar
Or java-jar target/$quickStart Java Project Name-0.0.1-SNAPSHOT-jar-with-dependencies.jar
... 02:01:19,277 [main] INFO org.activiti.engine.impl.ProcessEngineImpl - ProcessEngine default created processEngine [default] version: [5.22.0.0] ... 02:01:19,327 [main] DEBUG org.activiti.engine.impl.bpmn.deployer.BpmnDeployer - Processing deployment null 02:01:19,327 [main] INFO org.activiti.engine.impl.bpmn.deployer.BpmnDeployer - Processing resource onboarding.bpmn20.xml 02:01:19,444 [main] DEBUG org.activiti.engine.impl.bpmn.parser.handler.ProcessParseHandler - Parsing process ... 02:01:21,696 [main] DEBUG org.apache.ibatis.datasource.pooled.PooledDataSource - Returned connection 667346055 to pool. 02:01:21,696 [main] DEBUG org.activiti.engine.impl.interceptor.LogInterceptor - --- DeployCmd finished -------------------------------------------------------- ... 02:01:21,696 [main] DEBUG org.activiti.engine.impl.interceptor.LogInterceptor - --- starting ProcessDefinitionQueryImpl -------------------------------------------------------- ... 02:01:21,710 [main] DEBUG org.apache.ibatis.datasource.pooled.PooledDataSource - Returned connection 667346055 to pool. 02:01:21,710 [main] DEBUG org.activiti.engine.impl.interceptor.LogInterceptor - --- ProcessDefinitionQueryImpl finished -------------------------------------------------------- 02:01:21,710 [main] DEBUG org.activiti.engine.impl.interceptor.LogInterceptor - Found process definition [Onboarding] with id [onboarding:1:4]
The key output of interest here is the list line, which records the unique process ID (including the deployment version) of the process name "Onboarding" and "onboarding:1:4".
Your application now deploys the Onboarding process at runtime.