开源工作流引擎activiti与bboss整合使用方法浅析

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介: 本文介绍开源工作流引擎activiti与bboss ioc框架整合方法,涉及内容如下: a).activiti采用bboss ioc来配置和初始化流程引擎 b).在activiti流程中使用bboss ioc容器托管的组件 c).bboss 托管activiti引擎流程处理事务 下面介绍前两部分,事务部分请参考文章《bboss持久层事务管理组件托管第三方持久层框架(mybatis等)事务功能介绍 》。
本文介绍开源工作流引擎activiti与bboss ioc框架整合方法,涉及内容如下:
a).activiti采用bboss ioc来配置和初始化流程引擎
b).在activiti流程中使用bboss ioc容器托管的组件
c).bboss 托管activiti引擎流程处理事务

下面介绍前两部分,事务部分请参考文章 《bboss持久层事务管理组件托管第三方持久层框架(mybatis等)事务功能介绍 》

1 activiti-bboss源码工程下载及构建方法
1.1 环境准备
安装好jdk 1.6,ant 1.7.1或以上版本,并配置好jdk和ant的环境变量
安装好mysql数据库(自行安装),并启动
在mysql中建立一个activiti的数据库
准备好 eclipse

1.2 下载activiti与bboss结合的源码工程
基于activiti-5.12和最新的 bbossgroups 3.6.2
https://github.com/yin-bp/activiti-engine-5.12

1.3 下载后解压并构建

执行解压目录下的run.bat文件构建activiti流程引擎的jar包,生成的jar存放在distrib目录下:

img_8593ce4433b48a8814c054e5ca801248.jpe

2 在源码工程中运行流程测试用例
解压目录是一个eclipse工程,将其导入eclipse中
2.1 修改src/test/resources/poolman.xml中的数据库地址为mysql数据库地址,并设置账户:
 
......
<dbname>mysql</dbname>
<driver>com.mysql.jdbc.Driver</driver>

     <url>jdbc:mysql://localhost:3306/activiti</url> 

    <username>root</username>
    <password>123456</password>
............


2.2 修改src/test/resources/activiti.cfg.xml文件内容
为activiti配置bboss数据源mysql(是刚才在poolman.xml文件中配置的dbname为mysql的数据源的名称,该名称可以根据自己需要进行命名,没有特殊约定):

....
<property name="dataSource" factory-class="com.frameworkset.common.poolman.util.SQLManager" factory-method="getTXDatasourceByDBName">
    	<construction>
    		<property value="mysql" />
    	</construction>
    </property>
.....


为activiti配置bboss ioc容器对象,以便在测试用例中引用bboss ioc管理的组件来获取和设置流程环节处理人:
<property name="beanFactory" factory-class="org.frameworkset.spi.DefaultApplicationContext" 
			  factory-method="getApplicationContext">
			  <construction>
			  <property value="beans.xml"/>
			  </construction>
	</property>

被activiti使用的bboss ioc容器可以是独立的ioc容器,例如如上配置就是一个加载beans.xml的类型为DefaultApplicationContext的独立ioc容器(本文以独立ioc容器为例);也可以是bboss mvc对应的ioc容器,这样web应用中的流程就可以使用mvc ioc容器中配置的各种业务组件,mvc容器配置示例如下:
<property name="beanFactory" 
			  factory-class="org.frameworkset.web.servlet.support.WebApplicationContextUtils" 
			  factory-method="getWebApplicationContext"/>


下面是一个完整的activiti.cfg.xml文件:
<?xml version="1.0" encoding="UTF-8"?>
<properties>
  <property name="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
     <property name="dataSource" factory-class="com.frameworkset.common.poolman.util.SQLManager" factory-method="getTXDatasourceByDBName">
    	<construction>
    		<property value="mysql" />
    	</construction>
    </property>
    <!-- Database configurations -->
    <property name="databaseSchemaUpdate" value="true" />    
    <!-- job executor configurations -->
    <property name="jobExecutorActivate" value="false" />    
    <!-- mail server configurations -->
    <property name="mailServerPort" value="5025" />    
    <property name="history" value="full" />
  </property>
  <property name="beanFactory" factory-class="org.frameworkset.spi.DefaultApplicationContext" 
			  factory-method="getApplicationContext">
			  <construction>
			  <property value="beans.xml"/>
			  </construction>
	</property>
