Activiti工作流集成CDI简介
- activiti-cdi模块提供activiti的可配置型和cdi扩大
activiti-cdi的个性:
- 反对 @BusinessProcessScoped beans, 绑定到流程实例的cdi bean
- 流程为cdi bean反对自定义EL处理器
- 应用注解为流程实例提供申明式管制
- Activiti能够挂接在cdi事件总线上
- 反对Java EE和Java SE, 反对Spring
- 反对单元测试
要在maven我的项目中应用activiti-cdi,须要增加依赖:
<dependency> <groupId>org.activiti</groupId> <artifactId>activiti-cdi</artifactId> <version>5.8</version></dependency>
activiti-cdi 5.6以上的版本会主动退出activiti-entin和spring
设置activiti-cdi
Activiti cdi能够装置在不同环境中
查找流程引擎
cdi扩大须要拜访到ProcessEngine, 为了实现此性能:
- 应用org.activiti.cdi.spi.ProcessEngineLookup接口在运行期间进行查找
- cdi模块应用默认的名为org.activiti.cdi.impl.LocalProcessEngineLookup的实现,应用ProcessEngines这个工具类来查找ProcessEngine
- 默认配置下,应用ProcessEngines#NAME_DEFAULT来查找ProcessEngine.这个类可能是应用自定义名称的子类
- ==留神:== 须要把activiti.cfg.xml放在classpath下
Activiti cdi应用java.util.ServiceLoader SPI解决org.activiti.cdi.spi.ProcessEngineLookup的实例
- 为了提供接口的自定义实现,须要创立一个文本文件,名为META-INF/services/org.activiti.cdi.spi.ProcessEngineLookup, 在文件中须要指定实现的全类名
如果你没有提供自定义的org.activiti.cdi.spi.ProcessEngineLookup实现,activiti会应用默认的LocalProcessEngineLookup实现,须要做的就是把activiti.cfg.xml放到classpath下
配置Process Engine
- 理论的配置依赖于选用的ProcessEngineLookup策略
- 在这里次要联合LocalProcessEngineLookup探讨可用的配置,要求在classpath下提供一个spring的activiti.cfg.xml
- Activiti提供了不同的ProcessEngineConfiguration实现,次要是依赖理论应用的事务管理策略
- activiti-cdi模块对事务的要求不严格,意味着任何事务管理策略都能够应用,即使是spring事务形象层
cdi模块提供两种自定义ProcessEngineConfiguration实现:
- org.activiti.cdi.CdiJtaProcessEngineConfiguration: activiti的JtaProcessEngineConfiguration的子类,用于在activiti应用JTA治理的事务环境
- org.activiti.cdi.CdiStandaloneProcessEngineConfiguration: activiti的StandaloneProcessEngineConfiguration的子类,用于在activiti应用简略JDBC事务环境
JBoss7下的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"> <!-- lookup the JTA-Transaction manager --> <bean id="transactionManager" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:jboss/TransactionManager"></property> <property name="resourceRef" value="true" /> </bean> <!-- process engine configuration --> <bean id="processEngineConfiguration" class="org.activiti.cdi.CdiJtaProcessEngineConfiguration"> <!-- lookup the default Jboss datasource --> <property name="dataSourceJndiName" value="java:jboss/datasources/ExampleDS" /> <property name="databaseType" value="h2" /> <property name="transactionManager" ref="transactionManager" /> <!-- using externally managed transactions --> <property name="transactionsExternallyManaged" value="true" /> <property name="databaseSchemaUpdate" value="true" /> </bean></beans>
在Glassfish 3.1.1,假如配置好名为jdbc/activiti的datasource:
<?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"> <!-- lookup the JTA-Transaction manager --> <bean id="transactionManager" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="java:appserver/TransactionManager"></property> <property name="resourceRef" value="true" /> </bean> <!-- process engine configuration --> <bean id="processEngineConfiguration" class="org.activiti.cdi.CdiJtaProcessEngineConfiguration"> <property name="dataSourceJndiName" value="jdbc/activiti" /> <property name="transactionManager" ref="transactionManager" /> <!-- using externally managed transactions --> <property name="transactionsExternallyManaged" value="true" /> <property name="databaseSchemaUpdate" value="true" /> </bean></beans>
留神: 下面的配置要引入spring-context模块依赖
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>3.0.3.RELEASE</version></dependency>
公布流程
- 能够应用规范的activiti-api公布流程-RepositoryService
- activiti-cdi也提供了主动公布classpath下processes.xml中列出的流程的形式
processes.xml:
<?xml version="1.0" encoding="utf-8" ?><!-- list the processes to be deployed --><processes> <process resource="diagrams/myProcess.bpmn20.xml" /> <process resource="diagrams/myOtherProcess.bpmn20.xml" /></processes>
基于CDI环境的流程执行
- BPMN业务流程通常是一个长时间运行的操作,蕴含了用户和零碎工作的操作
- 运行过程中,流程会分成多个独自的工作单元,由用户和应用逻辑执行
在activiti-cdi中,流程实例能够调配到cdi环境中,关联展示成一个工作单元:
- 这是十分有用的,如果工作单元太简单:比方如果实现的用户工作是不同模式的简单程序,能够在这个操作中放弃non-process-scoped状态
默认配置下,流程实例调配到broadest激活环境,就会启动交互,如果交互环境没有激活,就会返回到申请中
与流程实例进行关联交互
- 解决 @BusinessProcessScoped beans, 或注入流程变量时,实现了激活的cdi环境与流程实例的关联
Activiti-cdi提供了org.activiti.cdi.BusinessProcess bean来管制关联:
- startProcessByXx(...): 对应activiti的RuntimeService中的相干办法,容许启动和随后向关联的业务流程
- resumeProcessById(String processInstanceId): 容许通过提供的Id来关联流程实例
- resumeTaskById(String taskId): 容许通过提供的Id来关联工作,也能够扩大关联流程实例
- 一个工作单元实现后 ,completeTask() 办法能够调用来解除流程实例和会话或申请的关联.这会告诉activiti当前任务曾经实现,并让流程实例继续执行
BusinessProcess bean是 @Named bean, 意思是导出的办法能够通过表达式语言调用:
比方在JSF页面中.上面的JSF 2 代码启动一个新的交互,调配给一个用户工作实例,Id作为一个申请参数传递:
<f:metadata><f:viewParam name="taskId" /><f:event type="preRenderView" listener="#{businessProcess.startTask(taskId, true)}" /></f:metadata>
申明式流程管制
- Activiti-cdi容许通过注解申明启动流程实例和实现工作
@org.activiti.cdi.annotation.StartProcess注解容许通过key或name启动流程实例.流程实例会在注解的办法返回之后启动:
@StartProcess("authorizeBusinessTripRequest")public String submitRequest(BusinessTripRequest request) { // do some work return "success";}
依据activiti的配置,注解办法的代码和启动流程实例会在同一个事务中执行 .@org.activiti.cdi.annotation.CompleteTask事务的应用形式雷同:
@CompleteTask(endConversation=false)public String authorizeBusinessTrip() { // do some work return "success";}
@CompleteTask注解能够完结以后会话.默认行为会在activiti返回后完结会话.能够禁用完结会话的性能
在流程中援用bean
Activiti-cdi应用自定义解析器把CDI bean裸露到activiti El中,能够在流程中援用这些bean:
<userTask id="authorizeBusinessTrip" name="Authorize Business Trip" activiti:assignee="#{authorizingManager.account.username}" />
authorizingManager能够是生产者办法提供的bean:
@Inject @ProcessVariable Object businessTripRequesterUsername;@Produces@Namedpublic 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();
应用@BusinessProcessScoped beans
应用activiti-cdi,bean的生命周期能够绑定到流程实例上:
- 能够提供一个自定义的环境实现,命名为BusinessProcessContext.
- BusinessProcessScoped bean的实例会作为流程变量保留到以后流程实例中
- BusinessProcessScoped bean须要是PassivationCapable,比方序列化
应用流程作用域bean的示例如下:
@Named@BusinessProcessScopedpublic class BusinessTripRequest implements Serializable { private static final long serialVersionUID = 1L; private String startDate; private String endDate; // ...}
有时,须要应用流程作用域bean,没有与流程实例关联:
比方启动流程之前.如果以后流程实例没有激活 ,BusinessProcessScoped bean实例会临时保留在部分作用域里:
- 会话
- 申请
- 依赖环境
如果作用域起初与业务流程实例关联了,bean实例会刷新到流程实例里
注入流程变量
- 流程变量能够实现用于注入
Activiti-CDI反对以下注入流程变量的形式:
- @BusinessProcessScoped应用 @Inject [附加润饰] 类型 属性名实现类型平安的流程变量的注入
应用@ProcessVariable(name)修饰符实现对类型不平安的流程变量的注入
@Inject @ProcessVariable Object accountNumber;@Inject @ProcessVariable("accountNumber") Object account
为了通过EL援用流程变量, 能够应用如下形式:
- @Named @BusinessProcessScoped beans能够间接援用
其余流程变量能够应用ProcessVariables bean来应用
#{processVariables['accountNumber']}
接管流程事件
- Activiti能够挂在CDI的事件总线上,就能够应用规范CDI事件机制来监听流程事件
为了启用activiti的CDI事件反对,须要在配置中启用对应的解析监听器:
<property name="postBpmnParseHandlers"> <list> <bean class="org.activiti.cdi.impl.event.CdiEventSupportBpmnParseHandler" /> </list></property>
- 这样activiti就配置成了应用CDI事件总线公布事件
在CDI bean中处理事件的形式:
- 应用@Observes注解申明特定的事件监听器
- 事件监听是类型平安的
- 流程事件类型是org.activiti.cdi.BusinessProcessEvent
一个简略事件监听办法示例:
public void onProcessEvent(@Observes BusinessProcessEvent businessProcessEvent) { // handle event}
监听器能够监听所有事件.如果想限度监听器接管的事件类型,能够增加润饰注解:
@BusinessProcess: 限度指定流程定义的事件
- @Observes @BusinessProcess("billingProcess")
@StartActivity: 限度指定进入环节的事件
- @Observes @StartActivity("shipGoods")
@EndActivity: 限度指定完结环节的事件
- @Observes @EndActivity("shipGoods")
- @TakeTransition: 限度指定连线的事件
润饰命名能够自由组合:
为了接管shipmentProcess流程中所有来到shipGoods环节的事件:
public void beforeShippingGoods(@Observes @BusinessProcess("shippingProcess") @EndActivity("shipGoods") BusinessProcessEvent evt) { // handle event}
- 默认配置下,事件监听器是同步调用,并在同一个事务环境中
CDI事务性监听器能够管制监听器什么时候处理事件:
能够保障监听器只在事件中的事务胜利之后才解决
public void onShipmentSuceeded(@Observes(during=TransactionPhase.AFTER_SUCCESS) @BusinessProcess("shippingProcess") @EndActivity("shipGoods") BusinessProcessEvent evt) { // send email to customer.}
Activiti CDI中的更多功能
- 流程引擎和服务都能够注入: Inject ProcessEngine,RepositoryService,TaskService,...
- 以后流程实例和工作能够注入: @Inject ProcessInstance, Task
- 以后业务标识能够注入: @Inject @BusinessKey String businessKey
- 以后流程实例id能够注入: @Inject @ProcessInstanceId String pid