Activiti Core 7.0.0.Beta1 入门
我们刚刚向Maven Central
发布了Activiti Core
和 Activiti Cloud 7.0.0.Beta1
,我们想重点介绍新的Process 和 Task Runtime API。
创建新 API 的目的很明确,旨在满足以下要求:
- 为我们的云方法提供清晰的路径
- 隔离内部和外部 API 以提供向前的向后兼容性
- 通过遵循单一职责方法提供未来的模块化路径
- 减少旧版本 API 的混乱
- 将安全和身份管理作为一等公民
- 减少常见用例的价值实现时间,在这些用例中您希望依赖流行框架提供的约定
- 提供底层服务的替代实现
- 使社区能够在尊重既定合同的同时进行创新
我们尚未弃用旧 API,因此您仍然可以*使用它,但我们强烈建议使用新 API 以获得长期支持。
此 API 处于测试阶段,这意味着我们可能会在 GA 发布之前对其进行更改和完善。我们将感谢我们从社区用户那里获得的所有反馈,如果您想参与该项目,请与我们联系。
是时候让我们接触几个示例项目了。
任务运行时 API(TaskRuntime API)
如果您正在构建业务应用程序,为您组织中的用户和组创建任务可能会很方便。
该任务运行时API是来帮助你。
你可以从 GitHub
克隆这个例子:https://github.com/Activiti/activiti-examples
本节的代码可以在activiti-api-basic-task-example
maven 模块中找到。
如果您在 Spring Boot 2 应用程序中运行,您只需要添加 activiti-spring-boot-starter 依赖项和一个 DB 驱动程序,您可以使用 H2 进行内存存储。
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
我们建议使用我们的 BOM(物料清单
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-dependencies</artifactId>
<version>7.0.0.Beta1</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
现在让我们切换到我们的 DemoApplication.class
:
https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples/DemoApplication.java#L25
然后你就可以使用 TaskRuntime
@Autowired
private TaskRuntime taskRuntime;
将 bean 注入应用程序后,您应该能够创建任务并与任务进行交互。
public interface TaskRuntime {
TaskRuntimeConfiguration configuration();
Task task(String taskId);
Page tasks(Pageable pageable);
Page tasks(Pageable pageable, GetTasksPayload payload);
Task create(CreateTaskPayload payload);
Task claim(ClaimTaskPayload payload);
Task release(ReleaseTaskPayload payload);
Task complete(CompleteTaskPayload payload);
Task update(UpdateTaskPayload payload);
Task delete(DeleteTaskPayload payload);
...
}
例如,您可以通过执行以下操作来创建任务:
taskRuntime.create(
TaskPayloadBuilder.create()
.withName("First Team Task")
.withDescription("This is something really important")
.withGroup("activitiTeam")
.withPriority(10)
.build());
此任务仅对属于activitiTeam
的用户
和所有者(当前登录的用户)可见
。
为了处理安全性、角色和组,我们依赖 Spring Security
模块。因为我们在 Spring Boot
应用程序中,所以我们可以使用 UserDetailsService
来配置可用用户
及其各自的组
和角色
。我们目前正在@Configuration
类中执行此操作:
[https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples /DemoApplicationConfiguration.java#L26](https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples /DemoApplicationConfiguration.java#L26)
这里需要注意的重要一点是,为了作为用户与 TaskRuntime API
交互,您需要具有角色: ACTIVITI_USER (Granted Authority: ROLE_ACTIVITI_USER)
在与 REST
端点交互时,授权机制将设置当前登录的用户,但为了示例,我们使用了一个实用程序类
[https://github.com/Activiti/activiti-examples/blob/master/activiti -api-basic-task-example/src/main/java/org/activiti/examples/SecurityUtil.java#L26](https://github.com/Activiti/activiti-examples/blob/master/activiti -api-basic-task-example/src/main/java/org/activiti/examples/SecurityUtil.java#L26)
允许我们在上下文中设置手动选择的用户。请注意,除非您正在尝试并且想在不通过 REST
端点的情况下更改用户,否则您永远不应该这样做。查看“网络”示例以查看更多根本不需要此实用程序类的真实场景。
示例中要强调的最后一件事是任务事件侦听器
的注册
:https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-task-example/src/main/java/org/activiti/examples/DemoApplication.java#L89
@Bean
public TaskRuntimeEventListener taskAssignedListener() {
return taskAssigned
-> logger.info(
">>> Task Assigned: '"
+ taskAssigned.getEntity().getName()
+"' We can send a notification to the assignee: "
+ taskAssigned.getEntity().getAssignee());
}
您可以根据需要注册任意数量的 TaskRuntimeEventListener
。这将使您的应用程序能够收到由服务触发的运行时事件的通知。
进程运行时 API(ProcessRuntime API)
以类似的方式,如果您想开始使用 ProcessRuntime API
,您需要包含与以前相同的依赖项
。我们的目标
是在未来提供更多的灵活性
和独立的运行时
,但现在同一个 Spring Boot Starter
提供 TaskRuntime
和 ProcessRuntime API
。
本节的代码可以在“activiti-api-basic-process-example” maven 模块中找到。
public interface ProcessRuntime {
ProcessRuntimeConfiguration configuration();
ProcessDefinition processDefinition(String processDefinitionId);
Page processDefinitions(Pageable pageable);
Page processDefinitions(Pageable pageable,
GetProcessDefinitionsPayload payload);
ProcessInstance start(StartProcessPayload payload);
Page processInstances(Pageable pageable);
Page processInstances(Pageable pageable,
GetProcessInstancesPayload payload);
ProcessInstance processInstance(String processInstanceId);
ProcessInstance suspend(SuspendProcessPayload payload);
ProcessInstance resume(ResumeProcessPayload payload);
ProcessInstance delete(DeleteProcessPayload payload);
void signal(SignalPayload payload);
...
}
与 TaskRuntime API 类似,为了与 ProcessRuntime API 交互,当前登录的用户需要具有“ACTIVITI_USER”角色。
首先,让我们自动装配我们的 ProcessRuntime
:
https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-process-example/src/main/java/org/activiti/examples/DemoApplication.java#L32
@Autowired
private ProcessRuntime processRuntime;
@Autowired
private SecurityUtil securityUtil;
和以前一样,我们需要我们的 SecurityUtil 助手来定义我们正在与我们的 API 交互的用户。
现在我们可以开始与 ProcessRuntime 交互:
Page processDefinitionPage = processRuntime.processDefinitions(Pageable.of(0, 10));
logger.info("> Available Process definitions: " + processDefinitionPage.getTotalItems());
for (ProcessDefinition pd : processDefinitionPage.getContent()) {
logger.info("\t > Process definition: " + pd);
}
流程定义需要放在/src/main/resources/processes/
中。对于本示例,我们定义了以下流程:
我们正在使用 Spring 调度功能每秒启动一个进程,从数组中获取随机值以进行处理:
@Scheduled(initialDelay = 1000, fixedDelay = 1000)
public void processText() {
securityUtil.logInAs("system");
String content = pickRandomString();
SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yy HH:mm:ss");
logger.info("> Processing content: " + content
+ " at " + formatter.format(new Date()));
ProcessInstance processInstance = processRuntime
.start(ProcessPayloadBuilder
.start()
.withProcessDefinitionKey("categorizeProcess")
.withProcessInstanceName("Processing Content: " + content)
.withVariable("content", content)
.build());
logger.info(">>> Created Process Instance: " + processInstance);
}
和以前一样,我们使用ProcessPayloadBuilder
以流畅的方式参数化我们想要启动哪个流程以及使用哪些流程变量。
现在,如果我们回顾流程定义,您会发现 3 个服务任务。为了提供这些服务任务的实现,您需要定义连接器:
@Bean
public Connector processTextConnector() {
return integrationContext -> {
Map inBoundVariables = integrationContext.getInBoundVariables();
String contentToProcess = (String) inBoundVariables.get("content")
// Logic Here to decide if content is approved or not
if (contentToProcess.contains("activiti")) {
logger.info("> Approving content: " + contentToProcess);
integrationContext.addOutBoundVariable("approved",true);
} else {
logger.info("> Discarding content: " + contentToProcess);
integrationContext.addOutBoundVariable("approved",false);
}
return integrationContext;
};
}
这些连接器使用 Bean
名称自动连接到ProcessRuntime
,在本例中为“processTextConnector
”。这个 bean 名称是从我们流程定义中的serviceTask
元素的implementation
属性中提取的:
https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-process-example/src/main/resources/processes/categorize-content.bpmn20.xml#L22
<bpmn:serviceTask id="Task_1ylvdew" name="Process Content" implementation="processTextConnector">
这个新的连接器接口是JavaDelegates
的自然演变,新版本的Activiti Core
将尝试通过将它们包装在连接器实现中来重用您的 JavaDelegates:
public interface Connector {
IntegrationContext execute(IntegrationContext integrationContext);
}
连接器接收带有流程变量的IntegrationContext
并返回修改后的IntegrationContext
以及需要映射回流程变量的结果。
在前面的示例中,连接器实现正在接收一个“内容”
变量并根据内容处理逻辑添加一个“批准”
变量。
在这些连接器中,您可能会包含系统到系统调用,例如 REST 调用和基于消息的交互。这些交互往往变得越来越复杂,因此我们将在未来的教程中看到如何从ProcessRuntime
(云连接器)上下文之外运行中提取这些连接器,以解耦此类外部交互的责任。ProcessRuntime
范围。
检查 maven 模块activiti-api-spring-integration-example
以获得更高级的示例,使用 Spring Integrations
基于文件轮询器启动进程。
完整示例
您可以找到同时使用ProcessRuntime
和TaskRuntime API
来自动化以下过程的示例:
节的代码可以在“activiti-api-basic-full-example
” maven 模块中找到。
作为 ProcessRuntime only
示例,这也对一些输入内容进行了分类,但在这种情况下,流程依赖于人类演员来决定是否批准内容。我们有一个计划任务,它每 5 秒创建一次新的流程实例,还有一个模拟用户检查是否有可用的任务可以处理。
https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-full-example/src/main/java/org/activiti/examples/DemoApplication.java#L63
和
https://github.com/Activiti/activiti-examples/blob/master/activiti-api-basic-full-example/src/main/java/org/activiti/examples/DemoApplication.java#L85
所述UserTask
创建一组potentialOwners
,在这个例子中,“activitiTeam
”基团。但在这种情况下,我们不会像第一个示例那样手动创建任务。流程实例在每次启动流程时为我们创建任务。
<bpmn:userTask id="Task_1ylvdew" name="Process Content">
<bpmn:incoming>SequenceFlow_09xowo4</bpmn:incoming>
<bpmn:outgoing>SequenceFlow_1jzbgkj</bpmn:outgoing>
<bpmn:potentialOwner>
<bpmn:resourceAssignmentExpression>
<bpmn:formalExpression>activitiTeam</bpmn:formalExpression>
</bpmn:resourceAssignmentExpression>
</bpmn:potentialOwner>
</bpmn:userTask>
属于该组的用户将能够声明并处理该任务。
我们鼓励您运行这些示例并对其进行试验,如果您有疑问或发现问题,请与我们联系。
概括
在这篇博文中,我们看到了如何开始使用来自新 Activiti Core Beta1
项目的新ProcessRuntime
和TaskRuntime
API。
我们建议您查看Activiti
示例存储库,以获取更多示例:
[https : //github.com/Activiti/activiti-examples](https : //github.com/Activiti/activiti-examples)
帮助我们编写更多这些示例可能是一个非常好的初始社区贡献。如果您有兴趣,请与我们联系,我们非常乐意为您提供指导。
如果您对这些示例和教程有任何疑问或反馈,请随时通过 Gitter 与我们联系:[https