</properties>

加载activiti.cfg.xml并启动Activiti:
TransactionManager tm = new TransactionManager();
		try
		{
			tm.begin();
			processEngine = ProcessEngineConfiguration
					.createProcessEngineConfigurationFromResource(xmlPath)
					.buildProcessEngine();
			tm.commit();
		}
		catch(Exception e)
		{
			throw new RuntimeException(e);
		}
		finally
		{
			tm.releasenolog();
		}

说明:之所以将初始化activiti流程引擎的逻辑包含在一个bboss 的事务上下文之中,是因为activiti使用的是mybatis 3.0.6版本存在一个缺陷,这个缺陷表现为:先通过sqlsession开启一个事务,然后直接通过sqlsession的getconnection方法获取一个DB链接来执行多次数据库的增删改操作,如果全部执行成功,调用sqlsession的commit方法提交事务,如果执行成功一部分操作后出现异常,再调用sqlsession的rollback回滚事务,这样问题就出来了,mybatis会直接把connection返回给链接池,并不会提交或者回滚之前的db操作(因为这些操作没有调用sqlsession的相关方法来执行,而是直接通过connection完成的),connection并没有被物理关闭而只是返回到池中,这样就导致了之前修改和删除的数据被锁定了,导致后续针对这些锁定的记录的修改操作全部被阻塞造成不可预估的后果。

activiti在启动时会从mybatis的sqlsession中直接获取一个connection来执行创建和更新流程的库表结构并往属性表中插入或者更新流程的版本信息,如果在执行的过程中出现了问题的话,会导致数据库死锁,但是我们采用bboss的事务管理框架来托管mybatis的事务后就能够正常解决这个问题。

2.3 beans.xml 配置和管理bboss ioc组件

我们在src/test/resources/beans.xml文件中配置了一个组件:
<properties>
<property name="taskAssigneeAssignment" class="org.frameworkset.activiti.test.AssigneeAssignment"/>

</properties>


org.frameworkset.activiti.test.AssigneeAssignment组件是一个activiti task listener ,同时有个getHandlerMan方法用来获取任务处理人,代码如下:
package org.frameworkset.activiti.test;

import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;


/**
 * @author biaoping.yin
 */
public class AssigneeAssignment implements TaskListener {

  public void notify(DelegateTask delegateTask) {
    delegateTask.setAssignee("kermit");//设置任务处理人
  }
  
  public String getHandlerMan()
  {
	  return "kermit";
  }
  
}


3 在activiti的流程定义文件中引用bboss ioc中的组件
3.1 组件作为任务监听器使用
流程定义文件src/test/resources/org/activiti/examples/bpmn/tasklistener/CustomTaskAssignmentTest.testAssigneeAssignment.bpmn20.xml相关内容:
<activiti:taskListener event="create" delegateExpression="${taskAssigneeAssignment}" />


流程定义文件完整内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<definitions id="taskListenerExample" 
  xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  xmlns:activiti="http://activiti.org/bpmn"
	targetNamespace="Examples">
	
	<process id="setAssigneeInListener" name="Custom task assignment Example">
	
		<startEvent id="theStart" />
		
		<sequenceFlow id="flow1" sourceRef="theStart" targetRef="task1" />

		<userTask id="task1" name="Schedule meeting" >
		  <documentation>
		    Schedule a meeting with management.
		  </documentation>
		  <extensionElements>
		    <!--<activiti:taskListener event="create" class="org.activiti.examples.bpmn.tasklistener.AssigneeAssignment" />  -->
		    <activiti:taskListener event="create" delegateExpression="${taskAssigneeAssignment}" />
		  </extensionElements>
		</userTask>
		
		<sequenceFlow id="flow2" sourceRef="task1" targetRef="theEnd" />
		
		<endEvent id="theEnd" />
		
	</process>

</definitions>


