- 1. 简介
- 2. 开始
- 3. 配置
- 4. Flowable API
- 5. 集成 Spring
- 6. 部署
- 7. BPMN 2.0 介绍
- 8. BPMN 2.0 结构
- 9. 表单
- 10. JPA
- 11. 历史
- 12. 身份管理
- 13. Eclipse Designer
- 14. Flowable UI 应用
- 15. REST API
- 16. 集成 CDI
- 17. 集成 LDAP
- 18. 高级
- 19. 工具
16.2. 使用 CDI 的基于上下文的流程执行
本章节将介绍Flowable CDI扩展使用的基于上下文的流程执行模型(contextual process execution model)。BPMN业务流程通常是一个长期运行的交互动作,包含用户与系统的任务。在运行时,流程分割为独立工作单元的集合,由用户与/或应用逻辑操作。在flowable-cdi中,流程实例可以关联至一个CDI作用域,代表了一个工作单元。在工作单元很复杂的时候特别有用,比如用户任务由多个不同表单的复杂顺序组成,并需要在交互过程中保持"非流程作用域(non-process-scoped)"状态的场景。
16.2.1. 将一个会话关联至一个流程实例
解析@BusinessProcessScoped bean或注入流程变量,都依赖活动的CDI作用域与流程实例的关联。flowable-cdi提供了org.flowable.cdi.BusinessProcess
bean用于控制该关联,并提供:
startProcessBy(…)方法,镜像了Flowable
RuntimeService
服务暴露的对应方法,用于启动并关联一个业务流程,resumeProcessById(String processInstanceId)
,用于将给定id关联至流程实例,resumeTaskById(String taskId)
,用于将给定id关联至任务(以及扩展至相关的流程实例)。
当完成了一个工作单元(例如一个用户任务)时,可以调用completeTask()
方法,解除流程实例与会话/请求的关联。这将通知Flowable完成当前任务,并继续运行流程实例。
请注意BusinessProcess
bean是一个@Named
bean,意味着可以使用表达式(比如在JSF页面中)调用它。下面的JSF2代码片段启动了一个新的会话,并将其关联至一个用户任务实例,其id作为请求参数传递(例如pageName.jsf?taskId=XX
):
<f:metadata>
<f:viewParam name="taskId" />
<f:event type="preRenderView" listener="#{businessProcess.startTask(taskId, true)}" />
</f:metadata>
16.2.2. 声明式控制流程
Flowable可以使用注解,声明式地启动流程实例以及完成任务。@org.flowable.cdi.annotation.StartProcess
注解可以通过"key"或"name"启动一个流程实例。请注意流程实例在注解的方法返回之后启动。例如:
@StartProcess("authorizeBusinessTripRequest")
public String submitRequest(BusinessTripRequest request) {
// 进行一些操作
return "success";
}
按照Flowable的配置,被注解的方法代码以及流程实例的启动将处于同一个事务中。@org.flowable.cdi.annotation.CompleteTask
的使用方式相同:
@CompleteTask(endConversation=false)
public String authorizeBusinessTrip() {
// 进行一些操作
return "success";
}
@CompleteTask
注解可以结束当前会话。默认行为是在调用Flowable返回后结束回话。但可以像上面的例子一样,禁用结束会话。
16.2.3. 从流程中引用Bean
flowable-cdi使用自定义解析器,将CDI bean暴露给Flowable El。因此可以像这样在流程中引用bean:
<userTask name="Authorize Business Trip"
flowable:assignee="#{authorizingManager.account.username}" />
其中"authorizingManager"可以是生产者方法提供的bean:
@Inject @ProcessVariable Object businessTripRequesterUsername;
@Produces
@Named
public Employee authorizingManager() {
TypedQuery<Employee> query = entityManager.createQuery("SELECT e FROM Employee e WHERE e.account.username='"
+ businessTripRequesterUsername + "'", Employee.class);
Employee employee = query.getSingleResult();
return employee.getManager();
}
可以使用flowable:expression="myEjb.method()"
扩展,在服务任务中调用一个EJB中的业务方法。请注意这需要在MyEjb
类上使用@Named
注解。
16.2.4. 使用@BusinessProcessScoped bean
可以使用flowable-cdi将一个bean的生命周期绑定在一个流程实例上。为此提供名为BusinessProcessContext的自定义的上下文实现。BusinessProcessScoped bean实例将作为流程变量存储在当前流程实例中。BusinessProcessScoped bean需要是可持久化(PassivationCapable,例如Serializable)的。下面是一个流程作用域bean的例子:
@Named
@BusinessProcessScoped
public class BusinessTripRequest implements Serializable {
private static final long serialVersionUID = 1L;
private String startDate;
private String endDate;
// ...
}
有时也需要在没有关联至流程实例的情况下(例如在流程启动前)使用流程作用域bean。如果当前没有激活的流程实例,则BusinessProcessScoped bean的实例将临时存储在本地作用域(也就是会话或请求中,取决于上下文)。如果该作用域之后关联至一个业务流程实例,则会将bean实例刷入该流程实例。
16.2.5. 注入流程变量
flowable-cdi支持以下方式注入流程变量
使用
@Inject [additional qualifiers] Type fieldName
类型安全地注入@BusinessProcessScoped
bean使用
@ProcessVariable(name?)
限定名不安全地注入其它流程变量:
@Inject @ProcessVariable Object accountNumber;
@Inject @ProcessVariable("accountNumber") Object account
要在EL中引用流程变量,有类似的选择:
可以直接引用
@Named @BusinessProcessScoped
bean,可以通过
ProcessVariables
bean引用其它流程变量:
#{processVariables['accountNumber']}
16.2.6. 接收流程事件
Flowable可以关联至CDI事件总线。这样就可以使用标准CDI事件机制获取流程事件。要为Flowable启用CDI事件支持,需要在配置中启用相应的处理监听器:
<property name="postBpmnParseHandlers">
<list>
<bean class="org.flowable.cdi.impl.event.CdiEventSupportBpmnParseHandler" />
</list>
</property>
这样Flowable就被配置为使用CDI事件总线发布事件。下面介绍如何在CDI bean中接收流程事件。事件通知是类型安全的。流程事件的类型是org.flowable.cdi.BusinessProcessEvent
。 下面是一个简单的事件观察者方法的例子:
public void onProcessEvent(@Observes BusinessProcessEvent businessProcessEvent) {
// 处理事件
}
所有事件都会通知观察者。如果需要限制观察者接收的事件,可以添加限定注解:
@BusinessProcess
: 限制事件为特定的流程定义。例如:@Observes @BusinessProcess("billingProcess") BusinessProcessEvent evt
@StartActivity
: 使用特定的活动限制事件。例如:@Observes @StartActivity("shipGoods") BusinessProcessEvent evt
将在进入id为"shipGoods"的活动时调用。@EndActivity
: 使用特定的活动限制事件。例如:@Observes @EndActivity("shipGoods") BusinessProcessEvent evt
将在离开id为"shipGoods"的活动时调用。@TakeTransition
: 使用特定的路径限制事件。@CreateTask
: 使用特定任务的创建限制事件。@DeleteTask
: 使用特定任务的删除限制事件。@AssignTask
: 使用特定任务的指派限制事件。@CompleteTask
: 使用特定任务的完成限制事件。
上面的限定名可以自由组合。例如,要接收离开"shipmentProcess"中的"shipGoods"活动时生成的所有事件,可以撰写下面的观察者方法:
public void beforeShippingGoods(@Observes @BusinessProcess("shippingProcess") @EndActivity("shipGoods") BusinessProcessEvent evt) {
// 处理事件
}
在默认配置下,事件监听器将在上下文相同的事务中同步调用。CDI事务性观察者(CDI transactional observer,只能与JavaEE/EJB一起使用)可以在将事件交给观察者方法时进行控制。使用事务性观察者,可以保证比如只在触发事件的事务成功时才通知观察者:
public void onShipmentSuceeded(@Observes(during=TransactionPhase.AFTER_SUCCESS) @BusinessProcess("shippingProcess") @EndActivity("shipGoods") BusinessProcessEvent evt) {
// 给客户发送邮件。
}
16.2.7. 其他功能
可以注入流程引擎与服务:
@Inject ProcessEngine, RepositoryService, TaskService
, …可以注入当前的流程实例与任务:
@Inject ProcessInstance, Task
,可以注入当前的businessKey:
@Inject @BusinessKey String businessKey
,可以注入当前的流程实例id:
@Inject @ProcessInstanceId String pid
+
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论