项目使用SpringBoot + activiti6.0,使用multi databases scheme方式实现saas多租户。
在@configuration类中使用MultiSchemaMultiTenantProcessEngineConfiguration创建activiti process engine configuration
@bean
,然后异步执行使用SharedExecutorServiceAsyncExecutor类。
MultiSchemaMultiTenantProcessEngineConfigurationImpl engineConfig = new MultiSchemaMultiTenantProcessEngineConfigurationImpl(holder);
engineConfig.setAsyncExecutorActivate(true);
engineConfig.setAsyncExecutor(new SharedExecutorServiceAsyncExecutor(holder));
engineConfig.setDatabaseType(MultiSchemaMultiTenantProcessEngineConfiguration.DATABASE_TYPE_POSTGRES);
engineConfig.setDatabaseSchemaUpdate(MultiSchemaMultiTenantProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE);
然而,流程上的超时怎么也无法触发。
-----------------------
阅读了activiti源代码,发现activiti的acquireTimersJobs线程先会从act_ru_timers表中获取到即将执行的timers,然后将timers添加到act_ru_jobs表中,再由acquireAsyncJobs线程获取异步任务并触发任务。然而在执行触发前,DefaultJobManager都会询问process engine configuration上的asyncExecutor是否为active,而SharedExecutorServiceAsyncExecutor的active属性一直是false,也就无法触发任务了。
Class DefaultJobManager{
protected boolean isAsyncExecutorActive() {
return processEngineConfiguration.getAsyncExecutor().isActive();
源代码中SharedExecutorServiceAsyncExecutor的start()中,不会将active设置为true。
@Override
public void start() {
for (String tenantId : timerJobAcquisitionRunnables.keySet()) {
startTimerJobAcquisitionForTenant(tenantId);
startAsyncJobAcquisitionForTenant(tenantId);
startResetExpiredJobsForTenant(tenantId);
而父类DefaultAsyncJobExecutor的start方法,在启动后会将isActive属性设置为true。
public void start() {
if (isActive) {
return;
log.info("Starting up the default async job executor [{}].", getClass().getName());
if (timerJobRunnable == null) {
timerJobRunnable = new AcquireTimerJobsRunnable(this, processEngineConfiguration.getJobManager());
if (resetExpiredJobsRunnable == null) {
resetExpiredJobsRunnable = new ResetExpiredJobsRunnable(this);
if (!isMessageQueueMode && asyncJobsDueRunnable == null) {
asyncJobsDueRunnable = new AcquireAsyncJobsDueRunnable(this);
if (!isMessageQueueMode) {
initAsyncJobExecutionThreadPool();
startJobAcquisitionThread();
startTimerAcquisitionThread();
startResetExpiredJobsThread();
isActive = true;
executeTemporaryJobs();
是SharedExecutorServiceAsyncExecutor的bug吗?还是需要额外设置active?
--------
调研了好久也没找到方法,但找到activiti还提供另外一种DefaultAsyncJobExecutor的实现-ExecutorPerTenantAsyncExecutor。而它的start()方法中很明显将active设置为true了。
public class ExecutorPerTenantAsyncExecutor implements TenantAwareAsyncExecutor {
public void start() {
for (AsyncExecutor asyncExecutor : tenantExecutors.values()) {
asyncExecutor.start();
active = true;
.....
于是直接修改@configuration代码一试,流程定义上的timers触发了。
@Bean
public MultiSchemaMultiTenantProcessEngineConfiguration processEngineConfiguration(
TenantInfoHolder holder) throws Exception {
MultiSchemaMultiTenantProcessEngineConfigurationImpl engineConfig = new MultiSchemaMultiTenantProcessEngineConfigurationImpl(holder);
engineConfig.setAsyncExecutorActivate(true);
engineConfig.setAsyncExecutor(new ExecutorPerTenantAsyncExecutor(holder));
engineConfig.setDatabaseType(MultiSchemaMultiTenantProcessEngineConfiguration.DATABASE_TYPE_POSTGRES);
engineConfig.setDatabaseSchemaUpdate(MultiSchemaMultiTenantProcessEngineConfiguration.DB_SCHEMA_UPDATE_FALSE);
return engineConfig;
----------
后话:关于activiti6.0实现multi tenant的网上资源不多,希望碰到类似问题的同学可以快速解决问题。
如果哪位老师知道SharedExecutorServiceAsyncExecutor的使用方法,希望可以回帖分享。
转载于:https://my.oschina.net/u/3706162/blog/1785664
原文链接:https://my.oschina.net/u/3706162/blog/1785664
<div class="intro-course"><span style="color: #0000cd;"><strong><span style="font-size: 36px;">Activiti是一个项目的名称,Alfresco软件在2010年5月17日宣布Activiti业务流程管理(BPM)开源项目的正式启动,其首席架构师由业务流程管理BPM的专家 Tom Baeyens担任。</span></strong></span></div>
<div class="intro-course"><span style="color: #0000cd;"><strong><span style="font-size: 36px;"><img src="https://img-bss.csdnimg.cn/202107271208211267.jpg" alt="" width="660" height="226" /></span></strong></span></div>
<div class="intro-course"><span style="color: #0000cd;"><strong><span style="font-size: 36px;">本套课程为Activiti基于SpringBoot下的教程</span></strong></span> <br /><span style="font-size: 24px;"><strong><span title="01、Activiti简介.mp4"><span class="text-with-highlight">1、Activiti简介<br />2、</span></span> <span title="02、Activiti安装eclipse插件.mp4"><span class="text-with-highlight">Activiti安装eclipse插件<br />3、</span></span> <span title="03、Activiti部署流程.mp4"><span class="text-with-highlight">Activiti部署流程<br />4、</span></span> <span title="04、Activiti启动流程实例.mp4"><span class="text-with-highlight">Activiti启动流程实例<br />5、</span></span> <span title="05、Activiti执行任务.mp4"><span class="text-with-highlight">Activiti执行任务<br />6、</span></span> <span title="06、Activiti操作流程定义.mp4"><span class="text-with-highlight">Activiti操作流程定义<br />7、</span></span> <span title="07、Activiti删除任务、流程定义.mp4"><span class="text-with-highlight">Activiti删除任务、流程定义<br />8、</span></span> <span title="08、Activiti查看流程图.mp4"><span class="text-with-highlight">Activiti查看流程图<br />9、</span></span> <span title="09、Activiti查看历史流程实例.mp4"><span class="text-with-highlight">Activiti查看历史流程实例<br />10、</span></span> <span title="10、Activiti查看流程实例状态.mp4"><span class="text-with-highlight">Activiti查看流程实例状态<br />11、</span></span> <span title="11、Activiti设置获取变量.mp4"><span class="text-with-highlight">Activiti设置获取变量<br />12、</span></span> <span title="12、Activiti查询历史数据.mp4"><span class="text-with-highlight">Activiti查询历史数据<br />13、</span></span> <span title="13、Activiti排他网关.mp4"><span class="text-with-highlight">Activiti排他网关<br />14、</span></span> <span title="14、Activiti并行网关.mp4"><span class="text-with-highlight">Activiti并行网关<br />15、</span></span> <span title="15、Activiti流程实例.mp4"><span class="text-with-highlight">Activiti流程实例<br />16、</span></span> <span title="16、Activiti获取执行对象.mp4"><span class="text-with-highlight">Activiti获取执行对象<br />17、</span></span> <span title="17、Activiti动态设置任务处理人.mp4"><span class="text-with-highlight">Activiti动态设置任务处理人<br />18、</span></span> <span title="18、Activiti任务认领、转发.mp4"><span class="text-with-highlight">Activiti任务认领、转发<br />19、</span></span> <span title="19、Activiti创建角色、用户.mp4"><span class="text-with-highlight">Activiti创建角色、用户<br />20、</span></span> <span title="20、Activiti任务拾取、回退.mp4"><span class="text-with-highlight">Activiti任务拾取、回退</span></span></strong></span></div>
我们过去听到的一项功能请求是以多租户方式运行Activiti引擎,使租户的数据与其他租户的数据隔离。 当然,在某些云/ SaaS环境中,这是必须的。
几个月前,波恩大学的学生拉斐尔·吉伦(Raphael Gielen)与我接触,他正在撰写有关Activiti中多租户的硕士论文。 几周前,我们在一个共同工作的咖啡馆聚会,反弹想法,并为租户一起破解了具有数据库模式隔离的第一个原型。 很有趣 ...
好了,本文主要对ProcessEngine构建过程中的数据库配置以及启动过程中的源码进行了一个简单的解读。接下来的下文中,将会对Flowable的ProcessEngine中,一个ProcessEngine构建的真的流程,完整的给大家解读一番。更多精彩,尽在码农修炼笔记!
Activiti租户也就是TENANT_ID_(tenantId)。该值主要用于记录启动的流程实例归属于哪个系统,比如a,b,c三个系统都有一个请假流程并且数据存储在同一个数据库,这个时候就应该考虑如何区分这三个流程了。
本文会详细讲解新的组合架构功能,洒上一些真实工作代码示例 !
1.1 多租户共享数据库
Activiti5.15版本中增加了多租户的概念,该功能主要用于数据共享在一个数据...
事件等简介摘抄自官方文档
*后台服务基于Springboot2 + Activiti6,整合文章请参考:https://blog.csdn.net/yy756127197/article/details/101211510 不需要流程设计器就排除3,4步骤 *
1. 定时...
边界事件:边界事件属于一种特殊的中间事件。区别是: 中间事件 可以单独作为流程元素存在于流程中,而 边界事件 必须附属于某个流程元素(如任务、子流程等)。边界事件是Catching事件。
二、定时器边界事件
说明:定时器边界事件会在定时器时间到了之后进行触发,需要开启异步执行器(在activiti.cfg.xml中)。此处模拟一个损坏的物品首先交给初级工程师修理,定时1分钟后没有修好就...
自学了一段时间的activiti,发现网上有很多的demo都用不起。找了很多,都比较失望。所以今天自己写一个简单的基于springboot的activiti项目。
ok,开始
首先,我们需要先创建一个springboot项目。下面这个pom依赖。
<dependency>
<groupId>org.springframework.boot</group...
背景:项目中用到工作流,其中有一个需求是,市民通过公众号上报事件,然后流程往下走,最后会回到上报人手中,但是由于是公众号,上报人可能上报之后就不关心之后怎么样了;到最后会影响报表的数据;
现在这个需求需要改成,当案件回到上报人之后,如果上报人在三天之内没有处理这个案件,系统就把这个案件自动结束;
测试案例:
a) 张三提交请假单
b) 经理审批请假单。流程回到张三手中
c) 张三审批流程;如果超时则自动审批
更新配置文件
如果是SSM项目,配置文件中添加
<property name="job.
初步学习其流程引擎及配置
国内外开源工作流众多,Activiti是其中较为出众的一款,它由jbpm发展而来,最新版本已发展到Activiti7,它的设计遵循bpmn规范并进行了扩展,服务层使用java开发,有web及IDE端的流程设计器,持久层框架采用mybatis,支持多种数据库类型(如oracle、mysql、postgreSQL等等)。
流程引擎配置类的类图如下:
EngineServices中定义了获取各种服务类实例对象的方法
ProcessEngine继承了EngineServices
EngineServices:定义各种服务类实例对象方法,下面会详细说明。
ProcessEngine:继承EngineServices接口,并增加了对流程引擎名称的获取以及关闭流程引擎的支持。
ProcessEngineImpl:对ProcessEngine接口的实现。
ProcessEngines:负责管理所有流程引擎ProcessEngine集合,并负责流程引擎实例对象的注册、获取、注销等操作