Activiti-业务流程引擎

Activiti框架(Java)-XML任务流(bpm)及其管理的描述。 在这里,我将描述基本的基本概念以及如何构建简单的业务流程。

Activiti的主要概念是过程和任务。 流程是由定向流和分支互连的所有任务。

我将涉及以下方面:

  • -最原始形式的Activiti
  • -用户,角色
  • -连接SpringBoot
  • -REST API
  • -工作和代表

流从任务到任务的移动是逐步进行的,每个这样的步骤都会在等待输入和任务执行的同时暂停该过程,所有中间操作都保存在数据库中。

我将在下面指出在哪里采取什么措施。 让我们从一个简单的示例开始-程序开发过程,该过程包括编写代码和测试。 以下是流程图。

图片

这都是一个过程,它具有ID,Name和其他特征。

图片

它具有:

过程的开始,两个任务“开发”和“测试”,一个分支(网关),过程结束。 换句话说,一切都是这样的:

  • 加载bpm描述
  • 开始过程
  • 开始之后,我们立即进入Develop任务
  • 在执行Develop之后,它将进入测试阶段,并根据测试结果结束或再次返回到开发过程。

Activiti包含一组服务

这里是主要的:

  • RepositoryService:控制流程描述的加载
  • RuntimeService:启动进程
  • TaskService:执行任务
  • FormService:访问任务变量
  • HistoryService:访问流程历史记录
  • IdentityService:用户和角色

最原始形式的Activiti


但这一切都始于配置和文件-activiti.cfg.xml。

从这个

ProcessEngineConfiguration cfg = ProcessEngineConfiguration .createProcessEngineConfigurationFromResource("activiti.cfg.xml"); 

如果您不使用配置,则Activiti会将数据库本身部署在H2内存中,这不适合我,但是我心爱的Oracle已满,可以选择连接不同的数据库。

这是我的配置

activiti.cfg.xml
 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration"> <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:xe" /> <property name="jdbcDriver" value="oracle.jdbc.driver.OracleDriver" /> <property name="jdbcUsername" value="BPM" /> <property name="jdbcPassword" value="1" /> <!-- Database configurations --> <property name="databaseSchemaUpdate" value="false" /> <property name="asyncExecutorActivate" value="false" /> <!-- mail server configurations --> <property name="mailServerPort" value="5025" /> </bean> </beans> 


我们更改“属性名称= jdbc *”中的值,然后连接另一个数据库

项目结构



聚甲醛
 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>DemoActiviti</groupId> <artifactId>DemoActiviti</artifactId> <version>1.0-SNAPSHOT</version> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.activiti</groupId> <version>6.0.0</version> <artifactId>activiti-spring-boot-starter-integration</artifactId> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> <version>1.7.21</version> </dependency> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version>11.2.0</version> </dependency> </dependencies> <build> <plugins> <!-- Maven Assembly Plugin --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>2.4.1</version> <configuration> <!-- get all project dependencies --> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <!-- MainClass in mainfest make a executable jar --> <archive> <manifest> <mainClass>com.example.DemoActiviti</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>make-assembly</id> <!-- bind to the packaging phase --> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <target>1.8</target> </configuration> </plugin> </plugins> </build> </project> 


POM中存在插件“ maven-assembly-plugin”将使您能够构建(打包)一个具有依赖项启动并运行的jar
 java -jar DemoActiviti-1.0-SNAPSHOT-jar-with-dependencies.jar 

安装在本地Maven存储库中的Oracle jdbc驱动程序

 mvn install:install-file -Dfile={Path/to/your/ojdbc6.jar} -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.2.0 -Dpackaging=jar 

log4j
 log4j.rootLogger=WARN, ACT log4j.appender.ACT=org.apache.log4j.ConsoleAppender log4j.appender.ACT.layout=org.apache.log4j.PatternLayout log4j.appender.ACT.layout.ConversionPattern= %d{hh:mm:ss,SSS} [%t] %-5p %c %x - %m%n 


对于此过程,我们定义4个操作:bpm加载,过程启动,开发和测试。 每个动作将具有一个对应的参数:部署,开始,开发,测试。

我们从中获取数据库脚本
活动开始
在文件夹\ activiti-6.0.0 \ activiti-6.0.0 \数据库\创建中-创建数据库的脚本

用户,角色


准备用户和角色:

身分识别
 public class DemoActiviti { private static final String DEV_PROCESS = "devProcess"; public static void main(String[] args) { Locale.setDefault(Locale.ENGLISH); ProcessEngineConfiguration cfg = ProcessEngineConfiguration .createProcessEngineConfigurationFromResource("activiti.cfg.xml"); ProcessEngine processEngine = cfg.buildProcessEngine(); createIdentity(processEngine, "programmer", "programmers"); createIdentity(processEngine, "tester", "testers"); } public static void createIdentity(ProcessEngine processEngine, String userName, String userGroup) { IdentityService identityService = processEngine.getIdentityService(); String userId = userName + "Id"; if (identityService.createUserQuery().userId(userId).count() == 0) { User user = identityService.newUser(userName); user.setId(userId); user.setEmail(userName + "@gmail.com"); identityService.saveUser(user); System.out.println("user created success fully"); } String groupId = userGroup + "Id"; if (identityService.createGroupQuery().groupId(groupId).count() == 0) { Group group = identityService.newGroup(userGroup); group.setName(userGroup); group.setId(groupId); identityService.saveGroup(group); System.out.println("group created success fully"); } if (identityService.createGroupQuery().groupId(groupId).list().size() > 0) { identityService.createMembership(userId, groupId); System.out.println("user to group success fully"); } } } 


分别创建用户和组,开发人员和测试人员。

在数据库中,所有表均被相应的服务划分并具有前缀

ACT_RE_ *:存储库。
ACT_RU_ *:运行时。
ACT_ID_ *:身份。
ACT_HI _ *:历史记录
依此类推

从中创建用户后,您可以在此处看到

图片

我们将描述中的任务分配给相应的组(CandidateGroup),例如将Develop任务分配给该组-程序员

图片

因此,我们要做的第一件事是将其放置在数据库“ MyProcess.bpmn”中,并使用deploy命令运行该程序

 java -jar DemoActiviti-1.0-SNAPSHOT-jar-with-dependencies.jar deploy 

接下来,开始启动过程

 java -jar DemoActiviti-1.0-SNAPSHOT-jar-with-dependencies.jar start 

经过delpoy和start过程之后,相应的条目将出现在数据库中。

资料库

图片

运行时执行什么任务

图片

分配给谁

图片

在代码中,看起来像这样(完整的代码将在下面):

部署

 deployment = repositoryService.createDeployment() .addClasspathResource("processes/MyProcess.bpmn").deploy() 

开始

 ProcessInstance myProcess = runtimeService.startProcessInstanceByKey(DEV_PROCESS); 

发展

之后,您可以开始完成开发任务

 java -jar DemoActiviti-1.0-SNAPSHOT-jar-with-dependencies.jar develop 

  //    tasks = taskService.createTaskQuery().taskCandidateGroup("programmers").list(); 

在“开发”任务中,定义了一个“问题”变量

图片

