前言
在十年前刚开始接触工作流引擎的时候,所知道的就只有Activiti,根本不知道还有没有其他工作流引擎,虽然中文手册和教程十分欠缺,但经过不断摸索,用得越来越顺,也一直用得好好的。最近在搭建一个工作流服务平台,找了很多前端画流程的开源框架,一直没找到Activiti专属的画图框架,后来找到了bpmn-js,但是发现画出来的流程在Activiti上跑不了,查了下才发现所使用的面板插件是Camunda专属的,其实连bpmn-js都是Camunda社区所开发的。顿时对Camunda产生的兴趣,在网上看了很多Camunda、Flowable、Activiti对比的文章,发现现在Camunda的社区是最活跃的,抱着尝试一下的想法,在项目上拉了个分支,开始了Camunda迁移工作。
为什么是Camunda7.8?
当前最新的版本其实是Camunda7.11,功能已经做得非常完善了,可以在maven库中找了官方的rest接口库、webapp库,再配合bpmn-js,根本不用怎么写代码就可以实现工作流管理。但是项目部署后根本启动不了,才知道跟springboot版本不兼容,我用的是springboot1.5.9,而camunda7.8以上版本都是基于springboot2.0的,所以只能使用7.8版本。
贴一下我的pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.jia</groupId>
<artifactId>jia-api-admin</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>jia-api-admin</name>
<description>Jia服务平台管理后台</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.9.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Edgware.SR3</spring-cloud.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<!--<dependency>
<groupId>org.activiti</groupId>
<artifactId>activiti-spring-boot-starter-basic</artifactId>
<version>6.0.0</version>
</dependency>-->
<dependency>
<groupId>org.camunda.bpm.springboot</groupId>
<artifactId>camunda-bpm-spring-boot-starter</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<!--<scope>provided</scope>-->
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- json工具类 -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
</dependency>
</dependencies>
<distributionManagement>
<snapshotRepository>
<id>nexus-snapshots</id>
<url>http://maven.wydiy.com/repository/maven-snapshots/</url>
</snapshotRepository>
<repository>
<id>nexus-releases</id>
<url>http://maven.wydiy.com/repository/maven-releases/</url>
</repository>
</distributionManagement>
<build>
<finalName>jia-api-admin</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</project>
数据库迁移
其实网上已经有迁移的教程,Camunda官网也提供的迁移的方法和脚本,但是那个是从Activiti5.21迁移到Camunda7.5,只能一边尝试一边解决版本问题。首先是数据库的迁移,如果是全新的项目,那什么都不用管,项目启动时就会自动新建表,但我原来使用的是Activiti6.0,已经有业务数据了,只能无缝迁移,还好Camunda是从Activiti分出来了,保留了Activiti的大部分表,结构也很相似,并且Camunda在github上也放了迁移脚本。我找到mysql的脚本,发现mysql的脚本居然有语法错误,只好自己修复一下,同时把脚本push都github上,本来没想过作者会留意,因为最后一次更新已经是三年前了,谁想作者竟然亲自问我push的理由,我说明理由后,把我的脚本merge到master上,真的是惊喜,作者也是一个很负责任的人。但是,那样还不够,7.8版本跟7.5版本还是有不少区别,没办法,只能拿我的库和7.8的初始化库一项一项地对比,整理出最新的脚本。
create table ACT_RU_INCIDENT (
ID_ varchar(64) not null,
INCIDENT_TIMESTAMP_ timestamp not null,
INCIDENT_MSG_ varchar(4000),
INCIDENT_TYPE_ varchar(255) not null,
EXECUTION_ID_ varchar(64),
ACTIVITY_ID_ varchar(255),
PROC_INST_ID_ varchar(64),
PROC_DEF_ID_ varchar(64),
CAUSE_INCIDENT_ID_ varchar(64),
ROOT_CAUSE_INCIDENT_ID_ varchar(64),
CONFIGURATION_ varchar(255),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
create index ACT_IDX_INC_CONFIGURATION on ACT_RU_INCIDENT(CONFIGURATION_);
alter table ACT_RU_INCIDENT
add constraint ACT_FK_INC_EXE
foreign key (EXECUTION_ID_)
references ACT_RU_EXECUTION (ID_);
alter table ACT_RU_INCIDENT
add constraint ACT_FK_INC_PROCINST
foreign key (PROC_INST_ID_)
references ACT_RU_EXECUTION (ID_);
alter table ACT_RU_INCIDENT
add constraint ACT_FK_INC_PROCDEF
foreign key (PROC_DEF_ID_)
references ACT_RE_PROCDEF (ID_);
alter table ACT_RU_INCIDENT
add constraint ACT_FK_INC_CAUSE
foreign key (CAUSE_INCIDENT_ID_)
references ACT_RU_INCIDENT (ID_) on delete cascade on update cascade;
alter table ACT_RU_INCIDENT
add constraint ACT_FK_INC_RCAUSE
foreign key (ROOT_CAUSE_INCIDENT_ID_)
references ACT_RU_INCIDENT (ID_) on delete cascade on update cascade;
/** add ACT_INST_ID_ column to execution table */
alter table ACT_RU_EXECUTION
add ACT_INST_ID_ nvarchar(64);
/** populate ACT_INST_ID_ from history */
/** get from history for active activity instances */
UPDATE
ACT_RU_EXECUTION E
SET
ACT_INST_ID_ = (
SELECT
MAX(ID_)
FROM
ACT_HI_ACTINST HAI
WHERE
HAI.EXECUTION_ID_ = E.ID_
AND
HAI.END_TIME_ is null
)
WHERE
E.ACT_INST_ID_ is null
AND
E.ACT_ID_ is not null;
/** remaining executions use execution id as activity instance id */
UPDATE
ACT_RU_EXECUTION
SET
ACT_INST_ID_ = ID_
WHERE
ACT_INST_ID_ is null;
/** add SUSPENSION_STATE_ column to task table */
-- alter table ACT_RU_TASK
-- add SUSPENSION_STATE_ integer;
UPDATE ACT_RU_TASK T
INNER JOIN ACT_RU_EXECUTION E
ON T.EXECUTION_ID_ = E.ID_
SET T.SUSPENSION_STATE_ = E.SUSPENSION_STATE_;
UPDATE ACT_RU_TASK
SET SUSPENSION_STATE_ = 1
WHERE SUSPENSION_STATE_ is null;
/** add authorizations **/
create table ACT_RU_AUTHORIZATION (
ID_ varchar(64) not null,
REV_ integer not null,
TYPE_ integer not null,
GROUP_ID_ varchar(255),
USER_ID_ varchar(255),
RESOURCE_TYPE_ integer not null,
RESOURCE_ID_ varchar(64),
PERMS_ integer,
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
alter table ACT_RU_AUTHORIZATION
add constraint ACT_UNIQ_AUTH_USER
unique (USER_ID_,TYPE_,RESOURCE_TYPE_,RESOURCE_ID_);
alter table ACT_RU_AUTHORIZATION
add constraint ACT_UNIQ_AUTH_GROUP
unique (GROUP_ID_,TYPE_,RESOURCE_TYPE_,RESOURCE_ID_);
/** add deployment ID to job table **/
alter table ACT_RU_JOB
add DEPLOYMENT_ID_ varchar(64);
/** add parent act inst ID */
alter table ACT_HI_ACTINST
add PARENT_ACT_INST_ID_ varchar(64);-- add new column to historic activity instance table --
alter table ACT_HI_ACTINST
add ACT_INST_STATE_ integer;
-- add follow-up date to tasks --
alter table ACT_RU_TASK
add FOLLOW_UP_DATE_ datetime;
alter table ACT_HI_TASKINST
add FOLLOW_UP_DATE_ datetime;
-- add JOBDEF table --
create table ACT_RU_JOBDEF (
ID_ varchar(64) NOT NULL,
REV_ integer,
PROC_DEF_ID_ varchar(64) NOT NULL,
PROC_DEF_KEY_ varchar(255) NOT NULL,
ACT_ID_ varchar(255) NOT NULL,
JOB_TYPE_ varchar(255) NOT NULL,
JOB_CONFIGURATION_ varchar(255),
SUSPENSION_STATE_ integer,
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- add new columns to job table --
alter table ACT_RU_JOB
add PROCESS_DEF_ID_ varchar(64);
alter table ACT_RU_JOB
add PROCESS_DEF_KEY_ varchar(64);
alter table ACT_RU_JOB
add SUSPENSION_STATE_ integer;
alter table ACT_RU_JOB
add JOB_DEF_ID_ varchar(64);
-- update job table with values from execution table --
UPDATE
ACT_RU_JOB J
SET
PROCESS_DEF_ID_ = (
SELECT
PI.PROC_DEF_ID_
FROM
ACT_RU_EXECUTION PI
WHERE
PI.ID_ = J.PROCESS_INSTANCE_ID_
),
SUSPENSION_STATE_ = (
SELECT
PI.SUSPENSION_STATE_
FROM
ACT_RU_EXECUTION PI
WHERE
PI.ID_ = J.PROCESS_INSTANCE_ID_
);
UPDATE
ACT_RU_JOB J
SET
PROCESS_DEF_KEY_ = (
SELECT
PD.KEY_
FROM
ACT_RE_PROCDEF PD
WHERE
PD.ID_ = J.PROCESS_DEF_ID_
);
-- add Hist OP Log table --
create table ACT_HI_OP_LOG (
ID_ varchar(64) not null,
PROC_DEF_ID_ varchar(64),
PROC_INST_ID_ varchar(64),
EXECUTION_ID_ varchar(64),
TASK_ID_ varchar(64),
USER_ID_ varchar(255),
TIMESTAMP_ timestamp not null,
OPERATION_TYPE_ varchar(64),
OPERATION_ID_ varchar(64),
ENTITY_TYPE_ varchar(30),
PROPERTY_ varchar(64),
ORG_VALUE_ varchar(4000),
NEW_VALUE_ varchar(4000),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- add new column to ACT_HI_VARINST --
alter table ACT_HI_VARINST
add ACT_INST_ID_ varchar(64);
alter table ACT_HI_DETAIL
add VAR_INST_ID_ varchar(64);
alter table ACT_HI_TASKINST
add ACT_INST_ID_ varchar(64);
-- set cached entity state to 63 on all executions --
UPDATE
ACT_RU_EXECUTION
SET
CACHED_ENT_STATE_ = 63;
-- add new table ACT_HI_INCIDENT --
create table ACT_HI_INCIDENT (
ID_ varchar(64) not null,
PROC_DEF_ID_ varchar(64),
PROC_INST_ID_ varchar(64),
EXECUTION_ID_ varchar(64),
CREATE_TIME_ timestamp not null,
END_TIME_ timestamp null,
INCIDENT_MSG_ varchar(4000),
INCIDENT_TYPE_ varchar(255) not null,
ACTIVITY_ID_ varchar(255),
CAUSE_INCIDENT_ID_ varchar(64),
ROOT_CAUSE_INCIDENT_ID_ varchar(64),
CONFIGURATION_ varchar(255),
INCIDENT_STATE_ integer,
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- update ACT_RU_VARIABLE table --
-- add new column --
ALTER TABLE ACT_RU_VARIABLE
add VAR_SCOPE_ varchar(64);
-- migrate execution variables --
UPDATE
ACT_RU_VARIABLE V
SET
VAR_SCOPE_ = V.EXECUTION_ID_
WHERE
V.EXECUTION_ID_ is not null AND
V.TASK_ID_ is null;
-- migrate task variables --
UPDATE
ACT_RU_VARIABLE V
SET
VAR_SCOPE_ = V.TASK_ID_
WHERE
V.TASK_ID_ is not null;
-- set VAR_SCOPE_ not null --
ALTER TABLE ACT_RU_VARIABLE
MODIFY VAR_SCOPE_ varchar(64) NOT NULL;
-- add unique constraint --
ALTER TABLE ACT_RU_VARIABLE
ADD CONSTRAINT ACT_UNIQ_VARIABLE
UNIQUE (VAR_SCOPE_, NAME_);
-- indexes for deadlock problems - https://app.camunda.com/jira/browse/CAM-2567 --
create index ACT_IDX_INC_CAUSEINCID on ACT_RU_INCIDENT(CAUSE_INCIDENT_ID_);
create index ACT_IDX_INC_EXID on ACT_RU_INCIDENT(EXECUTION_ID_);
create index ACT_IDX_INC_PROCDEFID on ACT_RU_INCIDENT(PROC_DEF_ID_);
create index ACT_IDX_INC_PROCINSTID on ACT_RU_INCIDENT(PROC_INST_ID_);
create index ACT_IDX_INC_ROOTCAUSEINCID on ACT_RU_INCIDENT(ROOT_CAUSE_INCIDENT_ID_);-- add deployment.lock row to property table --
INSERT INTO ACT_GE_PROPERTY
VALUES ('deployment.lock', '0', 1);
-- add revision column to incident table --
ALTER TABLE ACT_RU_INCIDENT
ADD REV_ INTEGER;
-- set initial incident revision to 1 --
UPDATE
ACT_RU_INCIDENT
SET
REV_ = 1;
-- set incident revision column to not null --
ALTER TABLE ACT_RU_INCIDENT
MODIFY REV_ INTEGER NOT NULL;
-- case management
ALTER TABLE ACT_RU_VARIABLE
ADD CASE_EXECUTION_ID_ varchar(64);
ALTER TABLE ACT_RU_VARIABLE
ADD CASE_INST_ID_ varchar(64);
ALTER TABLE ACT_RU_TASK
ADD CASE_EXECUTION_ID_ varchar(64);
ALTER TABLE ACT_RU_TASK
ADD CASE_INST_ID_ varchar(64);
ALTER TABLE ACT_RU_TASK
ADD CASE_DEF_ID_ varchar(64);
ALTER TABLE ACT_RU_EXECUTION
ADD SUPER_CASE_EXEC_ varchar(64);
ALTER TABLE ACT_RU_EXECUTION
ADD CASE_INST_ID_ varchar(64);
ALTER TABLE ACT_HI_OP_LOG
ADD CASE_EXECUTION_ID_ varchar(64);
ALTER TABLE ACT_HI_OP_LOG
ADD CASE_INST_ID_ varchar(64);
ALTER TABLE ACT_HI_OP_LOG
ADD CASE_DEF_ID_ varchar(64);
ALTER TABLE ACT_HI_OP_LOG
ADD PROC_DEF_KEY_ varchar(255);
ALTER TABLE ACT_HI_PROCINST
ADD CASE_INST_ID_ varchar(64);
ALTER TABLE ACT_HI_TASKINST
ADD CASE_EXECUTION_ID_ varchar(64);
ALTER TABLE ACT_HI_TASKINST
ADD CASE_INST_ID_ varchar(64);
ALTER TABLE ACT_HI_TASKINST
ADD CASE_DEF_ID_ varchar(64);
-- create case definition table --
create table ACT_RE_CASE_DEF (
ID_ varchar(64) not null,
REV_ integer,
CATEGORY_ varchar(255),
NAME_ varchar(255),
KEY_ varchar(255) not null,
VERSION_ integer not null,
DEPLOYMENT_ID_ varchar(64),
RESOURCE_NAME_ varchar(4000),
DGRM_RESOURCE_NAME_ varchar(4000),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- create case execution table --
create table ACT_RU_CASE_EXECUTION (
ID_ varchar(64) NOT NULL,
REV_ integer,
CASE_INST_ID_ varchar(64),
SUPER_CASE_EXEC_ varchar(64),
BUSINESS_KEY_ varchar(255),
PARENT_ID_ varchar(64),
CASE_DEF_ID_ varchar(64),
ACT_ID_ varchar(255),
PREV_STATE_ integer,
CURRENT_STATE_ integer,
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- create case sentry part table --
create table ACT_RU_CASE_SENTRY_PART (
ID_ varchar(64) NOT NULL,
REV_ integer,
CASE_INST_ID_ varchar(64),
CASE_EXEC_ID_ varchar(64),
SENTRY_ID_ varchar(255),
TYPE_ varchar(255),
SOURCE_CASE_EXEC_ID_ varchar(64),
STANDARD_EVENT_ varchar(255),
SATISFIED_ boolean,
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- create unique constraint on ACT_RE_CASE_DEF --
alter table ACT_RE_CASE_DEF
add constraint ACT_UNIQ_CASE_DEF
unique (KEY_,VERSION_);
-- create index on business key --
create index ACT_IDX_CASE_EXEC_BUSKEY on ACT_RU_CASE_EXECUTION(BUSINESS_KEY_);
-- create foreign key constraints on ACT_RU_CASE_EXECUTION --
alter table ACT_RU_CASE_EXECUTION
add constraint ACT_FK_CASE_EXE_CASE_INST
foreign key (CASE_INST_ID_)
references ACT_RU_CASE_EXECUTION(ID_) on delete cascade on update cascade;
alter table ACT_RU_CASE_EXECUTION
add constraint ACT_FK_CASE_EXE_PARENT
foreign key (PARENT_ID_)
references ACT_RU_CASE_EXECUTION(ID_);
alter table ACT_RU_CASE_EXECUTION
add constraint ACT_FK_CASE_EXE_CASE_DEF
foreign key (CASE_DEF_ID_)
references ACT_RE_CASE_DEF(ID_);
-- create foreign key constraints on ACT_RU_VARIABLE --
alter table ACT_RU_VARIABLE
add constraint ACT_FK_VAR_CASE_EXE
foreign key (CASE_EXECUTION_ID_)
references ACT_RU_CASE_EXECUTION(ID_);
alter table ACT_RU_VARIABLE
add constraint ACT_FK_VAR_CASE_INST
foreign key (CASE_INST_ID_)
references ACT_RU_CASE_EXECUTION(ID_);
-- create foreign key constraints on ACT_RU_TASK --
alter table ACT_RU_TASK
add constraint ACT_FK_TASK_CASE_EXE
foreign key (CASE_EXECUTION_ID_)
references ACT_RU_CASE_EXECUTION(ID_);
alter table ACT_RU_TASK
add constraint ACT_FK_TASK_CASE_DEF
foreign key (CASE_DEF_ID_)
references ACT_RE_CASE_DEF(ID_);
-- create foreign key constraints on ACT_RU_CASE_SENTRY_PART --
alter table ACT_RU_CASE_SENTRY_PART
add constraint ACT_FK_CASE_SENTRY_CASE_INST
foreign key (CASE_INST_ID_)
references ACT_RU_CASE_EXECUTION(ID_);
alter table ACT_RU_CASE_SENTRY_PART
add constraint ACT_FK_CASE_SENTRY_CASE_EXEC
foreign key (CASE_EXEC_ID_)
references ACT_RU_CASE_EXECUTION(ID_);
-- create filter table
create table ACT_RU_FILTER (
ID_ varchar(64) not null,
REV_ integer not null,
RESOURCE_TYPE_ varchar(255) not null,
NAME_ varchar(255) not null,
OWNER_ varchar(255),
QUERY_ LONGTEXT not null,
PROPERTIES_ LONGTEXT,
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- add index to improve job executor performance
create index ACT_IDX_JOB_PROCINST on ACT_RU_JOB(PROCESS_INSTANCE_ID_);
-- create historic case instance/activity table and indexes --
create table ACT_HI_CASEINST (
ID_ varchar(64) not null,
CASE_INST_ID_ varchar(64) not null,
BUSINESS_KEY_ varchar(255),
CASE_DEF_ID_ varchar(64) not null,
CREATE_TIME_ datetime not null,
CLOSE_TIME_ datetime,
DURATION_ bigint,
STATE_ integer,
CREATE_USER_ID_ varchar(255),
SUPER_CASE_INSTANCE_ID_ varchar(64),
primary key (ID_),
unique (CASE_INST_ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
create table ACT_HI_CASEACTINST (
ID_ varchar(64) not null,
PARENT_ACT_INST_ID_ varchar(64),
CASE_DEF_ID_ varchar(64) not null,
CASE_INST_ID_ varchar(64) not null,
CASE_ACT_ID_ varchar(255) not null,
TASK_ID_ varchar(64),
CALL_PROC_INST_ID_ varchar(64),
CALL_CASE_INST_ID_ varchar(64),
CASE_ACT_NAME_ varchar(255),
CASE_ACT_TYPE_ varchar(255),
CREATE_TIME_ datetime not null,
END_TIME_ datetime,
DURATION_ bigint,
STATE_ integer,
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
create index ACT_IDX_HI_CAS_I_CLOSE on ACT_HI_CASEINST(CLOSE_TIME_);
create index ACT_IDX_HI_CAS_I_BUSKEY on ACT_HI_CASEINST(BUSINESS_KEY_);
create index ACT_IDX_HI_CAS_A_I_CREATE on ACT_HI_CASEACTINST(CREATE_TIME_);
create index ACT_IDX_HI_CAS_A_I_END on ACT_HI_CASEACTINST(END_TIME_);
create index ACT_IDX_HI_CAS_A_I_COMP on ACT_HI_CASEACTINST(CASE_ACT_ID_, END_TIME_, ID_);
create index ACT_IDX_HI_CAS_A_I_CASEINST on ACT_HI_CASEACTINST(CASE_INST_ID_, CASE_ACT_ID_);
create index ACT_IDX_TASK_ASSIGNEE on ACT_RU_TASK(ASSIGNEE_);
-- add case instance/execution to historic variable instance and detail --
alter table ACT_HI_VARINST
add CASE_INST_ID_ varchar(64);
alter table ACT_HI_VARINST
add CASE_EXECUTION_ID_ varchar(64);
alter table ACT_HI_DETAIL
add CASE_INST_ID_ varchar(64);
alter table ACT_HI_DETAIL
add CASE_EXECUTION_ID_ varchar(64);
create index ACT_IDX_HI_DETAIL_CASE_INST on ACT_HI_DETAIL(CASE_INST_ID_);
create index ACT_IDX_HI_DETAIL_CASE_EXEC on ACT_HI_DETAIL(CASE_EXECUTION_ID_);
create index ACT_IDX_HI_CASEVAR_CASE_INST on ACT_HI_VARINST(CASE_INST_ID_);
-- indexes to improve deployment
-- create index ACT_IDX_BYTEARRAY_NAME on ACT_GE_BYTEARRAY(NAME_);
-- create index ACT_IDX_DEPLOYMENT_NAME on ACT_RE_DEPLOYMENT(NAME_);
-- create index ACT_IDX_JOBDEF_PROC_DEF_ID ON ACT_RU_JOBDEF(PROC_DEF_ID_);
-- create index ACT_IDX_JOB_HANDLER_TYPE ON ACT_RU_JOB(HANDLER_TYPE_);
-- create index ACT_IDX_EVENT_SUBSCR_EVT_NAME ON ACT_RU_EVENT_SUBSCR(EVENT_NAME_);
-- create index ACT_IDX_PROCDEF_DEPLOYMENT_ID ON ACT_RE_PROCDEF(DEPLOYMENT_ID_);
-- case management --
ALTER TABLE ACT_RU_CASE_EXECUTION
ADD SUPER_EXEC_ varchar(64);
ALTER TABLE ACT_RU_CASE_EXECUTION
ADD REQUIRED_ boolean;
-- history --
ALTER TABLE ACT_HI_ACTINST
ADD CALL_CASE_INST_ID_ varchar(64);
ALTER TABLE ACT_HI_PROCINST
ADD SUPER_CASE_INSTANCE_ID_ varchar(64);
ALTER TABLE ACT_HI_CASEINST
ADD SUPER_PROCESS_INSTANCE_ID_ varchar(64);
ALTER TABLE ACT_HI_CASEACTINST
ADD REQUIRED_ boolean;
ALTER TABLE ACT_HI_OP_LOG
ADD JOB_ID_ varchar(64);
ALTER TABLE ACT_HI_OP_LOG
ADD JOB_DEF_ID_ varchar(64);
create table ACT_HI_JOB_LOG (
ID_ varchar(64) not null,
TIMESTAMP_ timestamp not null,
JOB_ID_ varchar(64) not null,
JOB_DUEDATE_ timestamp NULL,
JOB_RETRIES_ integer,
JOB_EXCEPTION_MSG_ varchar(4000),
JOB_EXCEPTION_STACK_ID_ varchar(64),
JOB_STATE_ integer,
JOB_DEF_ID_ varchar(64),
JOB_DEF_TYPE_ varchar(255),
JOB_DEF_CONFIGURATION_ varchar(255),
ACT_ID_ varchar(64),
EXECUTION_ID_ varchar(64),
PROCESS_INSTANCE_ID_ varchar(64),
PROCESS_DEF_ID_ varchar(64),
PROCESS_DEF_KEY_ varchar(255),
DEPLOYMENT_ID_ varchar(64),
SEQUENCE_COUNTER_ bigint,
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
create index ACT_IDX_HI_JOB_LOG_PROCINST on ACT_HI_JOB_LOG(PROCESS_INSTANCE_ID_);
create index ACT_IDX_HI_JOB_LOG_PROCDEF on ACT_HI_JOB_LOG(PROCESS_DEF_ID_);
-- history: add columns PROC_DEF_KEY_, PROC_DEF_ID_, CASE_DEF_KEY_, CASE_DEF_ID_ --
ALTER TABLE ACT_HI_PROCINST
ADD PROC_DEF_KEY_ varchar(255);
ALTER TABLE ACT_HI_ACTINST
ADD PROC_DEF_KEY_ varchar(255);
ALTER TABLE ACT_HI_TASKINST
ADD PROC_DEF_KEY_ varchar(255);
ALTER TABLE ACT_HI_TASKINST
ADD CASE_DEF_KEY_ varchar(255);
ALTER TABLE ACT_HI_VARINST
ADD PROC_DEF_KEY_ varchar(255);
ALTER TABLE ACT_HI_VARINST
ADD PROC_DEF_ID_ varchar(64);
ALTER TABLE ACT_HI_VARINST
ADD CASE_DEF_KEY_ varchar(255);
ALTER TABLE ACT_HI_VARINST
ADD CASE_DEF_ID_ varchar(64);
ALTER TABLE ACT_HI_DETAIL
ADD PROC_DEF_KEY_ varchar(255);
ALTER TABLE ACT_HI_DETAIL
ADD PROC_DEF_ID_ varchar(64);
ALTER TABLE ACT_HI_DETAIL
ADD CASE_DEF_KEY_ varchar(255);
ALTER TABLE ACT_HI_DETAIL
ADD CASE_DEF_ID_ varchar(64);
ALTER TABLE ACT_HI_INCIDENT
ADD PROC_DEF_KEY_ varchar(255);
-- sequence counter
ALTER TABLE ACT_RU_EXECUTION
ADD SEQUENCE_COUNTER_ bigint;
ALTER TABLE ACT_HI_ACTINST
ADD SEQUENCE_COUNTER_ bigint;
ALTER TABLE ACT_RU_VARIABLE
ADD SEQUENCE_COUNTER_ bigint;
ALTER TABLE ACT_HI_DETAIL
ADD SEQUENCE_COUNTER_ bigint;
ALTER TABLE ACT_RU_JOB
ADD SEQUENCE_COUNTER_ bigint;
-- AUTHORIZATION --
-- add grant authorizations for group camunda-admin:
INSERT INTO
ACT_RU_AUTHORIZATION (ID_, TYPE_, GROUP_ID_, RESOURCE_TYPE_, RESOURCE_ID_, PERMS_, REV_)
VALUES
('camunda-admin-grant-process-definition', 1, 'camunda-admin', 6, '*', 2147483647, 1),
('camunda-admin-grant-task', 1, 'camunda-admin', 7, '*', 2147483647, 1),
('camunda-admin-grant-process-instance', 1, 'camunda-admin', 8, '*', 2147483647, 1),
('camunda-admin-grant-deployment', 1, 'camunda-admin', 9, '*', 2147483647, 1);
-- add global grant authorizations for new authorization resources:
-- DEPLOYMENT
-- PROCESS_DEFINITION
-- PROCESS_INSTANCE
-- TASK
-- with ALL permissions
INSERT INTO
ACT_RU_AUTHORIZATION (ID_, TYPE_, USER_ID_, RESOURCE_TYPE_, RESOURCE_ID_, PERMS_, REV_)
VALUES
('global-grant-process-definition', 0, '*', 6, '*', 2147483647, 1),
('global-grant-task', 0, '*', 7, '*', 2147483647, 1),
('global-grant-process-instance', 0, '*', 8, '*', 2147483647, 1),
('global-grant-deployment', 0, '*', 9, '*', 2147483647, 1);
-- variables --
ALTER TABLE ACT_RU_VARIABLE
ADD IS_CONCURRENT_LOCAL_ TINYINT;
-- metrics --
create table ACT_RU_METER_LOG (
ID_ varchar(64) not null,
NAME_ varchar(64) not null,
VALUE_ bigint,
TIMESTAMP_ timestamp not null,
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
create index ACT_IDX_METER_LOG on ACT_RU_METER_LOG(NAME_,TIMESTAMP_);
alter table ACT_HI_JOB_LOG
modify ACT_ID_ varchar(255);
-- index for deadlock problem - https://app.camunda.com/jira/browse/CAM-4440 --
create index ACT_IDX_AUTH_RESOURCE_ID on ACT_RU_AUTHORIZATION(RESOURCE_ID_);
-- indexes to improve deployment
create index ACT_IDX_BYTEARRAY_NAME on ACT_GE_BYTEARRAY(NAME_);
create index ACT_IDX_DEPLOYMENT_NAME on ACT_RE_DEPLOYMENT(NAME_);
create index ACT_IDX_JOBDEF_PROC_DEF_ID ON ACT_RU_JOBDEF(PROC_DEF_ID_);
create index ACT_IDX_JOB_HANDLER_TYPE ON ACT_RU_JOB(HANDLER_TYPE_);
create index ACT_IDX_EVENT_SUBSCR_EVT_NAME ON ACT_RU_EVENT_SUBSCR(EVENT_NAME_);
create index ACT_IDX_PROCDEF_DEPLOYMENT_ID ON ACT_RE_PROCDEF(DEPLOYMENT_ID_);
-- INCREASE process def key column size https://app.camunda.com/jira/browse/CAM-4328 --
alter table ACT_RU_JOB
modify PROCESS_DEF_KEY_ varchar(255);-- https://app.camunda.com/jira/browse/CAM-5364 --
create index ACT_IDX_AUTH_GROUP_ID on ACT_RU_AUTHORIZATION(GROUP_ID_);
-- metrics --
ALTER TABLE ACT_RU_METER_LOG
ADD REPORTER_ varchar(255);
-- job prioritization --
ALTER TABLE ACT_RU_JOB
ADD PRIORITY_ bigint NOT NULL
DEFAULT 0;
ALTER TABLE ACT_RU_JOBDEF
ADD JOB_PRIORITY_ bigint;
ALTER TABLE ACT_HI_JOB_LOG
ADD JOB_PRIORITY_ bigint NOT NULL
DEFAULT 0;
-- create decision definition table --
create table ACT_RE_DECISION_DEF (
ID_ varchar(64) not null,
REV_ integer,
CATEGORY_ varchar(255),
NAME_ varchar(255),
KEY_ varchar(255) not null,
VERSION_ integer not null,
DEPLOYMENT_ID_ varchar(64),
RESOURCE_NAME_ varchar(4000),
DGRM_RESOURCE_NAME_ varchar(4000),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- create unique constraint on ACT_RE_DECISION_DEF --
alter table ACT_RE_DECISION_DEF
add constraint ACT_UNIQ_DECISION_DEF
unique (KEY_,VERSION_);
-- case sentry part source --
ALTER TABLE ACT_RU_CASE_SENTRY_PART
ADD SOURCE_ varchar(255);
-- create history decision instance table --
create table ACT_HI_DECINST (
ID_ varchar(64) NOT NULL,
DEC_DEF_ID_ varchar(64) NOT NULL,
DEC_DEF_KEY_ varchar(255) NOT NULL,
DEC_DEF_NAME_ varchar(255),
PROC_DEF_KEY_ varchar(255),
PROC_DEF_ID_ varchar(64),
PROC_INST_ID_ varchar(64),
CASE_DEF_KEY_ varchar(255),
CASE_DEF_ID_ varchar(64),
CASE_INST_ID_ varchar(64),
ACT_INST_ID_ varchar(64),
ACT_ID_ varchar(255),
EVAL_TIME_ datetime not null,
COLLECT_VALUE_ double,
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- create history decision input table --
create table ACT_HI_DEC_IN (
ID_ varchar(64) NOT NULL,
DEC_INST_ID_ varchar(64) NOT NULL,
CLAUSE_ID_ varchar(64) NOT NULL,
CLAUSE_NAME_ varchar(255),
VAR_TYPE_ varchar(100),
BYTEARRAY_ID_ varchar(64),
DOUBLE_ double,
LONG_ bigint,
TEXT_ varchar(4000),
TEXT2_ varchar(4000),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- create history decision output table --
create table ACT_HI_DEC_OUT (
ID_ varchar(64) NOT NULL,
DEC_INST_ID_ varchar(64) NOT NULL,
CLAUSE_ID_ varchar(64) NOT NULL,
CLAUSE_NAME_ varchar(255),
RULE_ID_ varchar(64) NOT NULL,
RULE_ORDER_ integer,
VAR_NAME_ varchar(255),
VAR_TYPE_ varchar(100),
BYTEARRAY_ID_ varchar(64),
DOUBLE_ double,
LONG_ bigint,
TEXT_ varchar(4000),
TEXT2_ varchar(4000),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- create indexes for historic decision tables
create index ACT_IDX_HI_DEC_INST_ID on ACT_HI_DECINST(DEC_DEF_ID_);
create index ACT_IDX_HI_DEC_INST_KEY on ACT_HI_DECINST(DEC_DEF_KEY_);
create index ACT_IDX_HI_DEC_INST_PI on ACT_HI_DECINST(PROC_INST_ID_);
create index ACT_IDX_HI_DEC_INST_CI on ACT_HI_DECINST(CASE_INST_ID_);
create index ACT_IDX_HI_DEC_INST_ACT on ACT_HI_DECINST(ACT_ID_);
create index ACT_IDX_HI_DEC_INST_ACT_INST on ACT_HI_DECINST(ACT_INST_ID_);
create index ACT_IDX_HI_DEC_INST_TIME on ACT_HI_DECINST(EVAL_TIME_);
create index ACT_IDX_HI_DEC_IN_INST on ACT_HI_DEC_IN(DEC_INST_ID_);
create index ACT_IDX_HI_DEC_IN_CLAUSE on ACT_HI_DEC_IN(DEC_INST_ID_, CLAUSE_ID_);
create index ACT_IDX_HI_DEC_OUT_INST on ACT_HI_DEC_OUT(DEC_INST_ID_);
create index ACT_IDX_HI_DEC_OUT_RULE on ACT_HI_DEC_OUT(RULE_ORDER_, CLAUSE_ID_);
-- add grant authorization for group camunda-admin:
INSERT INTO
ACT_RU_AUTHORIZATION (ID_, TYPE_, GROUP_ID_, RESOURCE_TYPE_, RESOURCE_ID_, PERMS_, REV_)
VALUES
('camunda-admin-grant-decision-definition', 1, 'camunda-admin', 10, '*', 2147483647, 1);
-- external tasks --
create table ACT_RU_EXT_TASK (
ID_ varchar(64) not null,
REV_ integer not null,
WORKER_ID_ varchar(255),
TOPIC_NAME_ varchar(255),
RETRIES_ integer,
ERROR_MSG_ varchar(4000),
LOCK_EXP_TIME_ timestamp NULL,
SUSPENSION_STATE_ integer,
EXECUTION_ID_ varchar(64),
PROC_INST_ID_ varchar(64),
PROC_DEF_ID_ varchar(64),
PROC_DEF_KEY_ varchar(255),
ACT_ID_ varchar(255),
ACT_INST_ID_ varchar(64),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
alter table ACT_RU_EXT_TASK
add constraint ACT_FK_EXT_TASK_EXE
foreign key (EXECUTION_ID_)
references ACT_RU_EXECUTION (ID_);
create index ACT_IDX_EXT_TASK_TOPIC on ACT_RU_EXT_TASK(TOPIC_NAME_);
-- deployment --
ALTER TABLE ACT_RE_DEPLOYMENT
ADD SOURCE_ varchar(255);
ALTER TABLE ACT_HI_OP_LOG
ADD DEPLOYMENT_ID_ varchar(64);
-- job suspension state
ALTER TABLE ACT_RU_JOB
MODIFY COLUMN SUSPENSION_STATE_ integer
DEFAULT 1;
-- relevant for jobs created in Camunda 7.0
UPDATE ACT_RU_JOB
SET SUSPENSION_STATE_ = 1
WHERE SUSPENSION_STATE_ IS NULL;
ALTER TABLE ACT_RU_JOB
MODIFY COLUMN SUSPENSION_STATE_ integer
NOT NULL DEFAULT 1;
-- index to improve historic activity instance query - https://app.camunda.com/jira/browse/CAM-5257 --
create index ACT_IDX_HI_ACT_INST_STATS on ACT_HI_ACTINST(PROC_DEF_ID_, ACT_ID_, END_TIME_, ACT_INST_STATE_);
-- index to prevent deadlock on fk constraint - https://app.camunda.com/jira/browse/CAM-5440 --
create index ACT_IDX_EXT_TASK_EXEC on ACT_RU_EXT_TASK(EXECUTION_ID_);
-- https://app.camunda.com/jira/browse/CAM-5364 --
-- create index ACT_IDX_AUTH_GROUP_ID on ACT_RU_AUTHORIZATION(GROUP_ID_);
-- INCREASE process def key column size https://app.camunda.com/jira/browse/CAM-4328 --
alter table ACT_RU_JOB
modify PROCESS_DEF_KEY_ varchar(255);-- semantic version --
ALTER TABLE ACT_RE_PROCDEF
ADD VERSION_TAG_ varchar(64);
create index ACT_IDX_PROCDEF_VER_TAG on ACT_RE_PROCDEF(VERSION_TAG_);
-- AUTHORIZATION --
-- add grant authorizations for group camunda-admin:
INSERT INTO
ACT_RU_AUTHORIZATION (ID_, TYPE_, GROUP_ID_, RESOURCE_TYPE_, RESOURCE_ID_, PERMS_, REV_)
VALUES
('camunda-admin-grant-tenant', 1, 'camunda-admin', 11, '*', 2147483647, 1),
('camunda-admin-grant-tenant-membership', 1, 'camunda-admin', 12, '*', 2147483647, 1),
('camunda-admin-grant-batch', 1, 'camunda-admin', 13, '*', 2147483647, 1);
-- tenant id --
-- ALTER TABLE ACT_RE_DEPLOYMENT
-- ADD TENANT_ID_ varchar(64);
create index ACT_IDX_DEPLOYMENT_TENANT_ID on ACT_RE_DEPLOYMENT(TENANT_ID_);
-- ALTER TABLE ACT_RE_PROCDEF
-- ADD TENANT_ID_ varchar(64);
ALTER TABLE ACT_RE_PROCDEF
DROP INDEX ACT_UNIQ_PROCDEF;
create index ACT_IDX_PROCDEF_TENANT_ID ON ACT_RE_PROCDEF(TENANT_ID_);
-- ALTER TABLE ACT_RU_EXECUTION
-- ADD TENANT_ID_ varchar(64);
create index ACT_IDX_EXEC_TENANT_ID on ACT_RU_EXECUTION(TENANT_ID_);
-- ALTER TABLE ACT_RU_TASK
-- ADD TENANT_ID_ varchar(64);
create index ACT_IDX_TASK_TENANT_ID on ACT_RU_TASK(TENANT_ID_);
ALTER TABLE ACT_RU_VARIABLE
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_VARIABLE_TENANT_ID on ACT_RU_VARIABLE(TENANT_ID_);
-- ALTER TABLE ACT_RU_EVENT_SUBSCR
-- ADD TENANT_ID_ varchar(64);
create index ACT_IDX_EVENT_SUBSCR_TENANT_ID on ACT_RU_EVENT_SUBSCR(TENANT_ID_);
-- ALTER TABLE ACT_RU_JOB
-- ADD TENANT_ID_ varchar(64);
create index ACT_IDX_JOB_TENANT_ID on ACT_RU_JOB(TENANT_ID_);
ALTER TABLE ACT_RU_JOBDEF
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_JOBDEF_TENANT_ID on ACT_RU_JOBDEF(TENANT_ID_);
ALTER TABLE ACT_RU_INCIDENT
ADD TENANT_ID_ varchar(64);
ALTER TABLE ACT_RU_IDENTITYLINK
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_INC_TENANT_ID on ACT_RU_INCIDENT(TENANT_ID_);
ALTER TABLE ACT_RU_EXT_TASK
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_EXT_TASK_TENANT_ID on ACT_RU_EXT_TASK(TENANT_ID_);
ALTER TABLE ACT_RE_DECISION_DEF
DROP INDEX ACT_UNIQ_DECISION_DEF;
ALTER TABLE ACT_RE_DECISION_DEF
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_DEC_DEF_TENANT_ID on ACT_RE_DECISION_DEF(TENANT_ID_);
ALTER TABLE ACT_RE_CASE_DEF
DROP INDEX ACT_UNIQ_CASE_DEF;
ALTER TABLE ACT_RE_CASE_DEF
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_CASE_DEF_TENANT_ID on ACT_RE_CASE_DEF(TENANT_ID_);
ALTER TABLE ACT_GE_BYTEARRAY
ADD TENANT_ID_ varchar(64);
ALTER TABLE ACT_RU_CASE_EXECUTION
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_CASE_EXEC_TENANT_ID on ACT_RU_CASE_EXECUTION(TENANT_ID_);
ALTER TABLE ACT_RU_CASE_SENTRY_PART
ADD TENANT_ID_ varchar(64);
-- user on historic decision instance --
ALTER TABLE ACT_HI_DECINST
ADD USER_ID_ varchar(255);
-- tenant id on history --
-- ALTER TABLE ACT_HI_PROCINST
-- ADD TENANT_ID_ varchar(64);
create index ACT_IDX_HI_PRO_INST_TENANT_ID on ACT_HI_PROCINST(TENANT_ID_);
-- ALTER TABLE ACT_HI_ACTINST
-- ADD TENANT_ID_ varchar(64);
create index ACT_IDX_HI_ACT_INST_TENANT_ID on ACT_HI_ACTINST(TENANT_ID_);
-- ALTER TABLE ACT_HI_TASKINST
-- ADD TENANT_ID_ varchar(64);
create index ACT_IDX_HI_TASK_INST_TENANT_ID on ACT_HI_TASKINST(TENANT_ID_);
ALTER TABLE ACT_HI_VARINST
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_HI_VAR_INST_TENANT_ID on ACT_HI_VARINST(TENANT_ID_);
ALTER TABLE ACT_HI_DETAIL
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_HI_DETAIL_TENANT_ID on ACT_HI_DETAIL(TENANT_ID_);
ALTER TABLE ACT_HI_INCIDENT
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_HI_INCIDENT_TENANT_ID on ACT_HI_INCIDENT(TENANT_ID_);
ALTER TABLE ACT_HI_JOB_LOG
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_HI_JOB_LOG_TENANT_ID on ACT_HI_JOB_LOG(TENANT_ID_);
ALTER TABLE ACT_HI_COMMENT
ADD TENANT_ID_ varchar(64);
ALTER TABLE ACT_HI_ATTACHMENT
ADD TENANT_ID_ varchar(64);
ALTER TABLE ACT_HI_OP_LOG
ADD TENANT_ID_ varchar(64);
ALTER TABLE ACT_HI_DEC_IN
ADD TENANT_ID_ varchar(64);
ALTER TABLE ACT_HI_DEC_OUT
ADD TENANT_ID_ varchar(64);
ALTER TABLE ACT_HI_DECINST
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_HI_DEC_INST_TENANT_ID on ACT_HI_DECINST(TENANT_ID_);
ALTER TABLE ACT_HI_CASEINST
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_HI_CAS_I_TENANT_ID on ACT_HI_CASEINST(TENANT_ID_);
ALTER TABLE ACT_HI_CASEACTINST
ADD TENANT_ID_ varchar(64);
create index ACT_IDX_HI_CAS_A_I_TENANT_ID on ACT_HI_CASEACTINST(TENANT_ID_);
-- add tenant table
create table ACT_ID_TENANT (
ID_ varchar(64),
REV_ integer,
NAME_ varchar(255),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
create table ACT_ID_TENANT_MEMBER (
ID_ varchar(64) not null,
TENANT_ID_ varchar(64) not null,
USER_ID_ varchar(64),
GROUP_ID_ varchar(64),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
alter table ACT_ID_TENANT_MEMBER
add constraint ACT_UNIQ_TENANT_MEMB_USER
unique (TENANT_ID_, USER_ID_);
alter table ACT_ID_TENANT_MEMBER
add constraint ACT_UNIQ_TENANT_MEMB_GROUP
unique (TENANT_ID_, GROUP_ID_);
alter table ACT_ID_TENANT_MEMBER
add constraint ACT_FK_TENANT_MEMB
foreign key (TENANT_ID_)
references ACT_ID_TENANT (ID_);
alter table ACT_ID_TENANT_MEMBER
add constraint ACT_FK_TENANT_MEMB_USER
foreign key (USER_ID_)
references ACT_ID_USER (ID_);
alter table ACT_ID_TENANT_MEMBER
add constraint ACT_FK_TENANT_MEMB_GROUP
foreign key (GROUP_ID_)
references ACT_ID_GROUP (ID_);
-- BATCH --
-- remove not null from job definition table --
alter table ACT_RU_JOBDEF
modify PROC_DEF_ID_ varchar(64),
modify PROC_DEF_KEY_ varchar(255),
modify ACT_ID_ varchar(255);
create table ACT_RU_BATCH (
ID_ varchar(64) not null,
REV_ integer not null,
TYPE_ varchar(255),
TOTAL_JOBS_ integer,
JOBS_CREATED_ integer,
JOBS_PER_SEED_ integer,
INVOCATIONS_PER_JOB_ integer,
SEED_JOB_DEF_ID_ varchar(64),
BATCH_JOB_DEF_ID_ varchar(64),
MONITOR_JOB_DEF_ID_ varchar(64),
SUSPENSION_STATE_ integer,
CONFIGURATION_ varchar(255),
TENANT_ID_ varchar(64),
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
create table ACT_HI_BATCH (
ID_ varchar(64) not null,
TYPE_ varchar(255),
TOTAL_JOBS_ integer,
JOBS_PER_SEED_ integer,
INVOCATIONS_PER_JOB_ integer,
SEED_JOB_DEF_ID_ varchar(64),
MONITOR_JOB_DEF_ID_ varchar(64),
BATCH_JOB_DEF_ID_ varchar(64),
TENANT_ID_ varchar(64),
START_TIME_ datetime not null,
END_TIME_ datetime,
primary key (ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
-- create table ACT_HI_IDENTITYLINK (
-- ID_ varchar(64) not null,
-- TIMESTAMP_ timestamp not null,
-- TYPE_ varchar(255),
-- USER_ID_ varchar(255),
-- GROUP_ID_ varchar(255),
-- TASK_ID_ varchar(64),
-- PROC_DEF_ID_ varchar(64),
-- OPERATION_TYPE_ varchar(64),
-- ASSIGNER_ID_ varchar(64),
-- PROC_DEF_KEY_ varchar(255),
-- TENANT_ID_ varchar(64),
-- primary key (ID_)
-- ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
--
-- create index ACT_IDX_HI_IDENT_LNK_USER on ACT_HI_IDENTITYLINK(USER_ID_);
create index ACT_IDX_HI_IDENT_LNK_GROUP on ACT_HI_IDENTITYLINK(GROUP_ID_);
-- create index ACT_IDX_HI_IDENT_LNK_TENANT_ID on ACT_HI_IDENTITYLINK(TENANT_ID_);
create index ACT_IDX_JOB_JOB_DEF_ID on ACT_RU_JOB(JOB_DEF_ID_);
create index ACT_IDX_HI_JOB_LOG_JOB_DEF_ID on ACT_HI_JOB_LOG(JOB_DEF_ID_);
create index ACT_IDX_BATCH_SEED_JOB_DEF ON ACT_RU_BATCH(SEED_JOB_DEF_ID_);
alter table ACT_RU_BATCH
add constraint ACT_FK_BATCH_SEED_JOB_DEF
foreign key (SEED_JOB_DEF_ID_)
references ACT_RU_JOBDEF (ID_);
create index ACT_IDX_BATCH_MONITOR_JOB_DEF ON ACT_RU_BATCH(MONITOR_JOB_DEF_ID_);
alter table ACT_RU_BATCH
add constraint ACT_FK_BATCH_MONITOR_JOB_DEF
foreign key (MONITOR_JOB_DEF_ID_)
references ACT_RU_JOBDEF (ID_);
create index ACT_IDX_BATCH_JOB_DEF ON ACT_RU_BATCH(BATCH_JOB_DEF_ID_);
alter table ACT_RU_BATCH
add constraint ACT_FK_BATCH_JOB_DEF
foreign key (BATCH_JOB_DEF_ID_)
references ACT_RU_JOBDEF (ID_);
-- TASK PRIORITY --
ALTER TABLE ACT_RU_EXT_TASK
ADD PRIORITY_ bigint NOT NULL DEFAULT 0;
create index ACT_IDX_EXT_TASK_PRIORITY ON ACT_RU_EXT_TASK(PRIORITY_);
-- HI OP PROC INDECIES --
create index ACT_IDX_HI_OP_LOG_PROCINST on ACT_HI_OP_LOG(PROC_INST_ID_);
create index ACT_IDX_HI_OP_LOG_PROCDEF on ACT_HI_OP_LOG(PROC_DEF_ID_);
-- JOB_DEF_ID_ on INCIDENTS --
ALTER TABLE ACT_RU_INCIDENT
ADD JOB_DEF_ID_ varchar(64);
create index ACT_IDX_INC_JOB_DEF on ACT_RU_INCIDENT(JOB_DEF_ID_);
alter table ACT_RU_INCIDENT
add constraint ACT_FK_INC_JOB_DEF
foreign key (JOB_DEF_ID_)
references ACT_RU_JOBDEF (ID_);
ALTER TABLE ACT_HI_INCIDENT
ADD JOB_DEF_ID_ varchar(64);
-- BATCH_ID_ on ACT_HI_OP_LOG --
ALTER TABLE ACT_HI_OP_LOG
ADD BATCH_ID_ varchar(64);
-- alter table ACT_HI_IDENTITYLINK to match Camundas version, note that some data may not be filled for old instances!
alter table ACT_HI_IDENTITYLINK add column (
ASSIGNER_ID_ varchar(64),
OPERATION_TYPE_ varchar(64),
PROC_DEF_ID_ varchar(64),
PROC_DEF_KEY_ varchar(255),
TENANT_ID_ varchar(64),
TIMESTAMP_ timestamp);
-- drop PROC_INST_ID_, -- done in drop script
create index ACT_IDX_HI_IDENT_LNK_TENANT_ID on ACT_HI_IDENTITYLINK(TENANT_ID_);
-- changes in attributes
alter table ACT_HI_ACTINST MODIFY COLUMN ASSIGNEE_ varchar(64);
alter table ACT_HI_ACTINST MODIFY COLUMN TENANT_ID_ varchar(64);
alter table ACT_HI_PROCINST MODIFY COLUMN TENANT_ID_ varchar(64);
alter table ACT_HI_TASKINST MODIFY COLUMN TENANT_ID_ varchar(64);
alter table ACT_RE_DEPLOYMENT MODIFY COLUMN TENANT_ID_ varchar(64);
alter table ACT_RE_PROCDEF MODIFY COLUMN TENANT_ID_ varchar(64);
alter table ACT_RU_EVENT_SUBSCR MODIFY COLUMN TENANT_ID_ varchar(64);
alter table ACT_RU_EXECUTION MODIFY COLUMN TENANT_ID_ varchar(64);
alter table ACT_RU_JOB MODIFY COLUMN TENANT_ID_ varchar(64);
alter table ACT_RU_TASK MODIFY COLUMN TENANT_ID_ varchar(64);
-- delete users and groups, as you have to re-create them (hashed passwords, different group types, required authorizations)
delete from ACT_ID_MEMBERSHIP;
delete from ACT_ID_TENANT_MEMBER;
delete from ACT_ID_INFO;
delete from ACT_ID_USER;
delete from ACT_ID_GROUP;
-- drop tables not used in Camunda
drop table if exists ACT_EVT_LOG cascade;
drop table if exists ACT_PROCDEF_INFO cascade;
drop table if exists ACT_RE_MODEL cascade;
-- columns not used in camunda
alter table ACT_HI_IDENTITYLINK DROP COLUMN PROC_INST_ID_;
alter table ACT_HI_TASKINST DROP COLUMN CATEGORY_;
alter table ACT_RE_DEPLOYMENT DROP COLUMN CATEGORY_;
alter table ACT_RU_TASK DROP COLUMN CATEGORY_;
alter table ACT_HI_TASKINST DROP COLUMN CLAIM_TIME_;
alter table ACT_HI_VARINST DROP COLUMN CREATE_TIME_;
alter table ACT_RE_PROCDEF DROP COLUMN DESCRIPTION_;
alter table ACT_HI_VARINST DROP COLUMN LAST_UPDATED_TIME_;
alter table ACT_RU_EXECUTION DROP COLUMN LOCK_TIME_;
alter table ACT_HI_PROCINST DROP COLUMN NAME_;
alter table ACT_RU_EXECUTION DROP COLUMN NAME_;
ALTER TABLE ACT_RU_IDENTITYLINK DROP FOREIGN KEY ACT_FK_IDL_PROCINST;
alter table ACT_RU_IDENTITYLINK DROP COLUMN PROC_INST_ID_;
alter table ACT_RU_EVENT_SUBSCR DROP COLUMN PROC_DEF_ID_;
alter table ACT_RU_JOB DROP FOREIGN KEY ACT_FK_JOB_PROC_DEF;
alter table ACT_RU_JOB DROP COLUMN PROC_DEF_ID_;
alter table ACT_HI_ATTACHMENT DROP COLUMN TIME_;
alter table ACT_HI_TASKINST DROP COLUMN FORM_KEY_;
alter table ACT_RU_TASK DROP COLUMN FORM_KEY_;
alter table ACT_RE_PROCDEF DROP COLUMN HAS_GRAPHICAL_NOTATION_;
-- drop indexes not used in Camunda
ALTER TABLE act_hi_actinst drop index ACT_IDX_HI_ACT_INST_EXEC;
ALTER TABLE act_hi_identitylink drop index ACT_IDX_HI_IDENT_LNK_TASK;
ALTER TABLE act_hi_varinst drop index ACT_IDX_HI_PROCVAR_TASK_ID;
ALTER TABLE act_hi_taskinst drop index ACT_IDX_HI_TASK_INST_PROCINST;
ALTER TABLE act_hi_actinst
DROP COLUMN DELETE_REASON_,
ADD INDEX ACT_IDX_HI_ACT_INST_COMP (ID_, EXECUTION_ID_, ACT_ID_, END_TIME_) ,
ADD INDEX ACT_IDX_HI_ACT_INST_PROC_DEF_KEY (PROC_DEF_KEY_) ;
ALTER TABLE act_hi_attachment
ADD INDEX ACT_IDX_HI_ATTACHMENT_CONTENT (CONTENT_ID_) ,
ADD INDEX ACT_IDX_HI_ATTACHMENT_PROCINST (PROC_INST_ID_) ,
ADD INDEX ACT_IDX_HI_ATTACHMENT_TASK (TASK_ID_) ;
ALTER TABLE act_hi_comment
ADD INDEX ACT_IDX_HI_COMMENT_TASK (TASK_ID_) ,
ADD INDEX ACT_IDX_HI_COMMENT_PROCINST (PROC_INST_ID_) ;
ALTER TABLE act_hi_decinst
ADD COLUMN ROOT_DEC_INST_ID_ varchar(64) NULL AFTER USER_ID_,
ADD COLUMN DEC_REQ_ID_ varchar(64) NULL AFTER ROOT_DEC_INST_ID_,
ADD COLUMN DEC_REQ_KEY_ varchar(255) NULL AFTER DEC_REQ_ID_,
ADD INDEX ACT_IDX_HI_DEC_INST_ROOT_ID (ROOT_DEC_INST_ID_) ,
ADD INDEX ACT_IDX_HI_DEC_INST_REQ_ID (DEC_REQ_ID_) ,
ADD INDEX ACT_IDX_HI_DEC_INST_REQ_KEY (DEC_REQ_KEY_) ;
ALTER TABLE act_hi_detail
ADD COLUMN OPERATION_ID_ varchar(64) NULL AFTER TENANT_ID_,
ADD INDEX ACT_IDX_HI_DETAIL_PROC_DEF_KEY (PROC_DEF_KEY_) ,
ADD INDEX ACT_IDX_HI_DETAIL_BYTEAR (BYTEARRAY_ID_) ;
CREATE TABLE act_hi_ext_task_log (
ID_ varchar(64) COLLATE utf8_bin NOT NULL,
TIMESTAMP_ timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
EXT_TASK_ID_ varchar(64) COLLATE utf8_bin NOT NULL,
RETRIES_ int(11) DEFAULT NULL,
TOPIC_NAME_ varchar(255) COLLATE utf8_bin DEFAULT NULL,
WORKER_ID_ varchar(255) COLLATE utf8_bin DEFAULT NULL,
PRIORITY_ bigint(20) NOT NULL DEFAULT '0',
ERROR_MSG_ varchar(4000) COLLATE utf8_bin DEFAULT NULL,
ERROR_DETAILS_ID_ varchar(64) COLLATE utf8_bin DEFAULT NULL,
ACT_ID_ varchar(255) COLLATE utf8_bin DEFAULT NULL,
ACT_INST_ID_ varchar(64) COLLATE utf8_bin DEFAULT NULL,
EXECUTION_ID_ varchar(64) COLLATE utf8_bin DEFAULT NULL,
PROC_INST_ID_ varchar(64) COLLATE utf8_bin DEFAULT NULL,
PROC_DEF_ID_ varchar(64) COLLATE utf8_bin DEFAULT NULL,
PROC_DEF_KEY_ varchar(255) COLLATE utf8_bin DEFAULT NULL,
TENANT_ID_ varchar(64) COLLATE utf8_bin DEFAULT NULL,
STATE_ int(11) DEFAULT NULL,
REV_ int(11) DEFAULT NULL,
PRIMARY KEY (ID_),
KEY ACT_HI_EXT_TASK_LOG_PROCINST (PROC_INST_ID_),
KEY ACT_HI_EXT_TASK_LOG_PROCDEF (PROC_DEF_ID_),
KEY ACT_HI_EXT_TASK_LOG_PROC_DEF_KEY (PROC_DEF_KEY_),
KEY ACT_HI_EXT_TASK_LOG_TENANT_ID (TENANT_ID_),
KEY ACT_IDX_HI_EXTTASKLOG_ERRORDET (ERROR_DETAILS_ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
ALTER TABLE act_hi_identitylink
ADD INDEX ACT_IDX_HI_IDENT_LNK_PROC_DEF_KEY (PROC_DEF_KEY_) ,
ADD INDEX ACT_IDX_HI_IDENT_LINK_TASK (TASK_ID_) ;
ALTER TABLE act_hi_incident
ADD INDEX ACT_IDX_HI_INCIDENT_PROC_DEF_KEY (PROC_DEF_KEY_) ,
ADD INDEX ACT_IDX_HI_INCIDENT_PROCINST (PROC_INST_ID_) ;
ALTER TABLE act_hi_job_log
ADD INDEX ACT_IDX_HI_JOB_LOG_PROC_DEF_KEY (PROCESS_DEF_KEY_) ,
ADD INDEX ACT_IDX_HI_JOB_LOG_EX_STACK (JOB_EXCEPTION_STACK_ID_) ;
ALTER TABLE act_hi_procinst
ADD COLUMN STATE_ varchar(255) NULL AFTER PROC_DEF_KEY_,
ADD INDEX ACT_IDX_HI_PRO_INST_PROC_DEF_KEY (PROC_DEF_KEY_) ;
ALTER TABLE act_hi_taskinst
ADD INDEX ACT_IDX_HI_TASK_INST_PROC_DEF_KEY (PROC_DEF_KEY_) ,
ADD INDEX ACT_IDX_HI_TASKINST_PROCINST (PROC_INST_ID_) ,
ADD INDEX ACT_IDX_HI_TASKINSTID_PROCINST (ID_, PROC_INST_ID_) ;
ALTER TABLE act_hi_varinst
ADD COLUMN STATE_ varchar(20) NULL AFTER TENANT_ID_,
ADD INDEX ACT_IDX_HI_VAR_INST_PROC_DEF_KEY (PROC_DEF_KEY_) ,
ADD INDEX ACT_IDX_HI_VARINST_BYTEAR (BYTEARRAY_ID_) ;
ALTER TABLE act_re_case_def
ADD COLUMN HISTORY_TTL_ int(11) NULL AFTER TENANT_ID_;
CREATE TABLE act_re_decision_req_def (
ID_ varchar(64) COLLATE utf8_bin NOT NULL,
REV_ int(11) DEFAULT NULL,
CATEGORY_ varchar(255) COLLATE utf8_bin DEFAULT NULL,
NAME_ varchar(255) COLLATE utf8_bin DEFAULT NULL,
KEY_ varchar(255) COLLATE utf8_bin NOT NULL,
VERSION_ int(11) NOT NULL,
DEPLOYMENT_ID_ varchar(64) COLLATE utf8_bin DEFAULT NULL,
RESOURCE_NAME_ varchar(4000) COLLATE utf8_bin DEFAULT NULL,
DGRM_RESOURCE_NAME_ varchar(4000) COLLATE utf8_bin DEFAULT NULL,
TENANT_ID_ varchar(64) COLLATE utf8_bin DEFAULT NULL,
PRIMARY KEY (ID_),
KEY ACT_IDX_DEC_REQ_DEF_TENANT_ID (TENANT_ID_)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
ALTER TABLE act_re_decision_def
ADD COLUMN DEC_REQ_ID_ varchar(64) NULL AFTER DGRM_RESOURCE_NAME_,
ADD COLUMN DEC_REQ_KEY_ varchar(255) NULL AFTER DEC_REQ_ID_,
ADD COLUMN HISTORY_TTL_ int(11) NULL AFTER TENANT_ID_,
ADD COLUMN VERSION_TAG_ varchar(64) NULL AFTER HISTORY_TTL_,
ADD INDEX ACT_IDX_DEC_DEF_REQ_ID (DEC_REQ_ID_) ;
ALTER TABLE act_re_decision_def ADD CONSTRAINT ACT_FK_DEC_REQ FOREIGN KEY (DEC_REQ_ID_) REFERENCES act_re_decision_req_def (ID_);
ALTER TABLE act_re_deployment
DROP COLUMN KEY_,
DROP COLUMN ENGINE_VERSION_,
MODIFY COLUMN DEPLOY_TIME_ timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER TENANT_ID_;
ALTER TABLE act_re_procdef
DROP COLUMN ENGINE_VERSION_,
ADD COLUMN HISTORY_TTL_ int(11) NULL AFTER VERSION_TAG_;
ALTER TABLE act_ru_case_sentry_part
ADD COLUMN VARIABLE_EVENT_ varchar(255) NULL AFTER SOURCE_,
ADD COLUMN VARIABLE_NAME_ varchar(255) NULL AFTER VARIABLE_EVENT_;
DROP TABLE IF EXISTS act_ru_deadletter_job;
ALTER TABLE act_ru_execution
DROP COLUMN ROOT_PROC_INST_ID_,
DROP COLUMN IS_MI_ROOT_,
DROP COLUMN START_TIME_,
DROP COLUMN START_USER_ID_,
DROP COLUMN IS_COUNT_ENABLED_,
DROP COLUMN EVT_SUBSCR_COUNT_,
DROP COLUMN TASK_COUNT_,
DROP COLUMN JOB_COUNT_,
DROP COLUMN TIMER_JOB_COUNT_,
DROP COLUMN SUSP_JOB_COUNT_,
DROP COLUMN DEADLETTER_JOB_COUNT_,
DROP COLUMN VAR_COUNT_,
DROP COLUMN ID_LINK_COUNT_,
DROP INDEX ACT_IDC_EXEC_ROOT;
ALTER TABLE act_ru_ext_task
ADD COLUMN ERROR_DETAILS_ID_ varchar(64) NULL AFTER ERROR_MSG_,
ADD INDEX ACT_IDX_EXT_TASK_ERR_DETAILS (ERROR_DETAILS_ID_) ;
ALTER TABLE act_ru_ext_task ADD CONSTRAINT ACT_FK_EXT_TASK_ERROR_DETAILS FOREIGN KEY (ERROR_DETAILS_ID_) REFERENCES act_ge_bytearray (ID_);
ALTER TABLE act_ru_job DROP FOREIGN KEY ACT_FK_JOB_EXECUTION;
ALTER TABLE act_ru_job DROP FOREIGN KEY ACT_FK_JOB_PROCESS_INSTANCE;
ALTER TABLE act_ru_meter_log
ADD COLUMN MILLISECONDS_ bigint(20) NULL DEFAULT 0 AFTER REPORTER_,
ADD INDEX ACT_IDX_METER_LOG_MS (MILLISECONDS_) ,
ADD INDEX ACT_IDX_METER_LOG_NAME_MS (NAME_, MILLISECONDS_) ,
ADD INDEX ACT_IDX_METER_LOG_REPORT (NAME_, REPORTER_, MILLISECONDS_) ,
ADD INDEX ACT_IDX_METER_LOG_TIME (TIMESTAMP_) ;
DROP TABLE IF EXISTS act_ru_suspended_job;
ALTER TABLE act_ru_task
DROP COLUMN CLAIM_TIME_,
MODIFY COLUMN CREATE_TIME_ timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP AFTER PRIORITY_;
DROP TABLE IF EXISTS act_ru_timer_job;
代码迁移
上面说过,如果单纯的新项目,根本不需要写什么代码,引几个maven库就能跑起来了,只是我原来的rest接口不可能都替换成官方的rest接口,那样工作量太大了,成本太高了,只好根据IDE的错误提醒一项一项地解决,过程就不说了,贴出修改后的Service类
package cn.jia.workflow.service;
import cn.jia.workflow.entity.DeploymentExample;
import cn.jia.workflow.entity.ProcessDefinitionExample;
import cn.jia.workflow.entity.ProcessInstanceExample;
import cn.jia.workflow.entity.TaskExample;
import com.github.pagehelper.Page;
import org.camunda.bpm.engine.history.HistoricProcessInstance;
import org.camunda.bpm.engine.history.HistoricTaskInstance;
import org.camunda.bpm.engine.history.HistoricVariableInstance;
import org.camunda.bpm.engine.repository.Deployment;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.task.Comment;
import org.camunda.bpm.engine.task.Task;
import java.io.InputStream;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
public interface WorkflowService {
/**
* 部署工作流
* @param deployment
* @param inputStream
*/
void deployProcess(Deployment deployment, InputStream inputStream);
void deployProcess(Deployment deployment, ZipInputStream zipInputStream);
/**
* 获取工作流列表
* @return
*/
List<Deployment> getDeployment();
/**
* 分页获取工作流列表
* @param pageNo
* @param pageSize
* @return
*/
Page<Deployment> getDeployment(DeploymentExample example, int pageNo, int pageSize);
/**
* 根据ID获取工作流
* @param deploymentId
* @return
*/
Deployment getDeploymentById(String deploymentId);
/**
* 获取工作流部署资源列表
* @param deploymentId
* @return
*/
List<String> getDeploymentResourceNames(String deploymentId);
/**
* 删除工作流
* @param deploymentId
*/
void deleteDeployment(String deploymentId);
/**
* 获取工作流定义列表
* @param example
* @param pageNo
* @param pageSize
* @return
*/
Page<ProcessDefinition> getProcessDefinition(ProcessDefinitionExample example, int pageNo, int pageSize);
/**
* 获取工作流定义信息
* @param processDefinitionId
* @return
*/
ProcessDefinition getProcessDefinitionById(String processDefinitionId);
/**
* 获取工作流图解内容
* @param processDefinitionId
* @return
*/
InputStream getProcessDiagram(String processDefinitionId);
/**
* 获取工作流定义内容
* @param deploymentId
* @param resourceName
* @return
*/
InputStream getResourceAsStream(String deploymentId, String resourceName);
/**
* 激活工作流
* @param processDefinitionId
*/
void activateProcessDefinition(String processDefinitionId);
/**
* 挂起工作流
* @param processDefinitionId
*/
void suspendProcessDefinition(String processDefinitionId);
/**
* 开始任务
* @param processDefinitionKey
* @param businessKey
* @param variables
*/
void startProcess(String processDefinitionKey, String businessKey, Map<String, Object> variables);
/**
* 获得某个人的任务别表
* @param assignee
* @return
*/
List<Task> getTasks(String assignee);
/**
* 分页显示某个人的任务列表
* @param example
* @param pageNo
* @param pageSize
* @return
*/
Page<Task> getTasks(TaskExample example, int pageNo, int pageSize);
/**
* 根据业务编号查找当前用户的最新任务
* @param businessKey
* @return
*/
Task getTaskByBusinessKey(String businessKey, String assignee);
/**
* 根据业务编号查找最新任务列表
* @param businessKey
* @return
*/
List<Task> getTaskByBusinessKey(String businessKey);
/**
* 根据任务ID获取任务信息
* @param taskId
* @return
*/
Task getTaskById(String taskId);
/**
* 根据实例ID获取
* @param processInstanceId
* @return
*/
List<Task> getTaskByProcessInstanceId(String processInstanceId);
/**
* 完成任务
* @param taskId
* @param variables
*/
void completeTasks(String taskId, Map<String, Object> variables);
/**
* 删除流程实例
* @param processInstanceId
* @param deleteReason
*/
void deleteProcessInstance(String processInstanceId, String deleteReason);
/**
* 委托受理人
* @param taskId 任务ID
* @param userId 被委托人
*/
void delegateTask(String taskId, String userId);
/**
* 任务认领
* @param taskId 任务ID
* @param userId 认领人ID
*/
void claimTask(String taskId, String userId);
/**
* 设置受理人
* @param taskId 任务ID
* @param userId 受理人ID
*/
void setAssignee(String taskId, String userId);
/**
* 获取任务审批人列表
* @param taskId
* @return
*/
List<String> getCandidate(String taskId);
/**
* 获取历史审批列表
* @param assignee
* @return
*/
List<HistoricTaskInstance> getHistorys(String assignee);
/**
* 分页显示历史审批列表
* @param example
* @param pageNo
* @param pageSize
* @return
*/
Page<HistoricTaskInstance> getHistorys(TaskExample example, int pageNo, int pageSize);
/**
* 根据业务编码分页显示历史审批列表
* @param businessKey
* @param pageNo
* @param pageSize
* @return
*/
Page<HistoricTaskInstance> getHistorysByBusinessKey(String businessKey, int pageNo, int pageSize);
/**
* 获取历史实例列表
* @param applicant
* @return
*/
List<HistoricProcessInstance> getHistoricProcessInstances(String applicant);
/**
* 分页显示历史实例列表
* @param example
* @param pageNo
* @param pageSize
* @return
*/
Page<HistoricProcessInstance> getHistoricProcessInstances(ProcessInstanceExample example, int pageNo, int pageSize);
/**
* 根据Task中的流程实例的ID,来获取对应的流程实例
* @param task 流程中的任务
* @return
*/
ProcessInstance getProcessInstanceByTask(Task task);
/**
* 根据历史Task中的流程实例的ID,来获取对应的历史流程实例
* @param instanceId
* @return
*/
HistoricProcessInstance getHistoricProcessInstanceById(String instanceId);
/**
* 根据taskId获取变量值
* @param taskId
* @param variableName
* @param variableClass
* @return
*/
<T> T getProcessVariables(String taskId, String variableName, Class<T> variableClass);
/**
* 根据taskId获取变量值
* @param taskId
* @param variableName
* @return
*/
Object getProcessVariables(String taskId, String variableName);
/**
* 根据实例ID获取历史变量值
* @param processInstanceId
* @param variableName
* @param variableClass
* @return
*/
<T> T getHistoricVariable(String processInstanceId, String variableName, Class<T> variableClass);
/**
* 根据实例ID获取历史变量值
* @param processInstanceId
* @param variableName
* @return
*/
Object getHistoricVariable(String processInstanceId, String variableName);
/**
* 获取任务变量列表
* @param processInstanceId
* @param taskId
* @return
*/
List<HistoricVariableInstance> getHistoricVariables(String processInstanceId, String taskId);
/**
* 获取实例变量列表
* @param processInstanceId
* @return
*/
List<HistoricVariableInstance> getHistoricVariables(String processInstanceId);
/**
* 获取任务的指定变量
* @param taskId
* @param variableName
* @return
*/
Object getTaskVariable(String taskId, String variableName);
/**
* 获取任务所有变量
* @param taskId
* @return
*/
Map<String, Object> getTaskVariables(String taskId);
/**
* 设置流程变量
* @param taskId
* @param variables
*/
void setProcessVariables(String taskId, Map<String, Object> variables);
/**
* 设置流程变量
* @param taskId
* @param variableName
* @param value
*/
void setProcessVariable(String taskId, String variableName, Object value);
/**
* 设置任务变量
* @param taskId
* @param variables
*/
void setTaskVariables(String taskId, Map<String, Object> variables);
/**
* 设置任务变量
* @param taskId
* @param variableName
* @param value
*/
void setTaskVariable(String taskId, String variableName, Object value);
/**
* 获取任务审批批注列表
* @param taskId
* @return
*/
List<Comment> getTaskComments(String taskId);
/**
* 获取任务审批批注信息
* @param taskId
* @return
*/
String getTaskComment(String taskId);
/**
* 添加任务批注
* @param taskId
* @param message
*/
void addComment(String taskId, String message);
/**
* 获取实例流程图
* @param instanceId
* @return
*/
InputStream getInstanceDiagram(String instanceId);
}
package cn.jia.workflow.service.impl;
import cn.jia.core.common.EsSecurityHandler;
import cn.jia.core.util.StringUtils;
import cn.jia.workflow.entity.DeploymentExample;
import cn.jia.workflow.entity.ProcessDefinitionExample;
import cn.jia.workflow.entity.ProcessInstanceExample;
import cn.jia.workflow.entity.TaskExample;
import cn.jia.workflow.service.WorkflowService;
import com.github.pagehelper.Page;
import org.camunda.bpm.engine.*;
import org.camunda.bpm.engine.history.*;
import org.camunda.bpm.engine.repository.Deployment;
import org.camunda.bpm.engine.repository.DeploymentQuery;
import org.camunda.bpm.engine.repository.ProcessDefinition;
import org.camunda.bpm.engine.repository.ProcessDefinitionQuery;
import org.camunda.bpm.engine.runtime.ProcessInstance;
import org.camunda.bpm.engine.task.Comment;
import org.camunda.bpm.engine.task.IdentityLink;
import org.camunda.bpm.engine.task.Task;
import org.camunda.bpm.engine.task.TaskQuery;
import org.camunda.bpm.model.bpmn.Bpmn;
import org.camunda.bpm.model.bpmn.BpmnModelInstance;
import org.camunda.bpm.model.bpmn.instance.Process;
import org.camunda.bpm.model.bpmn.instance.*;
import org.camunda.bpm.model.bpmn.instance.bpmndi.*;
import org.camunda.bpm.model.bpmn.instance.dc.Bounds;
import org.camunda.bpm.model.bpmn.instance.di.Waypoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;
@Service
public class WorkflowServiceImpl implements WorkflowService {
@Autowired
private RepositoryService repositoryService;
@Autowired
private RuntimeService runtimeService;
@Autowired
private TaskService taskService;
@Autowired
private HistoryService historyService;
@Autowired
private IdentityService identityService;
@Override
public void deployProcess(Deployment deployment, InputStream inputStream) {
String clientId = EsSecurityHandler.clientId();
repositoryService.createDeployment().addInputStream(deployment.getName()+".bpmn", inputStream).name(deployment.getName()).tenantId(clientId).deploy();
}
@Override
public void deployProcess(Deployment deployment, ZipInputStream zipInputStream) {
String clientId = EsSecurityHandler.clientId();
repositoryService.createDeployment().addZipInputStream(zipInputStream).name(deployment.getName()).tenantId(clientId).deploy();
}
@Override
public List<Deployment> getDeployment() {
return repositoryService.createDeploymentQuery().tenantIdIn(EsSecurityHandler.clientId()).list();
}
@Override
public Page<Deployment> getDeployment(DeploymentExample example, int pageNo, int pageSize) {
Page<Deployment> page = new Page<>(pageNo, pageSize);
DeploymentQuery query = repositoryService.createDeploymentQuery().tenantIdIn(EsSecurityHandler.clientId());
if(example != null){
if(example.getName() != null){
query.deploymentNameLike("%" + example.getName() + "%");
}
}
query.orderByDeploymentTime().desc();
page.setTotal(query.count());
page.addAll(query.listPage((pageNo - 1) * pageSize, pageSize));
return page;
}
@Override
public Deployment getDeploymentById(String deploymentId) {
return repositoryService.createDeploymentQuery().tenantIdIn(EsSecurityHandler.clientId()).deploymentId(deploymentId).singleResult();
}
@Override
public List<String> getDeploymentResourceNames(String deploymentId) {
return repositoryService.getDeploymentResourceNames(deploymentId);
}
@Override
public InputStream getResourceAsStream(String deploymentId, String resourceName) {
return repositoryService.getResourceAsStream(deploymentId, resourceName);
}
@Override
public void deleteDeployment(String deploymentId) {
repositoryService.deleteDeployment(deploymentId);
}
@Override
public Page<ProcessDefinition> getProcessDefinition(ProcessDefinitionExample example, int pageNo, int pageSize) {
Page<ProcessDefinition> page = new Page<>(pageNo, pageSize);
ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery().tenantIdIn(EsSecurityHandler.clientId());
if(StringUtils.isNotEmpty(example.getKey())) {
query.processDefinitionKeyLike("%" + example.getKey() + "%");
}
if(StringUtils.isNotEmpty(example.getDeploymentId())) {
query.deploymentId(example.getDeploymentId());
}
if(StringUtils.isNotEmpty(example.getCategory())){
query.processDefinitionCategoryLike("%" + example.getCategory() + "%");
}
if(StringUtils.isNotEmpty(example.getName())){
query.processDefinitionNameLike("%" + example.getName() + "%");
}
if(StringUtils.isNotEmpty(example.getResourceName())){
query.processDefinitionResourceNameLike("%" + example.getResourceName() + "%");
}
query.orderByDeploymentId().desc();
page.setTotal(query.count());
page.addAll(query.listPage((pageNo - 1) * pageSize, pageSize));
return page;
}
@Override
public ProcessDefinition getProcessDefinitionById(String processDefinitionId) {
return repositoryService.getProcessDefinition(processDefinitionId);
}
@Override
public InputStream getProcessDiagram(String processDefinitionId) {
return repositoryService.getProcessDiagram(processDefinitionId);
}
@Override
public void activateProcessDefinition(String processDefinitionId) {
repositoryService.activateProcessDefinitionById(processDefinitionId);
}
@Override
public void suspendProcessDefinition(String processDefinitionId) {
repositoryService.suspendProcessDefinitionById(processDefinitionId);
}
@Override
public void startProcess(String processDefinitionKey, String businessKey, Map<String, Object> variables) {
identityService.setAuthentication(String.valueOf(variables.get("applicant")), null, Collections.singletonList(EsSecurityHandler.clientId()));
runtimeService.startProcessInstanceByKey(processDefinitionKey, businessKey, variables);
}
@Override
public List<Task> getTasks(String assignee) {
return taskService.createTaskQuery().or().taskAssignee(assignee).taskCandidateUser(assignee).endOr().tenantIdIn(EsSecurityHandler.clientId()).list();
}
@Override
public Page<Task> getTasks(TaskExample example, int pageNo, int pageSize) {
Page<Task> page = new Page<>(pageNo, pageSize);
TaskQuery query = taskService.createTaskQuery();
if(example != null) {
if(StringUtils.isNotEmpty(example.getAssignee())) {
query.taskAssignee(example.getAssignee());
}
if(StringUtils.isNotEmpty(example.getCandidateUser())) {
query.taskCandidateUser(example.getCandidateUser());
}
if(StringUtils.isNotEmpty(example.getCandidateOrAssigned())) {
query.or().taskAssignee(example.getCandidateOrAssigned()).taskCandidateUser(example.getCandidateOrAssigned()).endOr();
}
if(StringUtils.isNotEmpty(example.getDefinitionKey())) {
query.processDefinitionKey(example.getDefinitionKey());
}
if(StringUtils.isNotEmpty(example.getDefinitionName())) {
query.processDefinitionNameLike("%" + example.getDefinitionName() + "%");
}
if(StringUtils.isNotEmpty(example.getBusinessKey())) {
query.processInstanceBusinessKeyLike("%" + example.getBusinessKey() + "%");
}
if(StringUtils.isNotEmpty(example.getProcessInstanceId())) {
query.processInstanceId(example.getProcessInstanceId());
}
if(StringUtils.isNotEmpty(example.getApplicant())) {
query.processVariableValueLike("applicant", "%" + example.getApplicant() + "%");
}
}
query.tenantIdIn(EsSecurityHandler.clientId()).orderByTaskCreateTime().desc();
page.setTotal(query.count());
page.addAll(query.listPage((pageNo - 1) * pageSize, pageSize));
return page;
}
@Override
public Task getTaskByBusinessKey(String businessKey, String assignee) {
return taskService.createTaskQuery().processInstanceBusinessKey(businessKey).or().taskAssignee(assignee).taskCandidateUser(assignee).endOr().tenantIdIn(EsSecurityHandler.clientId()).singleResult();
}
@Override
public List<Task> getTaskByBusinessKey(String businessKey) {
return taskService.createTaskQuery().processInstanceBusinessKey(businessKey).tenantIdIn(EsSecurityHandler.clientId()).list();
}
@Override
public Task getTaskById(String taskId) {
return taskService.createTaskQuery().taskId(taskId).tenantIdIn(EsSecurityHandler.clientId()).singleResult();
}
@Override
public List<Task> getTaskByProcessInstanceId(String processInstanceId) {
return taskService.createTaskQuery().processInstanceId(processInstanceId).tenantIdIn(EsSecurityHandler.clientId()).list();
}
@Override
public void completeTasks(String taskId, Map<String, Object> variables) {
taskService.complete(taskId, variables);
}
@Override
public void deleteProcessInstance(String processInstanceId, String deleteReason) {
runtimeService.deleteProcessInstance(processInstanceId, deleteReason);
}
@Override
public void delegateTask(String taskId, String userId) {
taskService.delegateTask(taskId, userId);
}
@Override
public void claimTask(String taskId, String userId) {
taskService.claim(taskId, userId);
}
@Override
public void setAssignee(String taskId, String userId) {
taskService.setAssignee(taskId, userId);
}
@Override
public List<String> getCandidate(String taskId) {
List<String> candidate = new ArrayList<>();
List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(taskId);
for(IdentityLink id : identityLinks){
if("candidate".equals(id.getType())){
candidate.add(id.getUserId());
}
}
return candidate;
}
@Override
public List<HistoricTaskInstance> getHistorys(String assignee) {
return historyService.createHistoricTaskInstanceQuery().taskAssignee(assignee).tenantIdIn(EsSecurityHandler.clientId()).finished().list();
}
@Override
public Page<HistoricTaskInstance> getHistorys(TaskExample example, int pageNo, int pageSize) {
Page<HistoricTaskInstance> page = new Page<>(pageNo, pageSize);
HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery();
if(example != null) {
if(StringUtils.isNotEmpty(example.getAssignee())) {
query = query.taskAssignee(example.getAssignee());
}
if(StringUtils.isNotEmpty(example.getDefinitionKey())) {
query.processDefinitionKey(example.getDefinitionKey());
}
if(StringUtils.isNotEmpty(example.getDefinitionName())) {
query.processDefinitionName(example.getDefinitionName());
}
if(StringUtils.isNotEmpty(example.getBusinessKey())) {
query.processInstanceBusinessKeyLike("%" + example.getBusinessKey() + "%");
}
if(StringUtils.isNotEmpty(example.getProcessInstanceId())) {
query.processInstanceId(example.getProcessInstanceId());
}
if(StringUtils.isNotEmpty(example.getApplicant())) {
query.processVariableValueEquals("applicant", example.getApplicant());
}
}
query = query.tenantIdIn(EsSecurityHandler.clientId()).finished().orderByTaskDueDate().desc();
page.setTotal(query.count());
page.addAll(query.listPage((pageNo - 1) * pageSize, pageSize));
return page;
}
@Override
public Page<HistoricTaskInstance> getHistorysByBusinessKey(String businessKey, int pageNo, int pageSize) {
Page<HistoricTaskInstance> page = new Page<>(pageNo, pageSize);
HistoricTaskInstanceQuery query = historyService.createHistoricTaskInstanceQuery().processInstanceBusinessKey(businessKey).tenantIdIn(EsSecurityHandler.clientId()).finished().orderByHistoricTaskInstanceEndTime().asc();
page.setTotal(query.count());
page.addAll(query.listPage((pageNo - 1) * pageSize, pageSize));
return page;
}
@Override
public List<HistoricProcessInstance> getHistoricProcessInstances(String applicant) {
return historyService.createHistoricProcessInstanceQuery().startedBy(applicant).tenantIdIn(EsSecurityHandler.clientId()).list();
}
@Override
public Page<HistoricProcessInstance> getHistoricProcessInstances(ProcessInstanceExample example, int pageNo, int pageSize) {
Page<HistoricProcessInstance> page = new Page<>(pageNo, pageSize);
HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery();
if(example != null) {
if(StringUtils.isNotEmpty(example.getApplicant())) {
query.startedBy(example.getApplicant());
}
if(StringUtils.isNotEmpty(example.getDefinitionKey())) {
query.processDefinitionKey(example.getDefinitionKey());
}
if(StringUtils.isNotEmpty(example.getDefinitionName())) {
query.processDefinitionName(example.getDefinitionName());
}
if(example.getStartedBefore() != null) {
query.startedBefore(example.getStartedBefore());
}
if(example.getStartedAfter() != null) {
query.startedAfter(example.getStartedAfter());
}
if(example.getFinishedBefore() != null) {
query.finishedBefore(example.getFinishedBefore());
}
if(example.getFinishedAfter() != null) {
query.finishedAfter(example.getFinishedAfter());
}
if(StringUtils.isNotEmpty(example.getBusinessKey())) {
query.processInstanceBusinessKey(example.getBusinessKey());
}
}
query.tenantIdIn(EsSecurityHandler.clientId()).orderByProcessInstanceStartTime().desc();
page.setTotal(query.count());
page.addAll(query.listPage((pageNo - 1) * pageSize, pageSize));
return page;
}
@Override
public ProcessInstance getProcessInstanceByTask(Task task) {
//得到当前任务的流程
return runtimeService.createProcessInstanceQuery().tenantIdIn(EsSecurityHandler.clientId())
.processInstanceId(task.getProcessInstanceId()).singleResult();
}
@Override
public HistoricProcessInstance getHistoricProcessInstanceById(String instanceId) {
//得到当前任务的流程
return historyService.createHistoricProcessInstanceQuery().tenantIdIn(EsSecurityHandler.clientId())
.processInstanceId(instanceId).singleResult();
}
@Override
@SuppressWarnings("unchecked")
public <T> T getProcessVariables(String taskId, String variableName, Class<T> variableClass) {
return (T)taskService.getVariable(taskId, variableName);
}
@Override
public Object getProcessVariables(String taskId, String variableName) {
return taskService.getVariable(taskId, variableName);
}
@SuppressWarnings("unchecked")
@Override
public <T> T getHistoricVariable(String processInstanceId, String variableName, Class<T> variableClass) {
HistoricVariableInstance instance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(variableName).singleResult();
if(instance != null && instance.getValue() != null) {
return (T) instance.getValue();
}else {
return null;
}
}
@Override
public Object getHistoricVariable(String processInstanceId, String variableName) {
HistoricVariableInstance instance = historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).variableName(variableName).singleResult();
if(instance != null && instance.getValue() != null) {
return instance.getValue();
}else {
return null;
}
}
@Override
public List<HistoricVariableInstance> getHistoricVariables(String processInstanceId, String taskId) {
return historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).taskIdIn(taskId).list();
}
@Override
public List<HistoricVariableInstance> getHistoricVariables(String processInstanceId) {
return historyService.createHistoricVariableInstanceQuery().processInstanceId(processInstanceId).list();
}
@Override
public Object getTaskVariable(String taskId, String variableName) {
return taskService.getVariable(taskId, variableName);
}
@Override
public Map<String, Object> getTaskVariables(String taskId) {
return taskService.getVariables(taskId);
}
@Override
public void setProcessVariables(String taskId, Map<String, Object> variables) {
taskService.setVariables(taskId, variables);
}
@Override
public void setProcessVariable(String taskId, String variableName, Object value) {
taskService.setVariable(taskId, variableName, value);
}
@Override
public void setTaskVariables(String taskId, Map<String, Object> variables) {
taskService.setVariablesLocal(taskId, variables);
}
@Override
public void setTaskVariable(String taskId, String variableName, Object value) {
taskService.setVariableLocal(taskId, variableName, value);
}
@Override
public List<Comment> getTaskComments(String taskId) {
return taskService.getTaskComments(taskId);
}
@Override
public String getTaskComment(String taskId) {
List<String> comment = new ArrayList<>();
List<Comment> commentList = taskService.getTaskComments(taskId);
for(Comment c : commentList) {
comment.add(c.getFullMessage());
}
return String.join(",", comment);
}
@Override
public void addComment(String taskId, String message) {
Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
taskService.createComment(taskId, task.getProcessInstanceId(), message);
}
@Override
public InputStream getInstanceDiagram(String instanceId) {
return null;
// try {
// // 获取历史流程实例
// HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(instanceId).singleResult();
//
// // 获取流程中已经执行的节点,按照执行先后顺序排序
// List<HistoricActivityInstance> historicActivityInstanceList = historyService.createHistoricActivityInstanceQuery().processInstanceId(instanceId).orderByHistoricActivityInstanceId().asc().list();
//
// // 构造已执行的节点ID集合
// List<String> executedActivityIdList = new ArrayList<>();
// for (HistoricActivityInstance activityInstance : historicActivityInstanceList) {
// executedActivityIdList.add(activityInstance.getActivityId());
// }
//
// // 获取bpmnModel
// BpmnModel bpmnModel = repositoryService.getBpmnModel(historicProcessInstance.getProcessDefinitionId());
// // 获取流程已发生流转的线ID集合
// List<String> flowIds = this.getExecutedFlows(bpmnModel, historicActivityInstanceList);
//
// // 使用默认配置获得流程图表生成器,并生成追踪图片字符流
// ProcessDiagramGenerator processDiagramGenerator = new DefaultProcessDiagramGenerator();
// return processDiagramGenerator.generateDiagram(bpmnModel, "png", executedActivityIdList, flowIds, "宋体", "微软雅黑", "黑体", null, 2.0);
// } catch (Exception e) {
// e.printStackTrace();
// return null;
// }
}
// private List<String> getExecutedFlows(BpmnModel bpmnModel, List<HistoricActivityInstance> historicActivityInstances) {
// // 流转线ID集合
// List<String> flowIdList = new ArrayList<>();
// // 全部活动实例
// List<FlowNode> historicFlowNodeList = new LinkedList<>();
// // 已完成的历史活动节点
// List<HistoricActivityInstance> finishedActivityInstanceList = new LinkedList<>();
// for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
// historicFlowNodeList.add((FlowNode) bpmnModel.getMainProcess().getFlowElement(historicActivityInstance.getActivityId(), true));
// if (historicActivityInstance.getEndTime() != null) {
// finishedActivityInstanceList.add(historicActivityInstance);
// }
// }
//
// // 遍历已完成的活动实例,从每个实例的outgoingFlows中找到已执行的
// FlowNode currentFlowNode;
// for (HistoricActivityInstance currentActivityInstance : finishedActivityInstanceList) {
// // 获得当前活动对应的节点信息及outgoingFlows信息
// currentFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(currentActivityInstance.getActivityId(), true);
// List<SequenceFlow> sequenceFlowList = currentFlowNode.getOutgoingFlows();
//
// /*
// 遍历outgoingFlows并找到已已流转的
// 满足如下条件认为已已流转:
// 1.当前节点是并行网关或包含网关,则通过outgoingFlows能够在历史活动中找到的全部节点均为已流转
// 2.当前节点是以上两种类型之外的,通过outgoingFlows查找到的时间最近的流转节点视为有效流转
// */
// FlowNode targetFlowNode;
// if (BpmsActivityTypeEnum.PARALLEL_GATEWAY.getType().equals(currentActivityInstance.getActivityType())
// || BpmsActivityTypeEnum.INCLUSIVE_GATEWAY.getType().equals(currentActivityInstance.getActivityType())) {
// // 遍历历史活动节点,找到匹配Flow目标节点的
// for (SequenceFlow sequenceFlow : sequenceFlowList) {
// targetFlowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(sequenceFlow.getTargetRef(), true);
// if (historicFlowNodeList.contains(targetFlowNode)) {
// flowIdList.add(sequenceFlow.getId());
// }
// }
// } else {
// List<Map<String, String>> tempMapList = new LinkedList<>();
// // 遍历历史活动节点,找到匹配Flow目标节点的
// for (SequenceFlow sequenceFlow : sequenceFlowList) {
// for (HistoricActivityInstance historicActivityInstance : historicActivityInstances) {
// if (historicActivityInstance.getActivityId().equals(sequenceFlow.getTargetRef())) {
// tempMapList.add(DataUtil.toMap("flowId", sequenceFlow.getId(), "activityStartTime", String.valueOf(historicActivityInstance.getStartTime().getTime())));
// }
// }
// }
//
// // 遍历匹配的集合,取得开始时间最早的一个
// long earliestStamp = 0L;
// String flowId = null;
// for (Map<String, String> map : tempMapList) {
// long activityStartTime = Long.valueOf(map.get("activityStartTime"));
// if (earliestStamp == 0 || earliestStamp >= activityStartTime) {
// earliestStamp = activityStartTime;
// flowId = map.get("flowId");
// }
// }
// flowIdList.add(flowId);
// }
// }
// return flowIdList;
// }
public void generateProcess() throws IOException {
BpmnModelInstance modelInstance = Bpmn.createEmptyModel();
Definitions definitions = modelInstance.newInstance(Definitions.class);
definitions.setTargetNamespace("http://camunda.org/examples");
modelInstance.setDefinitions(definitions);
// create the process
Process process = modelInstance.newInstance(Process.class);
process.setAttributeValue("id", "process-one-task", true);
definitions.addChildElement(process);
BpmnDiagram diagram = modelInstance.newInstance(BpmnDiagram.class);
BpmnPlane plane = modelInstance.newInstance(BpmnPlane.class);
plane.setBpmnElement(process);
diagram.setBpmnPlane(plane);
definitions.addChildElement(diagram);
// create start event, user task and end event
StartEvent startEvent = createElement(modelInstance, process, "start", "Di generation wanted",
StartEvent.class, plane, 15, 15, 50, 50, true);
UserTask userTask = createElement(modelInstance, process, "userTask", "Generate Model with DI",
UserTask.class, plane, 100, 0, 80, 100, false);
createSequenceFlow(modelInstance, process, startEvent, userTask, plane, 65, 40, 100, 40);
EndEvent endEvent = createElement(modelInstance, process, "end", "DI generation completed",
EndEvent.class, plane, 250, 15, 50, 50, true);
createSequenceFlow(modelInstance, process, userTask, endEvent, plane, 200, 40, 250, 40);
// validate and write model to file
Bpmn.validateModel(modelInstance);
File file = File.createTempFile("bpmn-model-api-", ".bpmn");
Bpmn.writeModelToFile(file, modelInstance);
}
private <T extends BpmnModelElementInstance> T createElement(BpmnModelInstance modelInstance, BpmnModelElementInstance parentElement,
String id, String name, Class<T> elementClass, BpmnPlane plane,
double x, double y, double heigth, double width, boolean withLabel) {
T element = modelInstance.newInstance(elementClass);
element.setAttributeValue("id", id, true);
element.setAttributeValue("name", name, false);
parentElement.addChildElement(element);
BpmnShape bpmnShape = modelInstance.newInstance(BpmnShape.class);
bpmnShape.setBpmnElement((BaseElement) element);
Bounds bounds = modelInstance.newInstance(Bounds.class);
bounds.setX(x);
bounds.setY(y);
bounds.setHeight(heigth);
bounds.setWidth(width);
bpmnShape.setBounds(bounds);
if (withLabel) {
BpmnLabel bpmnLabel = modelInstance.newInstance(BpmnLabel.class);
Bounds labelBounds = modelInstance.newInstance(Bounds.class);
labelBounds.setX(x);
labelBounds.setY(y + heigth);
labelBounds.setHeight(heigth);
labelBounds.setWidth(width);
bpmnLabel.addChildElement(labelBounds);
bpmnShape.addChildElement(bpmnLabel);
}
plane.addChildElement(bpmnShape);
return element;
}
private SequenceFlow createSequenceFlow(BpmnModelInstance modelInstance, Process process, FlowNode from, FlowNode to, BpmnPlane plane,
int... waypoints) {
String identifier = from.getId() + "-" + to.getId();
SequenceFlow sequenceFlow = modelInstance.newInstance(SequenceFlow.class);
sequenceFlow.setAttributeValue("id", identifier, true);
process.addChildElement(sequenceFlow);
sequenceFlow.setSource(from);
from.getOutgoing().add(sequenceFlow);
sequenceFlow.setTarget(to);
to.getIncoming().add(sequenceFlow);
BpmnEdge bpmnEdge = modelInstance.newInstance(BpmnEdge.class);
bpmnEdge.setBpmnElement(sequenceFlow);
for (int i = 0; i < waypoints.length / 2; i++) {
double waypointX = waypoints[i*2];
double waypointY = waypoints[i*2+1];
Waypoint wp = modelInstance.newInstance(Waypoint.class);
wp.setX(waypointX);
wp.setY(waypointY);
bpmnEdge.addChildElement(wp);
}
plane.addChildElement(bpmnEdge);
return sequenceFlow;
}
}
再贴一个我常用的Listener
package cn.jia.workflow.listener;
import cn.jia.core.common.EsSecurityHandler;
import cn.jia.core.entity.JSONResult;
import cn.jia.core.util.*;
import cn.jia.workflow.common.ErrorConstants;
import lombok.extern.slf4j.Slf4j;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.delegate.*;
import org.camunda.bpm.engine.impl.el.JuelExpression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import java.util.Map;
/**
* Rest接口调用通用方法
* @author chcbz
* @date 2018年9月11日 下午3:37:55
*/
@Slf4j
@Service
public class RestListener implements ExecutionListener, TaskListener {
private static final long serialVersionUID = -507889727531125820L;
private JuelExpression url;
private JuelExpression method;
private JuelExpression params;
@Autowired
@Qualifier("singleRestTemplate")
private RestTemplate restTemplate;
@Autowired
private TaskService taskService;
@Override
public void notify(DelegateTask delegateTask) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
// OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails)SecurityContextHolder.getContext().getAuthentication().getDetails();
// headers.set("Authorization", "Bearer " + details.getTokenValue());
String rqurl = fixedValueToString(url, delegateTask);
String random = DataUtil.getRandom(false, 16);
rqurl = HttpUtil.addUrlValue(rqurl, "nonce", random);
String signature = MD5Util.str2Base32MD5(MD5Util.str2Base32MD5(random)+EsSecurityHandler.clientId());
rqurl = HttpUtil.addUrlValue(rqurl, "signature", signature);
String businessKey = String.valueOf(taskService.getVariable(delegateTask.getId(), "businessKey"));
rqurl = HttpUtil.addUrlValue(rqurl, "businessKey", businessKey);
String assignee = delegateTask.getAssignee();
rqurl = HttpUtil.addUrlValue(rqurl, "assignee", assignee);
String paramsStr = fixedValueToString(params, delegateTask);
if(StringUtils.isNotEmpty(paramsStr)){
Map<String, Object> paramsMap = JSONUtil.jsonToMap(paramsStr);
if(paramsMap != null){
for (String paramsKey : paramsMap.keySet()) {
rqurl = HttpUtil.addUrlValue(rqurl, paramsKey, String.valueOf(paramsMap.get(paramsKey)));
}
}
}
// String candidate = "";
// Set<IdentityLink> candidates = delegateTask.getCandidates();
// for(IdentityLink id : candidates){
// candidate += "," + id.getUserId();
// }
// rqurl = HttpUtil.addUrlValue(rqurl, "candidate", StringUtils.isEmpty(candidate) ? "" : candidate.substring(1));
log.info("======================rqurl: " + rqurl);
log.info("======================method: " + fixedValueToString(method, delegateTask));
log.info("======================params: " + paramsStr);
HttpEntity<String> entity = new HttpEntity<>(fixedValueToString(params, delegateTask), headers);
JSONResult<?> result = restTemplate.exchange(rqurl, HttpMethod.resolve(fixedValueToString(method, delegateTask)), entity, JSONResult.class).getBody();
if(!ErrorConstants.SUCCESS.equals(result.getCode())) {
log.error(result.getMsg());
}
}
@Override
public void notify(DelegateExecution execution) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON_UTF8);
// OAuth2AuthenticationDetails details = (OAuth2AuthenticationDetails)SecurityContextHolder.getContext().getAuthentication().getDetails();
// headers.set("Authorization", "Bearer " + details.getTokenValue());
String rqurl = fixedValueToString(url, execution);
String random = DataUtil.getRandom(false, 16);
rqurl = HttpUtil.addUrlValue(rqurl, "nonce", random);
String signature = MD5Util.str2Base32MD5(MD5Util.str2Base32MD5(random)+EsSecurityHandler.clientId());
rqurl = HttpUtil.addUrlValue(rqurl, "signature", signature);
String businessKey = execution.getBusinessKey();
rqurl = HttpUtil.addUrlValue(rqurl, "businessKey", businessKey);
HttpEntity<String> entity = new HttpEntity<>(fixedValueToString(params, execution), headers);
JSONResult<?> result = restTemplate.exchange(rqurl, HttpMethod.resolve(fixedValueToString(method, execution)), entity, JSONResult.class).getBody();
if(!ErrorConstants.SUCCESS.equals(result.getCode())) {
log.error(result.getMsg());
}
}
private String fixedValueToString(Expression fixedValue, VariableScope variableScope) {
if(fixedValue == null) {
return null;
}
return fixedValue.getValue(variableScope).toString();
}
}
再贴一个BPMN吧
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:camunda="http://camunda.org/schema/1.0/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tns="http://www.camunda.org/test" xmlns:xsd="http://www.w3.org/2001/XMLSchema" id="m1570518626053" name="" targetNamespace="http://bpmn.io/schema/bpmn">
<process id="carbook" name="商品车预订" processType="None" isClosed="false" isExecutable="true">
<startEvent id="startevent1" name="Start" />
<sequenceFlow id="flow1" sourceRef="startevent1" targetRef="Vehicle_reservation_approval" />
<userTask id="Vehicle_reservation_approval" name="仓库管理员审批" camunda:candidateUsers="${reviewers}">
<extensionElements>
<camunda:taskListener delegateExpression="${restListener}" event="create">
<camunda:field name="url">
<camunda:expression>https://api.mydomain.com/car/notify</camunda:expression>
</camunda:field>
<camunda:field name="method">
<camunda:expression>GET</camunda:expression>
</camunda:field>
<camunda:field name="params">
<camunda:expression>{"candidate":"${reviewers}","type":"Vehicle_reservation_approval"}</camunda:expression>
</camunda:field>
</camunda:taskListener>
</extensionElements>
</userTask>
<exclusiveGateway id="reviewResult" name="审核结果" />
<sequenceFlow id="flow3" sourceRef="Vehicle_reservation_approval" targetRef="reviewResult" />
<endEvent id="endevent1" name="End">
<incoming>flow4</incoming>
</endEvent>
<sequenceFlow id="pass" name="同意" sourceRef="reviewResult" targetRef="endevent1">
<extensionElements>
<camunda:executionListener delegateExpression="${restListener}" event="take">
<camunda:field name="url">
<camunda:expression>https://api.mydomain.com/car/complete/${businessKey}</camunda:expression>
</camunda:field>
<camunda:field name="method">
<camunda:expression>GET</camunda:expression>
</camunda:field>
<camunda:field name="params">
<camunda:expression>{}</camunda:expression>
</camunda:field>
</camunda:executionListener>
</extensionElements>
<conditionExpression xsi:type="tFormalExpression">${pass}</conditionExpression>
</sequenceFlow>
<sequenceFlow id="flow4" name="不同意" sourceRef="reviewResult" targetRef="endevent1">
<extensionElements>
<camunda:executionListener delegateExpression="${restListener}" event="take">
<camunda:field name="url">
<camunda:expression>https://api.mydomain.com/car/reject/${businessKey}</camunda:expression>
</camunda:field>
<camunda:field name="method">
<camunda:expression>GET</camunda:expression>
</camunda:field>
<camunda:field name="params">
<camunda:expression>{}</camunda:expression>
</camunda:field>
</camunda:executionListener>
</extensionElements>
</sequenceFlow>
</process>
<bpmndi:BPMNDiagram id="Diagram-_1" name="New Diagram" documentation="background=#3C3F41;count=1;horizontalcount=1;orientation=0;width=842.4;height=1195.2;imageableWidth=832.4;imageableHeight=1185.2;imageableX=5.0;imageableY=5.0">
<bpmndi:BPMNPlane bpmnElement="carbook">
<bpmndi:BPMNShape id="Shape-startevent1" bpmnElement="startevent1">
<omgdc:Bounds x="209" y="297" width="32" height="32" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="-107" y="-4" width="25" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Shape-Vehicle_reservation_approval" bpmnElement="Vehicle_reservation_approval">
<omgdc:Bounds x="343" y="285" width="105" height="55" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="0" y="0" width="105" height="55" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Shape-reviewResult" bpmnElement="reviewResult" isMarkerVisible="true">
<omgdc:Bounds x="539" y="300" width="32" height="32" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="-37" y="2" width="45" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="Shape-endevent1" bpmnElement="endevent1">
<omgdc:Bounds x="655" y="298" width="32" height="32" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="6" y="-3" width="20" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNShape>
<bpmndi:BPMNEdge id="BPMNEdge_flow1" bpmnElement="flow1" sourceElement="startevent1" targetElement="Vehicle_reservation_approval">
<omgdi:waypoint x="241" y="313" />
<omgdi:waypoint x="343" y="313" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="-1" y="-1" width="-1" height="-1" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_flow3" bpmnElement="flow3" sourceElement="Vehicle_reservation_approval" targetElement="reviewResult">
<omgdi:waypoint x="448" y="315" />
<omgdi:waypoint x="540" y="315" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="-1" y="-1" width="-1" height="-1" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_pass" bpmnElement="pass" sourceElement="reviewResult" targetElement="endevent1">
<omgdi:waypoint x="570" y="315" />
<omgdi:waypoint x="655" y="315" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="581" y="291" width="23" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
<bpmndi:BPMNEdge id="BPMNEdge_flow4" bpmnElement="flow4" sourceElement="Shape-reviewResult" targetElement="Shape-endevent1">
<omgdi:waypoint x="555" y="332" />
<omgdi:waypoint x="555" y="386" />
<omgdi:waypoint x="671" y="386" />
<omgdi:waypoint x="671" y="330" />
<bpmndi:BPMNLabel>
<omgdc:Bounds x="561" y="348" width="34" height="14" />
</bpmndi:BPMNLabel>
</bpmndi:BPMNEdge>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</definitions>
最后
至此,项目已经可以正常地跑起来,迁移工作也完成了,但是其实还有个问题没有解决,就是现在还无法自动生成实例流程图,官方没有给出相应例子,留待后续处理。
我把项目代码放到github上,供大家参考,只是由于采用的是springcloud,并且依赖了一些私有jar包,所以无法单独跑起来。
https://github.com/chcbz/jia-api-workflow
参考文章:
https://blog.youkuaiyun.com/qq_30739519/article/details/86583765(Camunda/Flowable/Activiti技术发展史)
https://blog.youkuaiyun.com/skayliu/article/details/89048225(从Activiti切换到Camunda的5个理由)
http://blog.camunda.com/post/2016/10/migrate-from-activiti-to-camunda/(How to migrate from Activiti 5.21 to Camunda BPM 7.5)