流程执行示例
测试用例:
src/test/java/org/activiti/examples/bpmn/tasklistener/CustomTaskAssignmentTest.java
测试方法:
 public void testAssigneeAssignment() {
//启动流程
    runtimeService.startProcessInstanceByKey("setAssigneeInListener");
//通过任务监听器组件taskAssigneeAssignment以下方法指定了流程环节处理人为kermit,所以kermit会有一个待办任务
//public void notify(DelegateTask delegateTask) {
//    delegateTask.setAssignee("kermit");//设置任务处理人
//  }

    
assertNotNull(taskService.createTaskQuery().taskAssignee("kermit").singleResult());
    assertEquals(0, taskService.createTaskQuery().taskAssignee("fozzie").count());
    assertEquals(0, taskService.createTaskQuery().taskAssignee("gonzo").count());
  }

3.2 直接调用组件方法获取任务处理人
流程定义文件src/test/resources/org/activiti/examples/bpmn/usertask/taskassignee/TaskAssigneeTest.testTaskAssignee.bpmn20.xml相关内容:
<formalExpression>${taskAssigneeAssignment.getHandlerMan()}</formalExpression>


完整流程定义文件:
<?xml version="1.0" encoding="UTF-8"?>
<definitions id="taskAssigneeExample" 
  xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL"
  xmlns:activiti="http://activiti.org/bpmn"
  targetNamespace="Examples">
  
  <process id="taskAssigneeExampleProcess" name="Schedule meeting reminder">
  
    <startEvent id="theStart" />
    
    <sequenceFlow id="flow1" sourceRef="theStart" targetRef="theTask" />

    <userTask id="theTask" name="Schedule meeting" >
      <documentation>
        Schedule an engineering meeting for next week with the new hire.
      </documentation>
      <humanPerformer>
        <resourceAssignmentExpression>
<!--           <formalExpression>kermit</formalExpression> -->
 <formalExpression>${taskAssigneeAssignment.getHandlerMan()}</formalExpression>
        </resourceAssignmentExpression>
      </humanPerformer>
    </userTask>
    
    <sequenceFlow id="flow2" sourceRef="theTask" targetRef="theEnd" />
    
    <endEvent id="theEnd" />
    
  </process>

</definitions>

流程执行:
测试用例src/test/java/org/activiti/examples/bpmn/usertask/taskassignee/TaskAssigneeTest.java

测试方法:
 public void testTaskAssignee() throws Throwable{    
    
    // Start process instance
	TransactionManager tm = new TransactionManager();
	try {
		tm.begin();//start bboss transaction
	    ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("taskAssigneeExampleProcess");
	    
	    // Get task list
//流程中通过${taskAssigneeAssignment.getHandlerMan()}表达式调用组件方法指定了kermit为任务处理人
	    List<Task> tasks = taskService
	      .createTaskQuery()
	      .taskAssignee("kermit")
	      .list();
	    assertEquals(1, tasks.size());
	    Task myTask = tasks.get(0);
	    assertEquals("Schedule meeting", myTask.getName());
	    assertEquals("Schedule an engineering meeting for next week with the new hire.", myTask.getDescription());
	
	    // Complete task. Process is now finished
	    taskService.complete(myTask.getId());
	    // assert if the process instance completed
	    assertProcessEnded(processInstance.getId());
            //do some bussiness 
            startmeeting();
	    tm.commit();//commit bboss transaction

	} catch (Throwable e) {
		throw e;
	}
        finally
        {
            tm.release();
        }  

  }

测试方法中我们将业务处理和流程的处理包含在bboss的事务上下文件,如果工作流中包含了监听器的执行,那么监听器中的业务处理也会受事务的控制。

4.activiti和bboss整合相关资源说明
本节说明bboss和activiti整合时,需要用到bboss和activiti的哪些jar包、运行时依赖的jar包以及相关配置文件,见下表:

img_8e6e5b75e9c2d2210bf77eb4a4d8e798.jpe

5.activiti-bboss eclipse demo工程
为了更好地方便大家使用activiti-bboss的整合版本,特意整理了一个demo工程,工程下载地址:
http://www.bbossgroups.com/file/download.htm?fileName=activiti-bboss-example.zip