使用FormService处理变量后,任务运行

 for (Task task : tasks) { System.out.println("Task:" + task.getTaskDefinitionKey() + ", id=" + task.getId()); FormData formData = formService.getTaskFormData(task.getId()); Map<String, Object> variables = new HashMap<String, Object>(); //   for (FormProperty formProperty : formData.getFormProperties()) { System.out.println("Enter varName <" + formProperty.getName() +">:"); String value = scanner.nextLine(); variables.put(formProperty.getId(), value); } //   taskService.complete(task.getId(), variables); System.out.println("Task complete success:" + task.getTaskDefinitionKey()); } 

图片

对于“开发”任务,系统将提示您输入变量。

在历史表中,您可以看到任务,流程的变量和值

图片

这样,Develop任务之后的进程将停止在其上,状态将保存在数据库中。

通常,循环如下所示:

要求执行者执行任务

 tasks = taskService.createTaskQuery().taskCandidateGroup("...").list(); 

变量定义

 Map<String, Object> variables = new HashMap<String, Object>(); ... variables.put("var_1", value); 

任务执行

 taskService.complete(task.getId(), variables); 

检查过程结束

 ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() .processInstanceId(processInstance.getId()).singleResult(); if (processInstance != null && !processInstance.isEnded()) 

在执行每个任务之后,该过程将被挂起,直到完成新任务。
因此,执行完Develop之后,让我们继续执行Test任务,在这里我们还将被要求输入变量“ devResult”-开发结果(即使在Test开始之前,输入结果也不太正确,然后输入结果),然后结果将是分支或结束(确定)或重新开发(否),请参见流程图。

图片

在这种情况下,发展等 如果您现在要求开发人员执行任务,那么将是任务,但需要进行测试-不。

程式码
 package com.example; import org.activiti.engine.*; import org.activiti.engine.form.FormData; import org.activiti.engine.form.FormProperty; import org.activiti.engine.repository.Deployment; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.apache.commons.lang3.StringUtils; import java.util.*; public class DemoActiviti { private static final String DEV_PROCESS = "devProcess"; public static void main(String[] args) { Locale.setDefault(Locale.ENGLISH); ProcessEngineConfiguration cfg = ProcessEngineConfiguration .createProcessEngineConfigurationFromResource("activiti.cfg.xml"); ProcessEngine processEngine = cfg.buildProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); String mode = StringUtils.EMPTY; if (args.length > 0) { mode = args[0]; } System.out.println("Processes mode: " + mode); Deployment deployment; if ("deploy".equals(mode)) { deployment = repositoryService.createDeployment() .addClasspathResource("processes/MyProcess.bpmn").deploy(); System.out.println("deploy process success"); System.exit(0); } else { List<Deployment> myProcesses = repositoryService.createDeploymentQuery() .processDefinitionKey(DEV_PROCESS).list(); deployment = myProcesses.get(myProcesses.size()-1); System.out.println("get process success:" + deployment.getId()); } // RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance; if ("start".equals(mode)){ ProcessInstance myProcess = runtimeService.startProcessInstanceByKey(DEV_PROCESS); System.out.println("start process success:" + myProcess.getName() +", id="+ myProcess.getId()); System.exit(0); } processInstance = runtimeService.createProcessInstanceQuery().deploymentId(deployment.getId()).singleResult(); TaskService taskService = processEngine.getTaskService(); FormService formService = processEngine.getFormService(); List<Task> tasks = new ArrayList<>(); if ("develop".equals(mode)) { System.out.println("develop mode"); //     tasks = taskService.createTaskQuery().taskCandidateGroup("programmers").list(); if (tasks.isEmpty()) { System.out.println("   "); System.exit(0); } } if ("test".equals(mode)) { System.out.println("test mode"); //     tasks = taskService.createTaskQuery().taskCandidateGroup("testers").list(); if (tasks.isEmpty()) { System.out.println("   "); System.exit(0); } } Scanner scanner = new Scanner(System.in); if (processInstance != null && !processInstance.isEnded()) { System.out.println("tasks count: [" + tasks.size() + "]"); for (Task task : tasks) { System.out.println("Task:" + task.getTaskDefinitionKey() + ", id=" + task.getId()); FormData formData = formService.getTaskFormData(task.getId()); Map<String, Object> variables = new HashMap<String, Object>(); //   for (FormProperty formProperty : formData.getFormProperties()) { System.out.println("Enter varName <" + formProperty.getName() +">:"); String value = scanner.nextLine(); variables.put(formProperty.getId(), value); } //   taskService.complete(task.getId(), variables); System.out.println("Task complete success:" + task.getTaskDefinitionKey()); } // Re-query the process instance, making sure the latest state is available //processInstance = runtimeService.createProcessInstanceQuery() // .processInstanceId(processInstance.getId()).singleResult(); } } } 


连接SpringBoot


我们使用Spring修改项目

向POM添加依赖项

使用SpringBoot的POM
  <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.1.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.activiti</groupId> <artifactId>activiti-spring-boot-starter-basic</artifactId> <version>6.0.0</version> </dependency> <dependency> <groupId>org.activiti</groupId> <version>6.0.0</version> <artifactId>activiti-spring-boot-starter-integration</artifactId> </dependency> .... 


DemoActiviti类现在已经变成这样
DemoActiviti-SpringBootApplication
 @SpringBootApplication @ImportResource("classpath:activiti.cfg.xml") public class DemoActiviti { public static void main(String[] args) { Locale.setDefault(Locale.ENGLISH); SpringApplication.run(DemoActiviti.class, args); } } 


我使用混合模型-当部分Bean在xml配置中描述时(@ImportResource(“ classpath:activiti.cfg.xml”)),其他通过注释定义。

activiti.cfg.xml-春天
 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <bean id="dataSource" class="org.springframework.jdbc.datasource.SimpleDriverDataSource"> <property name="url" value="jdbc:oracle:thin:@localhost:1521:xe" /> <property name="driverClass" value="oracle.jdbc.driver.OracleDriver" /> <property name="username" value="BPM" /> <property name="password" value="1" /> </bean> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration"> <property name="dataSource" ref="dataSource" /> <property name="transactionManager" ref="transactionManager" /> <property name="databaseSchemaUpdate" value="true" /> <property name="asyncExecutorActivate" value="false" /> </bean> </beans> 


现在Spring负责配置了,可以看出

 bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration" 

将SpringBoot作为组件添加标准命令行处理

指令行
 @Component public class CommandLine implements CommandLineRunner { @Autowired private DemoService demoService; public void run(String... args) { if ("test".equals(args[0])) { demoService.startTest(); } else if ("develop".equals(args[0])) { demoService.startDevelop(); } } } 


它将处理所有这些命令,我​​将不会全部执行它们,那里的一切都很简单,我将展示两个:测试和开发。 并添加服务来处理它们

演示服务
 @Service public class DemoService { @Autowired private TaskService taskService; @Autowired private FormService formService; public void startTest() { List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("testers").list(); if (tasks.isEmpty()) { System.out.println("   "); return; } processTasks(tasks); } public void startDevelop() { List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("develop").list(); if (tasks.isEmpty()) { System.out.println("   "); return; } processTasks(tasks); } private void processTasks(List<Task> tasks) { Scanner scanner = new Scanner(System.in); for (Task task : tasks) { ......    ,  } 


在CommandLine组件Autowir中,它们具有DemoService服务,并且其中已经准备好了Spring Activiti服务。

 @Autowired private TaskService taskService; 

我们从命令行收集并像以前一样运行。

如果要使用Web上的任务执行,请连接REST API。

REST API


默认情况下,SpringBoot将提供嵌入式Tomcat服务器,然后是技术问题。
在POM中,添加Spring Web依赖项

  <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> 

我们删除了CommandLine组件,现在所有内容都将通过HTTP通过URL传递。 添加RestController:

休息控制器
 @RestController public class DemoRestController { @Autowired private DemoService demoService; @RequestMapping(value="/test", method= RequestMethod.GET, produces= {MediaType.APPLICATION_JSON_VALUE}) public List<String> startTest(@RequestParam String devResult) { List<String> strings = demoService.startTest(devResult); return strings; } @RequestMapping(value="/develop", method= RequestMethod.GET, produces= MediaType.APPLICATION_JSON_VALUE) public List<String> startDevelop(@RequestParam String issue) { List<String> strings = demoService.startDevelop(issue); return strings; } @RequestMapping(value="/start", method= RequestMethod.GET, produces= MediaType.APPLICATION_JSON_VALUE) public List<String> startProcess() { List<String> strings = demoService.startDevProcess(); return strings; } } 


我们执行相同的命令,稍微更改了Autowire在控制器中的DemoService服务的响应。

演示服务
 @Service public class DemoService { @Autowired private TaskService taskService; @Autowired private FormService formService; @Autowired private RuntimeService runtimeService; public List<String> startTest(String devResult) { List<String> results = new ArrayList<>(); List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("testers").list(); if (tasks.isEmpty()) { results.add("The tasks for testing are not"); return results; } Object issue = runtimeService.getVariables(tasks.get(0).getProcessInstanceId()).get("issue"); processTasks(tasks, devResult); results.add("Task N " + issue + " - tested, result=" + devResult); return results; } public List<String> startDevelop(String issue) { List<String> results = new ArrayList<>(); List<Task> tasks = taskService.createTaskQuery().taskCandidateGroup("programmers").list(); if (tasks.isEmpty()) { results.add("There are no development tasks"); return results; } processTasks(tasks, issue); Object mIssue = runtimeService.getVariables(tasks.get(0).getProcessInstanceId()).get("issue"); results.add("Task N " + mIssue + " - taken in the develop"); return results; } public List<String> startDevProcess() { List<String> results = new ArrayList<>(); ProcessInstance myProcess = runtimeService.startProcessInstanceByKey("devProcess"); results.add("The process is started #"+myProcess.getId()); return results; } private void processTasks(List<Task> tasks, String param) { for (Task task : tasks) { FormData formData = formService.getTaskFormData(task.getId()); Map<String, Object> variables = new HashMap<>(); //   for (FormProperty formProperty : formData.getFormProperties()) { variables.put(formProperty.getId(), param); } //   taskService.complete(task.getId(), variables); } } } 


使用curl进行测试,结果如下:

图片

我在application.properties中将Tomcat的端口更改为8081
server.port = 8081

Activiti工作


Activiti有很多设计,例如,启动计划任务是“ TimerStartEvent”。 为了让Job在限制条件下开始执行,您必须指定
property name="asyncExecutorActivate" value="true" (请参阅activiti.cfg.xml),则Java进程将保持运行,并检查计划和运行任务。

我将回到最初的项目,其中以最原始的形式使用Activiti。

在DemoActiviti类中,我将仅支持以下两个命令:部署和启动我将进行一个新过程

图片

该过程开始后,他将转到计时器,计时器将根据时间表启动“开发”任务。 计时器将有一个时间表-每10秒启动一次,cron表达式-“ 0/10 * * * * *?”。

图片

让我们像以前一样部署新流程,然后启动该流程(开始)。 全部-任务每10秒运行一次。

作为一项任务,选择了Activiti组件-ServiceTask,您可以从中将其指定为Java类实现。

图片

类DemoDelegate
 public class DemoDelegate implements JavaDelegate { @Override public void execute(DelegateExecution execution) { Date now = new Date(); execution.setVariable("issue", now.toString()); System.out.println("job start="+now); } } 


在数据库的表中(从ACT_RU_TIMER_JOB t中选择*),您可以看到

图片

作业活动,在DUEDATE_字段中将有下一次启动时间。

代表的“问题”变量将记录在执行历史中

 select * from ACT_HI_VARINST t 

图片

DemoActiviti c Job的代码
 public class DemoActiviti { private static final String DEV_PROCESS = "devProcessJob"; public static void main(String[] args) { Locale.setDefault(Locale.ENGLISH); ProcessEngineConfiguration cfg = ProcessEngineConfiguration .createProcessEngineConfigurationFromResource("activiti.cfg.xml"); ProcessEngine processEngine = cfg.buildProcessEngine(); RepositoryService repositoryService = processEngine.getRepositoryService(); String mode = StringUtils.EMPTY; if (args.length > 0) { mode = args[0]; } System.out.println("Processes mode: " + mode); Deployment deployment; if ("deploy".equals(mode)) { deployment = repositoryService.createDeployment() .addClasspathResource("processes/MyProcessJob.bpmn").deploy(); System.out.println("deploy process success"); System.exit(0); } else { List<Deployment> myProcesses = repositoryService.createDeploymentQuery() .processDefinitionKey(DEV_PROCESS).list(); deployment = myProcesses.get(myProcesses.size()-1); System.out.println("get process success:" + deployment.getId()); } // RuntimeService runtimeService = processEngine.getRuntimeService(); ProcessInstance processInstance; if ("start".equals(mode)){ ProcessInstance myProcess = runtimeService.startProcessInstanceByKey(DEV_PROCESS); System.out.println("start process success:" + myProcess.getName() +", id="+ myProcess.getId()); } } } 


还有很多遗留事件:事件,侦听器,JPA等,也许我会回到他们身上。

用料
Activiti
Eclipse设计师

devProcess bpmn
 <?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/test"> <process id="devProcess" name="Dev process" isExecutable="true"> <startEvent id="startevent1" name="Start" activiti:initiator="programmerId"></startEvent> <userTask id="develop" name="Develop" activiti:candidateGroups="programmers"> <extensionElements> <activiti:formProperty id="issue" name="issue" type="string" required="true"></activiti:formProperty> </extensionElements> </userTask> <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="develop"></sequenceFlow> <userTask id="test" name="Test" activiti:candidateGroups="testers"> <extensionElements> <activiti:formProperty id="devResult" name="devResult" type="string" default="No" required="true"></activiti:formProperty> </extensionElements> </userTask> <sequenceFlow id="flow2" sourceRef="develop" targetRef="test"></sequenceFlow> <exclusiveGateway id="gateway" name="Exclusive Gateway" default="flowNo"></exclusiveGateway> <sequenceFlow id="flow3" sourceRef="test" targetRef="gateway"></sequenceFlow> <sequenceFlow id="flowOk" name="Ok" sourceRef="gateway" targetRef="endevent1"> <conditionExpression xsi:type="tFormalExpression"><![CDATA[${devResult == "Ok"}]]></conditionExpression> </sequenceFlow> <sequenceFlow id="flowNo" name="No" sourceRef="gateway" targetRef="develop"></sequenceFlow> <endEvent id="endevent1" name="End"></endEvent> </process> </definitions> 


devProcessJob bpmn
 <?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/test"> <process id="devProcessJob" name="Dev process Job" isExecutable="true"> <startEvent id="startevent" name="Start" activiti:initiator="programmerId"></startEvent> <sequenceFlow id="flow1" sourceRef="startevent" targetRef="timerstartevent"></sequenceFlow> <endEvent id="endevent" name="End"></endEvent> <startEvent id="timerstartevent" name="Timer start"> <extensionElements> <activiti:formProperty id="issue" name="issue" type="string"></activiti:formProperty> </extensionElements> <timerEventDefinition> <timeCycle>0/10 * * * * ?</timeCycle> </timerEventDefinition> </startEvent> <sequenceFlow id="flow2" sourceRef="timerstartevent" targetRef="servicetask1"></sequenceFlow> <sequenceFlow id="flow3" sourceRef="servicetask1" targetRef="endevent"></sequenceFlow> <serviceTask id="servicetask1" name="Develop" activiti:class="com.example.DemoDelegate"></serviceTask> </process> </definitions> 

Source: https://habr.com/ru/post/zh-CN416491/


All Articles