我们可以通过 activiti.cfg.xml 获取流程引擎配置对象 ProcessEngineConfiguration,然后通过流程引擎配置对象可以获取流程引擎对象 ProcessEngine对象。从流程引擎对象中可以获取很多对象,比如 RuntimeService、TaskService、RepositoryService等。本文主要对这些核心服务做一些介绍。
1. 流程存储服务 RepositoryService
- 管理流程定义文件xml以及静态资源的服务。
- 对特定流程的暂停和激活。
- 流程定义启动权限管理。
流程存储服务包括一些基础的api,部署文件构造器DeploymentBuilder
、部署文件查询器DeploymentQuery
、流程定义文件查询对象ProcessDefinitionQuery
。
通过流程存储服务可以获取很多对象,比如流程部署文件对象Deployment
、流程定义文件对象ProcessDefinitionQuery
、流程定义的java格式BpmnModel
。
进行测试相关的api
public class ConfigMDCTest {
private static final Logger logger = LoggerFactory.getLogger(ConfigMDCTest.class);
@Rule
public ActivitiRule activitiRule = new ActivitiRule();
@Test
public void test() throws Exception {
RepositoryService repositoryService = activitiRule.getRepositoryService();
DeploymentBuilder deploymentBuilder = repositoryService.createDeployment();
deploymentBuilder.name("测试部署").addClasspathResource("my-process.bpmn20.xml")
.addClasspathResource("secondClass_approve.bpmn20.xml");
deploymentBuilder.deploy();
DeploymentBuilder deploymentBuilder1 = repositoryService.createDeployment();
deploymentBuilder1.name("测试部署2").addClasspathResource("my-process.bpmn20.xml")
.addClasspathResource("secondClass_approve.bpmn20.xml");
deploymentBuilder1.deploy();
List<Deployment> deployments = repositoryService.createDeploymentQuery().orderByDeploymenTime().asc().listPage(0, 100);
for(Deployment deploy: deployments){
logger.info("流程部署名称", deploy.getName());
List<ProcessDefinition> processDefinitions = repositoryService.createProcessDefinitionQuery()
.deploymentId(deploy.getId()).listPage(0, 100);
for (ProcessDefinition processDefinition: processDefinitions) {
logger.info("流程定义文件名称 = {}, version ={}, id={}", processDefinition.getName(), processDefinition.getVersion(), processDefinition.getId());
}
}
}
}
//流程的暂停和激活
@Test
@org.activiti.engine.test.Deployment(resources = {"my-process.bpmn20.xml"})
public void testSuspend(){
RepositoryService repositoryService = activitiRule.getRepositoryService();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().singleResult();
repositoryService.suspendProcessDefinitionById(processDefinition.getId());//流程挂起
try {
activitiRule.getRuntimeService().startProcessInstanceById(processDefinition.getId());
} catch (Exception e) {
LOGGER.info("启动失败");
}
repositoryService.activateProcessDefinitionById(processDefinition.getId());//流程激活
activitiRule.getRuntimeService().startProcessInstanceById(processDefinition.getId());
LOGGER.info("启动成功");
}
// 流程定义启动权限管理
@Test
@org.activiti.engine.test.Deployment(resources = {"my-process.bpmn20.xml"})
public void testCandidateStarter(){
RepositoryService repositoryService = activitiRule.getRepositoryService();
ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().singleResult();
repositoryService.addCandidateStarterUser(processDefinition.getId(),"user");
repositoryService.addCandidateStarterGroup(processDefinition.getId(),"groupM");
List<IdentityLink> identityLinkList = repositoryService.getIdentityLinksForProcessDefinition(processDefinition.getId());
for(IdentityLink identityLink : identityLinkList){
LOGGER.info("identityLink: {}" , identityLink);
}
repositoryService.deleteCandidateStarterUser(processDefinition.getId(),"user");
repositoryService.deleteCandidateStarterGroup(processDefinition.getId(),"groupM");
List<IdentityLink> identityLinkList1 = repositoryService.getIdentityLinksForProcessDefinition(processDefinition.getId());
for(IdentityLink identityLink : identityLinkList1){
LOGGER.info("identityLink: {}" , identityLink);
}
}
2. 流程运行控制服务 RuntimeService
- 启动流程及对流程数据的控制。
- 流程实例(ProcessInstance)与执行流(Execution)查询。
- 触发流程操作、接收消息和信号。
RuntimeService启动流程及变量管理 - 启动流程的常用方式(id、key、message)。
- 启动流程可选参数(businessKey,variables、tenantId)。
- 变量(variables)的设置和获取
编写测试类
public class ConfigMDCTest {
private static final Logger logger = LoggerFactory.getLogger(ConfigMDCTest.class);
@Rule
public ActivitiRule activitiRule = new ActivitiRule();
@Test
public void test(){
RuntimeService runtimeService = activitiRule.getRuntimeService();
Map<String, Object> variables = Maps.newHashMap();
variables.put("key1", "value1");
//1. 流程启动的三种方式
/* ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("my-process", variables);*/
/*String id = activitiRule.getRepositoryService().createProcessDefinitionQuery().singleResult().getId();
runtimeService.startProcessInstanceById(id);*/
ProcessInstance processInstance = runtimeService.createProcessInstanceBuilder().businessKey("businessKey001")
.processDefinitionKey("my-process").variables(variables).start();
logger.info("流程实例{}已启动", processInstance);
//2. 变量的设置和获取
runtimeService.setVariableLocal(processInstance.getId(), "key1", "value1_");
Map<String, Object> variables1 = runtimeService.getVariables(processInstance.getId());
logger.info("变量 = {}", variables1);
//3. 流程实例的查询
ProcessInstance processInstance1 = runtimeService.createProcessInstanceQuery().processInstanceId(processInstance.getId()).singleResult();
//4. 流程执行对象的查询
List<Execution> executions = runtimeService.createExecutionQuery().processInstanceId(processInstance.getId()).listPage(0, 100);
for (Execution e: executions) {
logger.info("流程执行对象{}", e);
}
}
}
流程实例和执行流对象之间的关系:
//1. 流程实例(ProcessInstance)表示一次工作流业务的数据实体,启动一个流程就会窗机爱你一个流程实例。
//2. 执行流(Execution)表示流程实例中的执行路径。
//3. 流程实例继承了执行流,再其基础上扩展了一些接口。
当流程执行到某个特定的节点时,会将执行流程阻塞,直到流程被再次触发,触发流程有三种方式:触发器、信号和消息。
(1)触发器:使用 trigger 触发ReceiveTask节点(该节点类似与UserTask,当执行到该节点时会暂停,直到触发某一事件)。
我们需要首先重新绘制程序执行的流程图,添加ReceiveTask
节点,让程序流程阻塞到该节点。
<process id="my-process">
<startEvent id="start" />
<sequenceFlow id="flow1" sourceRef="start" targetRef="someTask" />
<!--<userTask id="someTask" name="Activiti is awesome!" />-->
<receiveTask id="someTask"/>
<sequenceFlow id="flow2" sourceRef="someTask" targetRef="end" />
<endEvent id="end" />
</process>
编写测试类触发阻塞的节点。
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void test(){
RuntimeService runtimeService = activitiRule.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("my-process");
Execution someTask = runtimeService.createExecutionQuery().activityId("someTask").singleResult();
logger.info("程序执行:{}", someTask);
runtimeService.trigger(someTask.getId());
someTask = runtimeService.createExecutionQuery().activityId("someTask").singleResult();
logger.info("程序执行:{}", someTask);
}
(2)信号: 触发信号捕获事件 signalEventReceived(捕获到某一信号,流程才会往下执行,信号可以针对全局)。
编写流程定义文件
<!--定义一个信号节点-->
<signal id="mySignal" name="my_signal"></signal>
<process id="my-process">
<startEvent id="start" />
<sequenceFlow id="flow1" sourceRef="start" targetRef="signal_catch" />
<!--定义一个捕获事件节点-->
<intermediateCatchEvent id="signal_catch">
<signalEventDefinition signalRef="mySignal"></signalEventDefinition>
</intermediateCatchEvent>
<sequenceFlow id="flow2" sourceRef="signal_catch" targetRef="end" />
<endEvent id="end" />
</process>
编写测试类
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void test(){
RuntimeService runtimeService = activitiRule.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("my-process");
Execution my_signal = runtimeService.createExecutionQuery().signalEventSubscriptionName("my_signal").singleResult();
logger.info("信号 = {}", my_signal);
runtimeService.signalEventReceived("my_signal");
my_signal = runtimeService.createExecutionQuery().signalEventSubscriptionName("my_signal").singleResult();
logger.info("信号 = {}", my_signal);
}
(3)消息:触发消息捕获事件(捕获到某一消息,流程才会往下执行,消息只能针对某一流程实例)
编写流程定义文件
<!--定义一个消息节点-->
<message id="myMessage" name="my_message"></message>
<process id="my-process">
<startEvent id="start" />
<sequenceFlow id="flow1" sourceRef="start" targetRef="signal_catch" />
<!--定义一个捕获事件节点-->
<intermediateCatchEvent id="signal_catch">
<messageEventDefinition messageRef="myMessage"></messageEventDefinition>
</intermediateCatchEvent>
<sequenceFlow id="flow2" sourceRef="signal_catch" targetRef="end" />
<endEvent id="end" />
</process>
编写测试类
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void test(){
RuntimeService runtimeService = activitiRule.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("my-process");
Execution my_message = runtimeService.createExecutionQuery().messageEventSubscriptionName("my_message").singleResult();
logger.info("消息 = {}", my_message);
runtimeService.messageEventReceived("my_message", my_message.getId());
my_message = runtimeService.createExecutionQuery().messageEventSubscriptionName("my_message").singleResult();
logger.info("消息 = {}", my_message);
}
在对流程运行控制服务中,我们介绍了三种启动方式:ID、Key和Message,我们来看通过消息是如何启动程序流程的。
编写程序流程定义文件。
<!--定义一个消息节点-->
<message id="myMessage" name="my_message"></message>
<process id="my-process">
<startEvent id="start">
<messageEventDefinition messageRef="myMessage"></messageEventDefinition>
</startEvent>
<sequenceFlow id="flow1" sourceRef="start" targetRef="someTask" />
<userTask id="someTask" />
<sequenceFlow id="flow2" sourceRef="someTask" targetRef="end" />
<endEvent id="end" />
</process>
编写测试类启动程序流程。
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void test(){
RuntimeService runtimeService = activitiRule.getRuntimeService();
ProcessInstance processInstance = runtimeService.startProcessInstanceByMessage("my_message");
}
3. 任务管理服务 TaskService
- 对用户任务(UserTask)进行管理和流程控制。
- 设置用户任务的权限信息(拥有者、候选人、办理人)。
- 针对用户任务添加任务附件、任务评论和事件记录。
(1)TaskService对Task管理与流程控制 - Task对象的创建和删除。
- 查询Task,并驱动Task节点完成执行。
- Task相关参数变量(variable)的设置。
创建流程定义文件
<process id="my-process">
<startEvent id="start"/>
<sequenceFlow id="flow1" sourceRef="start" targetRef="someTask" />
<userTask id="someTask">
<documentation>任务:${message}执行</documentation>
</userTask>
<sequenceFlow id="flow2" sourceRef="someTask" targetRef="end" />
<endEvent id="end" />
</process>
创建测试类
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void test(){
TaskService taskService = activitiRule.getTaskService();
Map<String, Object> params = Maps.newHashMap();
params.put("message", "myMessage");
activitiRule.getRuntimeService().startProcessInstanceByKey("my-process", params);
// 获取当前阻塞的流程节点
Task task = taskService.createTaskQuery().singleResult();
logger.info("task desc = {}", task.getDescription());
taskService.setVariable(task.getId(), "key1", "value1");
taskService.setVariableLocal(task.getId(), "localKey1", "localValue1");
Map<String, Object> variablesLocal = taskService.getVariablesLocal(task.getId());
logger.info("variablesLocal = {}", variablesLocal);
Map<String, Object> variables = taskService.getVariables(task.getId());
logger.info("variables = {}", variables);
Map<String, Object> processvariables = activitiRule.getRuntimeService().getVariables(task.getExecutionId());
logger.info("processvariables = {}", processvariables);
taskService.complete(task.getId());
}
(2)设置用户任务的权限信息
- 候选用户(candidateUser)和候选组(candidateGroup)。
- 指定拥有人(Owner)和办理人(Assignee)。
- 通过 claim 设置办理人。
编写流程定义文件
<process id="my-process">
<startEvent id="start"/>
<sequenceFlow id="flow1" sourceRef="start" targetRef="someTask" />
<userTask id="someTask" activiti:candidateUsers="user,admin,root"/>
<sequenceFlow id="flow2" sourceRef="someTask" targetRef="end" />
<endEvent id="end" />
</process>
编写测试类
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void test(){
TaskService taskService = activitiRule.getTaskService();
Map<String, Object> params = Maps.newHashMap();
params.put("message", "myMessage");
activitiRule.getRuntimeService().startProcessInstanceByKey("my-process", params);
Task task = taskService.createTaskQuery().singleResult();
//1. 指定任务的所有者为 当前用户root
taskService.setOwner(task.getId(), "root");
/*taskService.setAssignee(task.getId(), "root");*/
//2. 查询所有没有指定办理人,但是候选人是自己的任务
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("root").taskUnassigned().listPage(0, 100);
//3. 遍历任务设置这些任务的办理人
for (Task t : tasks){
taskService.claim(task.getId(), "root");
}
//4. 查询当前任务和其他用户的关系
List<IdentityLink> identityLinksForTask = taskService.getIdentityLinksForTask(task.getId());
identityLinksForTask.forEach(identityLink -> {logger.info("identityLink = {}",identityLink);});
taskService.complete(task.getId());
//5. 查询所有代办人为当前用户的任务,并进行处理
taskService.createTaskQuery().taskAssignee("root").listPage(0, 100)
.forEach(uncomtask ->{taskService.complete(uncomtask.getId());});
logger.info("是否还存在当前用户未处理的任务:{}", !taskService.createTaskQuery().taskAssignee("root").list().isEmpty());
}
(3)设置用户任务的附加信息
- 任务附件(attachment)的创建与查询。
- 任务评论(comment)的创建与查询。
- 事件记录(event)的创建与查询。
创建流程定义文件
<process id="my-process">
<startEvent id="start"/>
<sequenceFlow id="flow1" sourceRef="start" targetRef="someTask" />
<userTask id="someTask" activiti:candidateUsers="user,admin,root">
<documentation>任务:${message}执行</documentation>
</userTask>
<sequenceFlow id="flow2" sourceRef="someTask" targetRef="end" />
<endEvent id="end" />
</process>
创建测试类
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void test(){
TaskService taskService = activitiRule.getTaskService();
Map<String, Object> params = Maps.newHashMap();
params.put("message", "myMessage");
activitiRule.getRuntimeService().startProcessInstanceByKey("my-process", params);
Task task = taskService.createTaskQuery().singleResult();
taskService.setOwner(task.getId(), "root");
//1. 添加附件
taskService.createAttachment("url", task.getId(), task.getProcessInstanceId(), "name", "desc", "/url/atta.txt");
List<Attachment> attachments = taskService.getTaskAttachments(task.getId());
for (Attachment attachment: attachments) {
logger.info("attachment = {}", ToStringBuilder.reflectionToString(attachment, ToStringStyle.JSON_STYLE));
}
//2. 添加评论
taskService.addComment(task.getId(), task.getProcessInstanceId(), "我的评论");
List<Comment> taskComments = taskService.getTaskComments(task.getId());
taskComments.forEach(taskComment ->{logger.info("taskComment = {}", ToStringBuilder.reflectionToString(taskComment, ToStringStyle.JSON_STYLE));});
taskService.getTaskEvents(task.getId()).forEach(taskEvent ->{logger.info("taskEvent = {}", ToStringBuilder.reflectionToString(taskEvent, ToStringStyle.JSON_STYLE));});
}
4. 身份管理服务 IdentityService
- 管理用户(User)。
- 管理用户组(Group)。
- 用户与用户组的关系(Membership)。
编写测试类
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void test(){
IdentityService identityService = activitiRule.getIdentityService();
User user1 = identityService.newUser("user1");
user1.setPassword("123456");
identityService.saveUser(user1);
User user2 = identityService.newUser("user2");
user2.setPassword("123456");
identityService.saveUser(user2);
Group g1 = identityService.newGroup("g1");
identityService.saveGroup(g1);
Group g2 = identityService.newGroup("g1");
identityService.saveGroup(g2);
identityService.createMembership("user1", "g1");
identityService.createMembership("user1", "g2");
identityService.createMembership("user2", "g1");
identityService.createUserQuery().memberOfGroup("g1").listPage(0, 100)
.forEach(user ->{logger.info("g1 用户:{}", ToStringBuilder.reflectionToString(user, ToStringStyle.JSON_STYLE));});
}
5. 表单服务 FormService
- 解析流程定义中表单项的配置。
- 提交表单的方式驱动用户节点流转。
- 获取自定义外部表单key。
编写流程定义文件
<process id="my-process">
<startEvent id="start" activiti:formKey="/myProcess/startEvent/formKey">
<extensionElements>
<activiti:formProperty id="message" name="消息" type="string"></activiti:formProperty>
</extensionElements>
</startEvent>
<sequenceFlow id="flow1" sourceRef="start" targetRef="someTask"/>
<userTask id="someTask" activiti:formKey="/myProcess/userTask/formKey">
<extensionElements>
<activiti:formProperty id="submit" name="提交" type="string"></activiti:formProperty>
</extensionElements>
</userTask>
<sequenceFlow id="flow2" sourceRef="someTask" targetRef="end" />
<endEvent id="end" />
</process>
编写测试类
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void test(){
FormService formService = activitiRule.getFormService();
//1. 获取流程定义文件
ProcessDefinition processDefinition = activitiRule.getRepositoryService().createProcessDefinitionQuery().singleResult();
//2. 获取开始时间的表单属性
StartFormData startFormData = formService.getStartFormData(processDefinition.getId());
logger.info("开始节点的fomrkey = {}", startFormData.getFormKey());
List<FormProperty> formProperties = startFormData.getFormProperties();
for(FormProperty formProperty: formProperties){
logger.info("开始节点的表单属性 = {}", ToStringBuilder.reflectionToString(formProperty, ToStringStyle.JSON_STYLE));
}
HashMap<String, String> startMap = Maps.newHashMap();
startMap.put("message", "消息参数");
//3. 开始流程执行
ProcessInstance processInstance = formService.submitStartFormData(processDefinition.getId(), startMap);
Task task = activitiRule.getTaskService().createTaskQuery().singleResult();
//4. 获取任务节点的表单属性
TaskFormData taskFormData = formService.getTaskFormData(task.getId());
logger.info("任务节点的formKey = {}", taskFormData.getFormKey());
List<FormProperty> formProperties1 = taskFormData.getFormProperties();
for(FormProperty formProperty: formProperties1){
logger.info("任务节点的表单属性 = {}", ToStringBuilder.reflectionToString(formProperty, ToStringStyle.JSON_STYLE));
}
HashMap<String, String> taskMap = Maps.newHashMap();
taskMap.put("submit", "消息参数");
//5. 继续执行
formService.submitTaskFormData(task.getId(), startMap);
logger.info("task = {}", activitiRule.getTaskService().createTaskQuery().singleResult());
}
6. 历史管理服务 HistoryService
- 管理流程实例结束后的历史数据。
- 构建历史数据的查询对象。
- 根据流程实例ID删除流程历史数据。
HistoryService历史数据实体
历史数据实体 | 描述 |
---|---|
HistoricProcessInstance | 历史流程实例实体类 |
HistoricVariableInstance | 流程或任务变量值的实体 |
HistoricActivityInstance | 单个活动节点执行的信息 |
HistoricTaskInstance | 历史任务实例的信息 |
HistoricDetail | 历史流程活动任务详细信息 |
历史服务构建历史查询对象的方式:
- create[历史数据实体]Query。
- createNative[历史数据实体]Query。
- createProcessInstanceHistoryLogQuery。
历史服务删除历史操作:deleteHistoricProcessInstance、deleteHistoricTaskInstance。
首先修改配置文件中的historyLevel
级别的属性,然后进行编码测试:
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void test(){
ProcessInstanceBuilder processInstanceBuilder = activitiRule.getRuntimeService().createProcessInstanceBuilder();
ProcessInstance start = processInstanceBuilder.processDefinitionKey("my-process")
.variable("key1", "value1").variable("key2", "value2") //普通变量会持久化到数据库
.transientVariable("tkey1", "tvalue1").start();//瞬时变量不会
activitiRule.getRuntimeService().setVariable(start.getId(), "key1", "value1_");
Task task = activitiRule.getTaskService().createTaskQuery().processInstanceId(start.getId()).singleResult();
logger.info("task = {}", task);
HashMap<String, String> formParams = Maps.newHashMap();
formParams.put("fkey1","fvalues1");
formParams.put("key2","value2_f");
activitiRule.getFormService().submitTaskFormData(task.getId(), formParams);
HistoryService historyService = activitiRule.getHistoryService();
List<HistoricVariableInstance> historicVariableInstances = historyService.createHistoricVariableInstanceQuery().listPage(0, 100);
for (HistoricVariableInstance historicVariableInstance : historicVariableInstances) {
logger.info("historicVariableInstance = {}", historicVariableInstance);
}
//其他历史数据实体类似,略
//删除历史数据
historyService.deleteHistoricProcessInstance(start.getId());
logger.info("是否删除完成:{}", !historyService.createHistoricDetailQuery().list().isEmpty());
}
7. 其他管理服务 HistoryService
1.管理服务(ManagementService)
- job任务管理。
工作查询对象 | 描述 |
---|---|
JobQuery | 查询一般工作 |
TimerJobQuery | 查询定时工作 |
SuspendedJobQuery | 查询中断工作 |
DeadLetterJobQuery | 查询无法执行的工作 |
- 数据库相关通用操作。
- 查询表结构元数据(TableMetaData)。
- 通用表查询(TablePageQuery)。
- 执行自定义 Sql查询(executeCustomSql)。
- 执行流程引擎命令(Command)。
(1)由于需要自定义sql查询,所以需要定义mapper接口。
interface MyCustomMapper{
@Select("select * from act_ru_task")
public List<Map<String, Object>> findAll();
}
(2)修改配置类,将mapper类添加到StandaloneInMemProcessEngineConfiguration
属性中。
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneInMemProcessEngineConfiguration">
<property name="customMybatisMappers">
<set>
<value>activiti.MyCustomMapper</value>
</set>
</property>
</bean>
(3)编写测试类
@Test
@Deployment(resources = {"my-process.bpmn20.xml"})
public void test(){
ManagementService managementService = activitiRule.getManagementService();
//1. job任务管理
List<Job> jobs = managementService.createJobQuery().listPage(0, 100);
for (Job job : jobs) {
logger.info("job = {}", job);
}
//2. 数据库实体相关
TablePage tablePage = managementService.createTablePageQuery()
.tableName(managementService.getTableName(ProcessDefinitionEntity.class))
.listPage(0, 100);
tablePage.getRows().forEach(map ->{ logger.info("map = {}", map); });
activitiRule.getRuntimeService().startProcessInstanceByKey("my-process");
List<Map<String, Object>> maps = managementService.executeCustomSql(new AbstractCustomSqlExecution<MyCustomMapper, List<Map<String, Object>>>(MyCustomMapper.class) {
@Override
public List<Map<String, Object>> execute(MyCustomMapper myCustomMapper) {
return myCustomMapper.findAll();
}
});
logger.info("自定义sql查询:{}", maps);
//3. 执行命令
Object o = managementService.executeCommand(new Command<Object>() {
@Override
public Object execute(CommandContext commandContext) {
return commandContext.getProcessDefinitionEntityManager().findLatestProcessDefinitionByKey("my-process");
}
});
logger.info("流程定义实体 = {}", o);
}
2.动态流程定义服务(DynamicBpmnService)
动态的修改流程定义文件,很少用。