工程里面已经根据上文方法做好相关配置
activiti.cfg.xml
beans.xml
poolman.xml

下载解压后将其导入eclipse,修改poolman.xml中的数据库连接地址和账号即可运行demo工程中的测试用例:
/activiti-bboss-example/src/org/frameworkset/activiti/test/SimpleActivitTest.java
用例方法为:
@Test
	public void runBare() throws Throwable {

		initializeProcessEngine();// 初始化流程引擎,默认加载activiti.cfg.xml文件

		initializeServices();// 初始化流程相关服务

		initusers();// 初始化测试用户

		String deploymentId = null;

		try {

			deploymentId = annotationDeploymentSetUp(processEngine);// 部署测试流程

			testAssigneeAssignment();// 执行测试用例
			testTaskAssignee();// 执行测试用例

		} catch (AssertionFailedError e) {

			throw e;

		} catch (Throwable e) {

			throw e;

		} finally {
			annotationDeploymentTearDown(processEngine, deploymentId);// 卸载流程
			deleteusers();//清除用户信息
			assertAndEnsureCleanDb();// 重置activiti数据库表
			ClockUtil.reset();
		}
	}


和本文相关的两个流程的测试方法:
testAssigneeAssignment();// 执行测试用例
testTaskAssignee();// 执行测试用例

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
4月前
|
安全 NoSQL Java
SpringBoot集成Activiti5.22在线流程设计器
SpringBoot集成Activiti5.22在线流程设计器
48 0
SpringBoot集成Activiti5.22在线流程设计器
|
1月前
|
SQL NoSQL Redis
hxyFrame-activiti-boot工作流框架 v1.0
hxyFrame-activiti-boot工作流框架 v1.0
15 0
|
2月前
|
前端开发 JavaScript Java
基于Springboot+SpringSecurity+Activiti7实现的工作流系统可方便二次开发(附完整源码)
基于Springboot+SpringSecurity+Activiti7实现的工作流系统可方便二次开发(附完整源码)
58 0
|
8月前
|
SQL Java 关系型数据库
Activiti工作流框架学习笔记(二)之springboot2.0整合工作流Activiti6.0
Activiti工作流框架学习笔记(二)之springboot2.0整合工作流Activiti6.0
131 0
|
XML 应用服务中间件 数据格式
Activiti入门操作
Activiti入门操作
|
Java 应用服务中间件 数据库
工作流框架Activiti基本介绍!Activiti Explorer流程控制台介绍和Activiti数据库安装说明
本文是对工作流框架的基本介绍,介绍了工作流流程引擎的用户控制台Activiti Explorer和Activiti的集成环境。对工作流框架Activiti安装数据库以及数据库的使用方式进行说明。介绍了工作流框架Activiti生成用户和群组,流程dingyi以及数据模型的方式等功能,以及功能的启用禁用方式。
233 0
工作流框架Activiti基本介绍!Activiti Explorer流程控制台介绍和Activiti数据库安装说明
|
XML 缓存 Java
工作流引擎使用详解!工作流框架Activiti的详细配置以及安装和使用
本文极尽详细地阐述了工作流框架Activiti的详细配置以及安装和使用的相关注意点。从工作流Activiti框架的创建Activiti流程引擎ProcessEngine开始讲起,一直到数据库配置,部署以及工作流中的事件处理。通过这篇文章,基本上可以完全掌握工作流的基本搭建和基本使用原理,为后面项目中集成使用工作流框架Activiti进一步深化学习。
732 0
工作流引擎使用详解!工作流框架Activiti的详细配置以及安装和使用
|
Oracle 关系型数据库 Java
springboot 集成 activiti 流程引擎
springboot 集成 activiti 流程引擎
249 0
|
存储 Java API
SpringBoot - 工作流Activiti开发
1.工作流 1.1 开发前奏 介绍 当前系统activit开发以springboot+mybatis开发为准, 1.1.1 IDEA安装actiBPM 通过File -> Settings -> Plugins 找到actiBPM插件进行安装 1.1.2 核心API介绍 ProcessEngineConfiguration:流程引擎配置。
10356 0