前言

在十年前刚开始接触工作流引擎的时候,所知道的就只有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.csdn.net/qq_30739519/article/details/86583765(Camunda/Flowable/Activiti技术发展史)

https://blog.csdn.net/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)

更多推荐