diff --git a/.gitignore b/.gitignore index b9d582687a..919e777b76 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,7 @@ .ant_targets .DS_Store .bpmn +*.iml +.idea +rebel.xml +.settings diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component index d63fd2c173..05a738858c 100644 --- a/.settings/org.eclipse.wst.common.component +++ b/.settings/org.eclipse.wst.common.component @@ -6,7 +6,6 @@ - diff --git a/README.md b/README.md index e683d29e74..9d35679a34 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,30 @@ 本项目旨在让初学者快速入门Activiti。 -**作者**:[咖啡兔|http://www.kafeitu.me] +**作者**:[咖啡兔](http://www.kafeitu.me) **项目主页**:[http://www.kafeitu.me/activiti/2012/05/26/kft-activiti-demo.html](http://www.kafeitu.me/activiti/2012/05/26/kft-activiti-demo.html) -**在线演示(亚马逊EC2)**:[http://aws.kafeitu.me:8080/kft-activiti-demo](http://aws.kafeitu.me:8080/kft-activiti-demo) +**在线演示**:[http://demo.kafeitu.me:8080/kft-activiti-demo](http://demo.kafeitu.me:8080/kft-activiti-demo) -# 框架版本 +**Wiki文档**: [https://github.com/henryyan/kft-activiti-demo/wiki](https://github.com/henryyan/kft-activiti-demo/wiki) + +**QQ群在线支持:**: 236540304 + +**《Activiti实战》**:Activiti项目Team Leader **Tijs Rademakers**认可并推荐,详情访问 [http://www.kafeitu.me/activiti-in-action.html](http://www.kafeitu.me/activiti-in-action.html) -* Activiti: **5.11** +---- +![](https://raw.githubusercontent.com/henryyan/kft-activiti-demo/master/src/main/webapp/images/activiti-in-action.jpg) + +---- +去 China-Pub| 京东| 当当网| 亚马逊 购买 +---- + +# 框架版本 -* Spring: **3.1.1.RELEASE** +* Activiti: **5.19.0** -* Hibernate: **4.1.4.Final** +* Spring: **4.1.5.RELEASE** # 分支选择 @@ -23,6 +34,14 @@ Demo提供Maven版本和no-maven版本,分别适用于会用mavne和不会用m * **maven**分支:对应与git的`master`分支,便于安装和数据库初始化 * **no-maven**分支:直接是一个eclipse工程,包含eclipse的项目配置文件和WEB-INF/lib下面的所有的jar文件 +## Maven方式运行 + +> mvn clean jetty:run + +在 **pom.xml** 中配置了 **h2** 数据库与 **mysql** 数据库,默认启用 **h2** 数据库配置方式,如果使用 **mysql** 请启用mysql的配置(使用下面的命令)。 + +> mvn clean jetty:run -Pmysql + # 演示说明文档 * [配置说明](https://github.com/henryyan/kft-activiti-demo/wiki/%E9%85%8D%E7%BD%AE%E8%AF%B4%E6%98%8E) @@ -32,8 +51,56 @@ Demo提供Maven版本和no-maven版本,分别适用于会用mavne和不会用m ## Changelog +### 1.14.0(2015-11-26) +1. 添加查看引擎参数功能 +2. 添加查看引擎数据库功能 +3. 添加管理用户与组功能 +4. 添加作业管理功能 +5. 5.17+方式嵌入Rest服务 + +### 1.13.0(2015-11-23) +1. 集成基于5.17+的流程设计器(Activiti Modeler,很漂亮),demo依赖的版本支持5.17以上 +2. 数据库配置属性转移到pom.xml里面,可以直接修改`pom.xml`文件的参数,也可以在运行时通过`-Djdbc.password=111111`参数覆盖 + +### 1.11~1.12(unknown) +1. 内部消耗掉了,不要问我... + +### 1.10.1(2014-04-23) +1. 修复在最新版本Chrome(V34)不能运行Activiti Modeler问题 + +### 1.10.0(2014-04-18) +1. 集成了diagram-viewer,目前提供了三种流程跟踪方式 +2. 添加了针对JPA的演示 +3. 添加了全局监听的演示 +4. 使用5.15.1-kft版本(修复了5.15版本中查询待办任务<包含指定到人、候选人、候选组>方法的Bug) + +### 1.9.0(2014-01-01) +1. 升级Activiti到5.14 +2. 同时支持纯Rest接口和Activiti Modeler的Rest路径映射 + +### 1.8.0(2013-06-22) +1. 升级Activiti至5.13 +2. 移除了全局监听器(以后的版本会再加入) + +### 1.7.2(2013-04-17) +1. 升级Activiti至5.12.1-kft版本 +2. 添加全局监听器演示 + +### 1.7.1(2013-04-10) +1. 解决流程引擎自动生成的图片跟踪坐标错乱问题 +2. 使用重新打包的5.12.1,解决JDK6部署时报错问题 +3. 解决跟踪流程图时(调用引擎的图片生成工具)中文乱码 + +### 1.7.0(2013-03-10) +1. 添加分页查询演示 +2. 添加流程定义对象(ProcessDefinition)缓存演示, see: [Tweaking the process definition cache in Activiti 5.12](http://www.jorambarrez.be/blog/2012/12/20/tweaking-process-definition-cache/) +3. 添加activityFontName属性配置,可以解决流程图中包含中文导致生成的流程图乱码问题 +4. 整合Activiti Modeler,可以在线设计流程 + +> 特别说明:5.12.1不是官方提供,是我自己打包的一个版本(支持Native Query分页查询功能,5.13将会直接提供此功能) + ### 1.6.0(2013-01-06) -1. 添加多实例(发文会签)演示 +1. 添加多实例(发文)演示 2. 添加自动部署流程定义演示 ### 1.5.0 (2012-12-16) @@ -60,3 +127,32 @@ Demo提供Maven版本和no-maven版本,分别适用于会用mavne和不会用m 1.表单名称重构,portlet添加关于作者和表单概念模块 2.首页用jquery.portlet插件显示信息,并添加一个待办任务列表的portlet + +2. c50ec09 添加流程实例状态控制功能 +3. 9a97cda formkey查询任务时使用native query +4. 3e8ab24 清理垃圾 +5. 9035e56 动态表单和外置表单的运行中列表显示的当前节点的英文名称,并在查询流程数据时区分动态、外置表单 +6. 7f955c4 重写JuelFormEngine,解决windows平台读取表单内容乱码问题 +7. d72778b 升级portlet插件为1.1.1 +8. 5e4007c 升级初始化sql的activiti版本为5.11 +9. 684c8a0 解决jsp文件中出现两个head问题 +10. 3bcbd56 菜单的传统改为普通,外部改为外置 +11. 645347c 移除不需要的依赖版本号 + +### 1.4.1 (2012-12-01) + +1.升级jquery.portlet.js解决把一列的portlet拖走后不能再拖回问题 + +2.升级:jquery -> 1.83,jquery ui -> 1.9.2, jquery.layout -> 1.3,html头部声明用html标准代替xhtml + +### 1.4 (2012-11-27) + +1.表单名称重构,portlet添加关于作者和表单概念模块 + +2.首页用jquery.portlet插件显示信息,并添加一个待办任务列表的portlet + +### 中间的版本没记录就忽略了。。。 + +### 1.0.0(2011-10-23)鼻祖 + +1. 第一个原始版本,当时应该只有流程部署和流程启动。。。 diff --git a/bin/merge-to-no-maven.sh b/bin/merge-to-no-maven.sh index 85ea7ebe3b..77474c380e 100755 --- a/bin/merge-to-no-maven.sh +++ b/bin/merge-to-no-maven.sh @@ -2,7 +2,7 @@ NO_MAVEN_DIR="../kft-activiti-demo-no-maven" echo "delete all files of branch no-maven" -echo "delete libs" +#echo "delete libs" rm $NO_MAVEN_DIR/WebContent/WEB-INF/lib/* echo "delete java" @@ -17,11 +17,19 @@ rm -rf $NO_MAVEN_DIR/WebContent/common rm -rf $NO_MAVEN_DIR/WebContent/css rm -rf $NO_MAVEN_DIR/WebContent/images rm -rf $NO_MAVEN_DIR/WebContent/js +rm -rf $NO_MAVEN_DIR/WebContent/api +rm -rf $NO_MAVEN_DIR/WebContent/editor +rm -rf $NO_MAVEN_DIR/WebContent/explorer +rm -rf $NO_MAVEN_DIR/WebContent/libs rm -rf $NO_MAVEN_DIR/WebContent/WEB-INF/views echo "copying libs to no-maven" -mvn dependency:copy-dependencies -cp ./target/dependency/* $NO_MAVEN_DIR/WebContent/WEB-INF/lib/ +mvn package -Dmaven.test.skip=true +cp ./target/kft-activiti-demo/WEB-INF/lib/* $NO_MAVEN_DIR/WebContent/WEB-INF/lib/ +cd $NO_MAVEN_DIR +git checkout -- WebContent/WEB-INF/lib/junit-4.10.jar +git checkout -- WebContent/WEB-INF/lib/servlet-api-2.5.jar +cd - echo "copying java" cp -r src/main/java/* $NO_MAVEN_DIR/src @@ -30,11 +38,21 @@ cp -r src/test/java/* $NO_MAVEN_DIR/test echo "copying java resources" cp -r src/main/resources/* $NO_MAVEN_DIR/resources cp target/classes/application.properties $NO_MAVEN_DIR/resources +cd $NO_MAVEN_DIR +git checkout -- resources/activiti.cfg.xml +git checkout -- resources/application.test.properties +git checkout -- resources/applicationContext-test.xml +git checkout -- resources/data/sample-data.xml +cd - echo "copying web resources" cp -r src/main/webapp/common $NO_MAVEN_DIR/WebContent/common cp -r src/main/webapp/css $NO_MAVEN_DIR/WebContent/css cp -r src/main/webapp/images $NO_MAVEN_DIR/WebContent/images cp -r src/main/webapp/js $NO_MAVEN_DIR/WebContent/js +cp -r src/main/webapp/api $NO_MAVEN_DIR/WebContent/api +cp -r src/main/webapp/editor $NO_MAVEN_DIR/WebContent/editor +cp -r src/main/webapp/explorer $NO_MAVEN_DIR/WebContent/explorer +cp -r src/main/webapp/libs $NO_MAVEN_DIR/WebContent/libs cp -r src/main/webapp/WEB-INF/views $NO_MAVEN_DIR/WebContent/WEB-INF/views cp src/main/webapp/WEB-INF/*.xml $NO_MAVEN_DIR/WebContent/WEB-INF diff --git a/build.xml b/build.xml deleted file mode 100644 index ba192088e2..0000000000 --- a/build.xml +++ /dev/null @@ -1,57 +0,0 @@ - - - - - - - - - - - - - - - - - - - Activiti演示程序,请输入命令后操作! - - - - - 打包流程定义:请假(自定义表单) - - - - - - - - 打包流程定义:请假(动态表单) - - - - - - - - 打包流程定义:请假(外置表单) - - - - - - - - 打包流程定义:发文会签 - - - - - - - - - diff --git a/pom.xml b/pom.xml index 122ac3c4a8..55ba9847fa 100644 --- a/pom.xml +++ b/pom.xml @@ -1,591 +1,589 @@ - 4.0.0 - me.kafeitu.demo - kft-activiti-demo - 1.6.0 - war - Activiti demo - activiti demo for version 5.11 - - - - henryyan - Henry Yan - yanhonglei@gmail.com - http://www.kafeitu.me - 8 - - - - - - 1.6 - 3.1.2.RELEASE - 4.1.4.Final - 1.1.0.RELEASE - 1.4 - 2.5.2 - 2.0.4 - 2.8.1 - 12.0 - 3.1 - 2.4 - 2.1 - 1.6.6 - 1.2.17 - 7.6.4.v20120524 - 1.3.167 - 4.10 - 1.9.0 - 1.4.12 - 5.11 - - - com.h2database - h2 - 1.3.166 - - - - UTF-8 - - - - - Activiti - https://maven.alfresco.com/nexus/content/groups/public - - - Codehaus - http://repository.codehaus.org - - - - - - - - org.activiti - activiti-engine - ${activiti.version} - - - org.activiti - activiti-spring - ${activiti.version} - - - - - - org.codehaus.jackson - jackson-mapper-asl - 1.9.7 - - - - - commons-io - commons-io - ${commons-io.version} - - - commons-fileupload - commons-fileupload - 1.2.2 - - - - - - org.springframework - spring-core - ${spring.version} - - - commons-logging - commons-logging - - - - - org.springframework - spring-beans - ${spring.version} - - - org.springframework - spring-context - ${spring.version} - - - org.springframework - spring-context-support - ${spring.version} - - - org.springframework - spring-aop - ${spring.version} - - - org.aspectj - aspectjrt - 1.6.9 - - - org.aspectj - aspectjweaver - 1.6.9 - - - cglib - cglib - 2.2.2 - - - asm - asm - 3.3.1 - - - - - - - org.hibernate - hibernate-core - ${hibernate.version} - - - org.hibernate - hibernate-entitymanager - ${hibernate.version} - - - org.hibernate - hibernate-ehcache - ${hibernate.version} - - - org.hibernate.javax.persistence - hibernate-jpa-2.0-api - 1.0.1.Final - - - - - org.springframework.data - spring-data-jpa - ${spring-data-jpa.version} - - - junit - junit-dep - - - - - org.springframework - spring-orm - ${spring.version} - - - org.springframework - spring-jdbc - ${spring.version} - - - - - commons-dbcp - commons-dbcp - ${commons-dbcp.version} - - - - - ${jdbc.driver.groupId} - ${jdbc.driver.artifactId} - ${jdbc.driver.version} - runtime - - - - - - org.springframework - spring-webmvc - ${spring.version} - - - - javax.servlet - jstl - 1.2 - - - - javax.servlet - servlet-api - 2.5 - provided - - - - - - net.sf.ehcache - ehcache-core - ${ehcache.version} - - - - - org.slf4j - slf4j-api - ${slf4j.version} - - - org.slf4j - slf4j-log4j12 - ${slf4j.version} - - - org.slf4j - jcl-over-slf4j - ${slf4j.version} - - - log4j - log4j - ${log4j.version} - - - - - - org.apache.commons - commons-lang3 - ${commons-lang3.version} - - - commons-beanutils - commons-beanutils - 1.8.3 - - - commons-logging - commons-logging - - - - - - com.google.guava - guava - ${guava.version} - - - org.jodd - jodd - 3.3.2 - - - joda-time - joda-time - ${joda-time.version} - - - - - - junit - junit - ${junit.version} - test - - - - org.mockito - mockito-core - ${mockito.version} - test - - - - org.powermock - powermock-module-junit4 - ${powermock.version} - test - - - org.powermock - powermock-api-mockito - ${powermock.version} - test - - - org.mockito - mockito-all - - - - - - org.springframework - spring-test - ${spring.version} - - - - com.h2database - h2 - ${h2.version} - - - - org.dbunit - dbunit - 2.4.8 - - - - - org.eclipse.jetty.aggregate - jetty-webapp - ${jetty.version} - test - - - org.eclipse.jetty - jetty-jsp - ${jetty.version} - test - - - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 2.5 - - ${jdk.version} - ${jdk.version} - true - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.12 - - -Xmx256M - - - - - - org.codehaus.mojo - cobertura-maven-plugin - 2.5.1 - - - - **/entity/**/*.class - **/*Controller.class - - - - - - - - org.apache.maven.plugins - maven-eclipse-plugin - 2.9 - - 2.0 - - org.springframework.ide.eclipse.core.springnature - - - - - - - org.mortbay.jetty - jetty-maven-plugin - ${jetty.version} - - - - spring.profiles.active - development - - - true - - - /${project.artifactId} - - - - - - - org.apache.maven.plugins - maven-resources-plugin - 2.5 - - - - zip - bar - png - activiti - bpmn - - ${project.build.sourceEncoding} - - - - - - - - - kft-activiti-demo - - true - - - - - src/main/resources - true - - - - - - - - initdatas - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - refresh-db - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.7 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + me.kafeitu.demo + kft-activiti-demo + 1.15.0-SNAPSHOT + war + Activiti demo + activiti demo for version 5.17+ + + + + henryyan + Henry Yan + yanhonglei@gmail.com + http://www.kafeitu.me + 8 + + + + + + 1.7 + 4.1.5.RELEASE + 4.2.5.Final + 1.9.1.RELEASE + 1.4 + 2.0.4 + 2.8.1 + 17.0 + 3.3.2 + 2.4 + 2.1 + 1.7.5 + 1.2.17 + 8.1.15.v20140411 + 1.4.180 + 4.10 + 1.9.0 + 1.4.12 + 5.22.0 + + UTF-8 + + + + + + + + + + + com.fasterxml.jackson.core + jackson-databind + 2.5.4 + + + + + org.activiti + activiti-engine + ${activiti.version} + + + org.activiti + activiti-spring + ${activiti.version} + + + org.activiti + activiti-json-converter + ${activiti.version} + + + + org.activiti + activiti-explorer + ${activiti.version} + + + vaadin + com.vaadin + + + dcharts-widget + org.vaadin.addons + + + activiti-simple-workflow + org.activiti + + + + + org.activiti + activiti-modeler + ${activiti.version} + + + org.activiti + activiti-rest + ${activiti.version} + + + org.activiti + activiti-diagram-rest + ${activiti.version} + + + org.activiti + activiti-cxf + ${activiti.version} + + + org.apache.tomcat + juli + 6.0.47 + + + + + org.apache.cxf + cxf-api + 2.7.6 + + + org.apache.cxf + cxf-rt-frontend-jaxws + 2.7.6 + + + org.apache.cxf + cxf-rt-transports-http-jetty + 2.7.6 + test + + + org.apache.cxf + cxf-rt-transports-http + 2.7.6 + + + com.sun.xml.bind + jaxb-impl + 2.2.11 + + + + + org.infinispan + infinispan-core + 5.1.7.Final + + + + + commons-io + commons-io + ${commons-io.version} + + + commons-fileupload + commons-fileupload + 1.2.2 + + + + + + org.springframework + spring-core + ${spring.version} + + + commons-logging + commons-logging + + + + + org.springframework + spring-beans + ${spring.version} + + + org.springframework + spring-context + ${spring.version} + + + org.springframework + spring-context-support + ${spring.version} + + + org.springframework + spring-aop + ${spring.version} + + + org.aspectj + aspectjrt + 1.6.9 + + + org.aspectj + aspectjweaver + 1.6.9 + + + cglib + cglib + 2.2.2 + + + asm + asm + 3.3.1 + + + + + + + org.hibernate + hibernate-core + ${hibernate.version} + + + org.hibernate + hibernate-entitymanager + ${hibernate.version} + + + org.hibernate.javax.persistence + hibernate-jpa-2.0-api + 1.0.1.Final + + + + + org.springframework.data + spring-data-jpa + ${spring-data-jpa.version} + + + junit + junit-dep + + + + + org.springframework + spring-orm + ${spring.version} + + + org.springframework + spring-jdbc + ${spring.version} + + + + + org.apache.commons + commons-dbcp2 + 2.0.1 + + + + + ${jdbc.driver.groupId} + ${jdbc.driver.artifactId} + ${jdbc.driver.version} + runtime + + + + + + org.springframework + spring-web + ${spring.version} + + + org.springframework + spring-webmvc + ${spring.version} + + + + javax.servlet + jstl + 1.2 + + + + javax.servlet + javax.servlet-api + 3.1.0 + provided + + + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + org.slf4j + slf4j-log4j12 + ${slf4j.version} + + + org.slf4j + jcl-over-slf4j + ${slf4j.version} + + + log4j + log4j + ${log4j.version} + + + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + commons-beanutils + commons-beanutils + 1.8.3 + + + commons-logging + commons-logging + + + + + + com.google.guava + guava + ${guava.version} + + + org.jodd + jodd + 3.3.2 + + + joda-time + joda-time + ${joda-time.version} + + + + + com.fasterxml.uuid + java-uuid-generator + 3.1.3 + + + + + + junit + junit + ${junit.version} + test + + + + org.mockito + mockito-core + ${mockito.version} + test + + + + org.powermock + powermock-module-junit4 + ${powermock.version} + test + + + org.powermock + powermock-api-mockito + ${powermock.version} + test + + + org.mockito + mockito-all + + + + + + org.springframework + spring-test + ${spring.version} + + + + com.h2database + h2 + ${h2.version} + + + + org.dbunit + dbunit + 2.4.8 + + + + + org.eclipse.jetty.aggregate + jetty-webapp + ${jetty.version} + test + + + org.eclipse.jetty + jetty-jsp + ${jetty.version} + test + + + + + + + + src/main/resources + true + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + ${jdk.version} + ${jdk.version} + true + + + + + + org.apache.maven.plugins + maven-eclipse-plugin + 2.9 + + 2.0 + + org.springframework.ide.eclipse.core.springnature + + + + + + + org.mortbay.jetty + jetty-maven-plugin + ${jetty.version} + + + /${project.artifactId} + + kad + 9999 + + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.6 + + + + zip + bar + png + bpmn + + ${project.build.sourceEncoding} + + + + + + org.apache.tomcat.maven + tomcat7-maven-plugin + 2.2 + + /${project.artifactId} + + -Xms1024m -Xmx2048m -XX:PermSize=512m -XX:MaxPermSize=1024m -Dfile.encoding=UTF-8 + + + + + + kft-activiti-demo + + + + + + h2 + + h2 + + + com.h2database + h2 + 1.4.190 + + + org.h2.Driver + jdbc:h2:file:~/kft-activiti-demo;AUTO_SERVER=TRUE + sa + + org.hibernate.dialect.H2Dialect + + + true + + + + + src/main/resources + true + + + + + + + + mysql + + mysql + + + mysql + mysql-connector-java + 5.1.11 + + + com.mysql.jdbc.Driver + + root + root + org.hibernate.dialect.MySQL5InnoDBDialect + + + + + src/main/resources + true + + + + + diff --git a/src/main/java/me/kafeitu/demo/activiti/activiti/DbInitConfigurator.java b/src/main/java/me/kafeitu/demo/activiti/activiti/DbInitConfigurator.java new file mode 100644 index 0000000000..4c4ec3f647 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/activiti/DbInitConfigurator.java @@ -0,0 +1,29 @@ +package me.kafeitu.demo.activiti.activiti; + +import org.activiti.engine.cfg.ProcessEngineConfigurator; +import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.activiti.engine.impl.db.DbSqlSessionFactory; + +/** + * @author 三寻 + * @version 1.0 + * @date 16/8/19 + */ +public class DbInitConfigurator implements ProcessEngineConfigurator { + + @Override + public void beforeInit(ProcessEngineConfigurationImpl processEngineConfiguration) { + DbSqlSessionFactory.databaseSpecificLimitAfterStatements.put("h2", "LIMIT #{firstResult},#{maxResults}"); + DbSqlSessionFactory.databaseSpecificLimitAfterStatements.put("mysql", "LIMIT #{firstResult},#{maxResults}"); + } + + @Override + public void configure(ProcessEngineConfigurationImpl processEngineConfiguration) { + + } + + @Override + public int getPriority() { + return 0; + } +} diff --git a/src/main/java/me/kafeitu/demo/activiti/activiti/form/UsersFormType.java b/src/main/java/me/kafeitu/demo/activiti/activiti/form/UsersFormType.java index 61795b8aa5..c9a1ab8367 100644 --- a/src/main/java/me/kafeitu/demo/activiti/activiti/form/UsersFormType.java +++ b/src/main/java/me/kafeitu/demo/activiti/activiti/form/UsersFormType.java @@ -1,32 +1,32 @@ package me.kafeitu.demo.activiti.activiti.form; -import java.util.Arrays; - -import org.activiti.engine.impl.form.AbstractFormType; +import org.activiti.engine.form.AbstractFormType; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import java.util.Arrays; + /** * 用户表单字段类型 - * + * * @author henryyan */ public class UsersFormType extends AbstractFormType { - @Override - public String getName() { - return "users"; - } + @Override + public String getName() { + return "users"; + } - @Override - public Object convertFormValueToModelValue(String propertyValue) { - String[] split = StringUtils.split(propertyValue, ","); - return Arrays.asList(split); - } + @Override + public Object convertFormValueToModelValue(String propertyValue) { + String[] split = StringUtils.split(propertyValue, ","); + return Arrays.asList(split); + } - @Override - public String convertModelValueToFormValue(Object modelValue) { - return ObjectUtils.toString(modelValue); - } + @Override + public String convertModelValueToFormValue(Object modelValue) { + return ObjectUtils.toString(modelValue); + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/activiti/listener/GlobalTaskListener.java b/src/main/java/me/kafeitu/demo/activiti/activiti/listener/GlobalTaskListener.java new file mode 100644 index 0000000000..eee58d870b --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/activiti/listener/GlobalTaskListener.java @@ -0,0 +1,21 @@ +package me.kafeitu.demo.activiti.activiti.listener; + +import org.activiti.engine.delegate.DelegateTask; +import org.activiti.engine.delegate.TaskListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * User: henryyan + */ +public class GlobalTaskListener implements TaskListener { + + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public void notify(DelegateTask delegateTask) { + logger.debug("触发了全局监听器, pid={}, tid={}, event={}", new Object[]{ + delegateTask.getProcessInstanceId(), delegateTask.getId(), delegateTask.getEventName() + }); + } +} diff --git a/src/main/java/me/kafeitu/demo/activiti/cmd/JumpActivityCmd.java b/src/main/java/me/kafeitu/demo/activiti/cmd/JumpActivityCmd.java new file mode 100644 index 0000000000..297c637919 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/cmd/JumpActivityCmd.java @@ -0,0 +1,41 @@ +package me.kafeitu.demo.activiti.cmd; + +/** + * @author: Henry Yan + */ + +import org.activiti.engine.impl.interceptor.Command; +import org.activiti.engine.impl.interceptor.CommandContext; +import org.activiti.engine.impl.persistence.entity.ExecutionEntity; +import org.activiti.engine.impl.pvm.process.ActivityImpl; +import org.activiti.engine.impl.pvm.process.ProcessDefinitionImpl; + +public class JumpActivityCmd implements Command { + private String activityId; + private String processInstanceId; + private String jumpOrigin; + + public JumpActivityCmd(String processInstanceId, String activityId) { + this(processInstanceId, activityId, "jump"); + } + + public JumpActivityCmd(String processInstanceId, String activityId, String jumpOrigin) { + this.activityId = activityId; + this.processInstanceId = processInstanceId; + this.jumpOrigin = jumpOrigin; + } + + public Object execute(CommandContext commandContext) { + + ExecutionEntity executionEntity = commandContext.getExecutionEntityManager().findExecutionById(processInstanceId); + + executionEntity.destroyScope(jumpOrigin); + + ProcessDefinitionImpl processDefinition = executionEntity.getProcessDefinition(); + ActivityImpl activity = processDefinition.findActivity(activityId); + + executionEntity.executeActivity(activity); + + return executionEntity; + } +} diff --git a/src/main/java/me/kafeitu/demo/activiti/conf/DemoDataInitConfig.java b/src/main/java/me/kafeitu/demo/activiti/conf/DemoDataInitConfig.java new file mode 100644 index 0000000000..2c927bdbc9 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/conf/DemoDataInitConfig.java @@ -0,0 +1,207 @@ +package me.kafeitu.demo.activiti.conf; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; +import java.util.List; +import javax.annotation.PostConstruct; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import me.kafeitu.demo.activiti.util.PropertyFileUtil; +import org.activiti.engine.IdentityService; +import org.activiti.engine.ManagementService; +import org.activiti.engine.RepositoryService; +import org.activiti.engine.RuntimeService; +import org.activiti.engine.TaskService; +import org.activiti.engine.identity.Group; +import org.activiti.engine.identity.Picture; +import org.activiti.engine.identity.User; +import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.activiti.engine.impl.util.IoUtil; +import org.activiti.engine.repository.Deployment; +import org.activiti.engine.repository.Model; +import org.apache.commons.io.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +/** + * 自动初始化演示数据 + * + * @author Henry Yan + */ +@Component +public class DemoDataInitConfig { + + protected static final Logger LOGGER = LoggerFactory.getLogger(DemoDataInitConfig.class); + + @Autowired + protected IdentityService identityService; + + @Autowired + protected RepositoryService repositoryService; + + @Autowired + protected RuntimeService runtimeService; + + @Autowired + protected TaskService taskService; + + @Autowired + protected ManagementService managementService; + + @Autowired + protected ProcessEngineConfigurationImpl processEngineConfiguration; + + @PostConstruct + public void init() { + + try { + PropertyFileUtil.init(); + } catch (IOException e) { + e.printStackTrace(); + } + + if (Boolean.valueOf(PropertyFileUtil.get("create.demo.users", "true"))) { + LOGGER.info("Initializing demo groups"); + initDemoGroups(); + LOGGER.info("Initializing demo users"); + initDemoUsers(); + } + + if (Boolean.valueOf(PropertyFileUtil.get("create.demo.definitions", "true"))) { + LOGGER.info("Initializing demo process definitions"); + initProcessDefinitions(); + } + + if (Boolean.valueOf(PropertyFileUtil.get("create.demo.models", "true"))) { + LOGGER.info("Initializing demo models"); + initModelData(); + } + } + + protected void initDemoGroups() { + String[] assignmentGroups = new String[]{"deptLeader", "hr"}; + for (String groupId : assignmentGroups) { + createGroup(groupId, "assignment"); + } + + String[] securityGroups = new String[]{"user", "admin"}; + for (String groupId : securityGroups) { + createGroup(groupId, "security-role"); + } + } + + protected void createGroup(String groupId, String type) { + if (identityService.createGroupQuery().groupId(groupId).count() == 0) { + Group newGroup = identityService.newGroup(groupId); + newGroup.setName(groupId.substring(0, 1).toUpperCase() + groupId.substring(1)); + newGroup.setType(type); + identityService.saveGroup(newGroup); + } + } + + protected void initDemoUsers() { + createUser("admin", "Henry", "Yan", "000000", "henry.yan@kafeitu.me", + "", Arrays.asList("user", "admin"), null); + + createUser("hruser", "Lili", "Zhang", "000000", "lili.zhang@kafeitu.me", + "", Arrays.asList("hr", "user"), null); + + createUser("leaderuser", "Jhon", "Li", "000000", "jhon.li@kafeitu.me", + "", Arrays.asList("deptLeader", "user"), null); + + createUser("kafeitu", "Coffee", "Rabbit", "000000", "coffee.rabbit@kafeitu.me", + "", Arrays.asList("user", "admin"), null); + } + + protected void createUser(String userId, String firstName, String lastName, String password, + String email, String imageResource, List groups, List userInfo) { + + if (identityService.createUserQuery().userId(userId).count() == 0) { + + // Following data can already be set by demo setup script + + User user = identityService.newUser(userId); + user.setFirstName(firstName); + user.setLastName(lastName); + user.setPassword(password); + user.setEmail(email); + identityService.saveUser(user); + + if (groups != null) { + for (String group : groups) { + identityService.createMembership(userId, group); + } + } + } + + // Following data is not set by demo setup script + + // image + if (imageResource != null) { + byte[] pictureBytes = IoUtil.readInputStream(this.getClass().getClassLoader().getResourceAsStream(imageResource), null); + Picture picture = new Picture(pictureBytes, "image/jpeg"); + identityService.setUserPicture(userId, picture); + } + + // user info + if (userInfo != null) { + for (int i = 0; i < userInfo.size(); i += 2) { + identityService.setUserInfo(userId, userInfo.get(i), userInfo.get(i + 1)); + } + } + + } + + protected void initProcessDefinitions() { + + String deploymentName = "Demo processes"; + List deploymentList = repositoryService.createDeploymentQuery().deploymentName(deploymentName).list(); + + if (deploymentList == null || deploymentList.isEmpty()) { + repositoryService.createDeployment() + .name(deploymentName) + .addClasspathResource("diagrams/leave/leave.bpmn") + .addClasspathResource("diagrams/leave/leave.png") + .deploy(); + } + } + + protected void initModelData() { + createModelData("Demo model", "This is a demo model", "models/leave.model.json"); + } + + protected void createModelData(String name, String description, String jsonFile) { + List modelList = repositoryService.createModelQuery().modelName("Demo model").list(); + + if (modelList == null || modelList.isEmpty()) { + + Model model = repositoryService.newModel(); + model.setName(name); + + ObjectNode modelObjectNode = new ObjectMapper().createObjectNode(); + modelObjectNode.put("name", name); + modelObjectNode.put("description", description); + model.setMetaInfo(modelObjectNode.toString()); + + repositoryService.saveModel(model); + + try { + InputStream svgStream = this.getClass().getClassLoader().getResourceAsStream("models/leave.model.svg"); + repositoryService.addModelEditorSourceExtra(model.getId(), IOUtils.toByteArray(svgStream)); + } catch (Exception e) { + LOGGER.warn("Failed to read SVG", e); + } + + try { + InputStream editorJsonStream = this.getClass().getClassLoader().getResourceAsStream(jsonFile); + repositoryService.addModelEditorSource(model.getId(), IOUtils.toByteArray(editorJsonStream)); + } catch (Exception e) { + LOGGER.warn("Failed to read editor JSON", e); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/dao/ActivitiDao.java b/src/main/java/me/kafeitu/demo/activiti/dao/ActivitiDao.java new file mode 100644 index 0000000000..bf67284a1d --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/dao/ActivitiDao.java @@ -0,0 +1,29 @@ +package me.kafeitu.demo.activiti.dao; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.springframework.stereotype.Component; + +/** + * Activiti相关DAO操作 + * @author: Henry Yan + */ +@Component +public class ActivitiDao { + + @PersistenceContext + private EntityManager entityManager; + + /** + * 流程完成后清理detail表中的表单类型数据 + * @param processInstanceId + * @return + */ + public int deleteFormPropertyByProcessInstanceId(String processInstanceId) { + int i = entityManager.createNativeQuery("delete from act_hi_detail where proc_inst_id_ = ? and type_ = 'FormProperty' ") + .setParameter(1, processInstanceId).executeUpdate(); + return i; + } + +} diff --git a/src/main/java/me/kafeitu/demo/activiti/dao/LeaveDao.java b/src/main/java/me/kafeitu/demo/activiti/dao/LeaveDao.java index f5bf474fbf..135c1eb773 100644 --- a/src/main/java/me/kafeitu/demo/activiti/dao/LeaveDao.java +++ b/src/main/java/me/kafeitu/demo/activiti/dao/LeaveDao.java @@ -1,7 +1,6 @@ package me.kafeitu.demo.activiti.dao; import me.kafeitu.demo.activiti.entity.oa.Leave; - import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Component; diff --git a/src/main/java/me/kafeitu/demo/activiti/entity/IdEntity.java b/src/main/java/me/kafeitu/demo/activiti/entity/IdEntity.java index 65a63bc1c2..f94e6b608d 100644 --- a/src/main/java/me/kafeitu/demo/activiti/entity/IdEntity.java +++ b/src/main/java/me/kafeitu/demo/activiti/entity/IdEntity.java @@ -7,28 +7,28 @@ /** * 统一定义id的entity基类. - * + *

* 基类统一定义id的属性名称、数据类型、列名映射及生成策略. * 子类可重载getId()函数重定义id的列名映射和生成策略. - * + * * @author calvin */ //JPA 基类的标识 @MappedSuperclass public abstract class IdEntity { - protected Long id; + protected Long id; - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - //@GeneratedValue(strategy = GenerationType.SEQUENCE) - //@GeneratedValue(generator = "system-uuid") - //@GenericGenerator(name = "system-uuid", strategy = "uuid") - public Long getId() { - return id; - } + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + //@GeneratedValue(strategy = GenerationType.SEQUENCE) + //@GeneratedValue(generator = "system-uuid") + //@GenericGenerator(name = "system-uuid", strategy = "uuid") + public Long getId() { + return id; + } - public void setId(Long id) { - this.id = id; - } + public void setId(Long id) { + this.id = id; + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/entity/account/Group.java b/src/main/java/me/kafeitu/demo/activiti/entity/account/Group.java index 51442a210c..dfa0e000af 100644 --- a/src/main/java/me/kafeitu/demo/activiti/entity/account/Group.java +++ b/src/main/java/me/kafeitu/demo/activiti/entity/account/Group.java @@ -1,69 +1,71 @@ package me.kafeitu.demo.activiti.entity.account; +import javax.persistence.*; import java.io.Serializable; import java.util.List; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.ManyToMany; -import javax.persistence.Table; - /** * The persistent class for the ACT_ID_GROUP database table. - * */ @Entity @Table(name = "ACT_ID_GROUP") public class Group implements Serializable { - private static final long serialVersionUID = 1L; - private String id; - private String name; - private String type; - private List actIdUsers; + private static final long serialVersionUID = 1L; + private String id; + private Integer rev; + private String name; + private String type; + private List actIdUsers; + + public Group() { + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "ID_") + public String getId() { + return this.id; + } - public Group() { - } + public void setId(String id) { + this.id = id; + } - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - @Column(name = "ID_") - public String getId() { - return this.id; - } + @Column(name = "REV_") + public Integer getRev() { + return this.rev; + } - public void setId(String id) { - this.id = id; - } + public void setRev(Integer rev) { + this.rev = rev; + } - @Column(name = "NAME_") - public String getName() { - return this.name; - } + @Column(name = "NAME_") + public String getName() { + return this.name; + } - public void setName(String name) { - this.name = name; - } + public void setName(String name) { + this.name = name; + } - @Column(name = "TYPE_") - public String getType() { - return this.type; - } + @Column(name = "TYPE_") + public String getType() { + return this.type; + } - public void setType(String type) { - this.type = type; - } + public void setType(String type) { + this.type = type; + } - //bi-directional many-to-many association to User - @ManyToMany(mappedBy = "actIdGroups") - public List getActIdUsers() { - return this.actIdUsers; - } + //bi-directional many-to-many association to User + @ManyToMany(mappedBy = "actIdGroups") + public List getActIdUsers() { + return this.actIdUsers; + } - public void setActIdUsers(List actIdUsers) { - this.actIdUsers = actIdUsers; - } + public void setActIdUsers(List actIdUsers) { + this.actIdUsers = actIdUsers; + } } \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/entity/account/User.java b/src/main/java/me/kafeitu/demo/activiti/entity/account/User.java index b3ef19846f..5cd27f28fa 100644 --- a/src/main/java/me/kafeitu/demo/activiti/entity/account/User.java +++ b/src/main/java/me/kafeitu/demo/activiti/entity/account/User.java @@ -1,92 +1,82 @@ package me.kafeitu.demo.activiti.entity.account; +import javax.persistence.*; import java.io.Serializable; import java.util.List; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; -import javax.persistence.JoinColumn; -import javax.persistence.JoinTable; -import javax.persistence.ManyToMany; -import javax.persistence.Table; - /** * The persistent class for the ACT_ID_USER database table. - * */ @Entity @Table(name = "ACT_ID_USER") public class User implements Serializable { - private static final long serialVersionUID = 1L; - private String id; - private String email; - private String first; - private String last; - private String password; - private List actIdGroups; - - public User() { - } - - @Id - @GeneratedValue(strategy = GenerationType.AUTO) - @Column(name = "ID_") - public String getId() { - return this.id; - } - - public void setId(String id) { - this.id = id; - } - - @Column(name = "EMAIL_") - public String getEmail() { - return this.email; - } - - public void setEmail(String email) { - this.email = email; - } - - @Column(name = "FIRST_") - public String getFirst() { - return this.first; - } - - public void setFirst(String first) { - this.first = first; - } - - @Column(name = "LAST_") - public String getLast() { - return this.last; - } - - public void setLast(String last) { - this.last = last; - } - - @Column(name = "PWD_") - public String getPassword() { - return this.password; - } - - public void setPassword(String password) { - this.password = password; - } - - //bi-directional many-to-many association to Group - @ManyToMany - @JoinTable(name = "ACT_ID_MEMBERSHIP", joinColumns = { @JoinColumn(name = "USER_ID_") }, inverseJoinColumns = { @JoinColumn(name = "GROUP_ID_") }) - public List getActIdGroups() { - return this.actIdGroups; - } - - public void setActIdGroups(List actIdGroups) { - this.actIdGroups = actIdGroups; - } + private static final long serialVersionUID = 1L; + private String id; + private String email; + private String first; + private String last; + private String password; + private List actIdGroups; + + public User() { + } + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + @Column(name = "ID_") + public String getId() { + return this.id; + } + + public void setId(String id) { + this.id = id; + } + + @Column(name = "EMAIL_") + public String getEmail() { + return this.email; + } + + public void setEmail(String email) { + this.email = email; + } + + @Column(name = "FIRST_") + public String getFirst() { + return this.first; + } + + public void setFirst(String first) { + this.first = first; + } + + @Column(name = "LAST_") + public String getLast() { + return this.last; + } + + public void setLast(String last) { + this.last = last; + } + + @Column(name = "PWD_") + public String getPassword() { + return this.password; + } + + public void setPassword(String password) { + this.password = password; + } + + //bi-directional many-to-many association to Group + @ManyToMany + @JoinTable(name = "ACT_ID_MEMBERSHIP", joinColumns = {@JoinColumn(name = "USER_ID_")}, inverseJoinColumns = {@JoinColumn(name = "GROUP_ID_")}) + public List getActIdGroups() { + return this.actIdGroups; + } + + public void setActIdGroups(List actIdGroups) { + this.actIdGroups = actIdGroups; + } } \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/entity/oa/Leave.java b/src/main/java/me/kafeitu/demo/activiti/entity/oa/Leave.java index a371989aab..c7e352b0fd 100644 --- a/src/main/java/me/kafeitu/demo/activiti/entity/oa/Leave.java +++ b/src/main/java/me/kafeitu/demo/activiti/entity/oa/Leave.java @@ -1,197 +1,190 @@ package me.kafeitu.demo.activiti.entity.oa; -import java.io.Serializable; -import java.util.Date; -import java.util.Map; - -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Table; -import javax.persistence.Temporal; -import javax.persistence.TemporalType; -import javax.persistence.Transient; - import me.kafeitu.demo.activiti.entity.IdEntity; - import org.activiti.engine.history.HistoricProcessInstance; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.springframework.format.annotation.DateTimeFormat; +import javax.persistence.*; +import java.io.Serializable; +import java.util.Date; +import java.util.Map; + /** * Entity: Leave - * + * * @author HenryYan */ @Entity @Table(name = "OA_LEAVE") public class Leave extends IdEntity implements Serializable { - private static final long serialVersionUID = 1L; - private String processInstanceId; - private String userId; - - @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") - private Date startTime; - - @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") - private Date endTime; - - @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") - private Date realityStartTime; - - @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") - private Date realityEndTime; - private Date applyTime; - private String leaveType; - private String reason; - - //-- 临时属性 --// - - // 流程任务 - private Task task; - - private Map variables; - - // 运行中的流程实例 - private ProcessInstance processInstance; - - // 历史的流程实例 - private HistoricProcessInstance historicProcessInstance; - - // 流程定义 - private ProcessDefinition processDefinition; - - @Column - public String getProcessInstanceId() { - return processInstanceId; - } - - public void setProcessInstanceId(String processInstanceId) { - this.processInstanceId = processInstanceId; - } - - @Column - public String getUserId() { - return userId; - } - - public void setUserId(String userId) { - this.userId = userId; - } - - @Temporal(TemporalType.TIMESTAMP) - @Column(name = "START_TIME") - public Date getStartTime() { - return startTime; - } - - public void setStartTime(Date startTime) { - this.startTime = startTime; - } - - @Temporal(TemporalType.TIMESTAMP) - @Column(name = "END_TIME") - public Date getEndTime() { - return endTime; - } - - public void setEndTime(Date endTime) { - this.endTime = endTime; - } - - @Column - @Temporal(TemporalType.TIMESTAMP) - public Date getApplyTime() { - return applyTime; - } - - public void setApplyTime(Date applyTime) { - this.applyTime = applyTime; - } - - @Column - public String getLeaveType() { - return leaveType; - } - - public void setLeaveType(String leaveType) { - this.leaveType = leaveType; - } - - @Column - public String getReason() { - return reason; - } - - public void setReason(String reason) { - this.reason = reason; - } - - @Temporal(TemporalType.TIMESTAMP) - @Column(name = "REALITY_START_TIME") - public Date getRealityStartTime() { - return realityStartTime; - } - - public void setRealityStartTime(Date realityStartTime) { - this.realityStartTime = realityStartTime; - } - - @Temporal(TemporalType.TIMESTAMP) - @Column(name = "REALITY_END_TIME") - public Date getRealityEndTime() { - return realityEndTime; - } - - public void setRealityEndTime(Date realityEndTime) { - this.realityEndTime = realityEndTime; - } - - @Transient - public Task getTask() { - return task; - } - - public void setTask(Task task) { - this.task = task; - } - - @Transient - public Map getVariables() { - return variables; - } - - public void setVariables(Map variables) { - this.variables = variables; - } - - @Transient - public ProcessInstance getProcessInstance() { - return processInstance; - } - - public void setProcessInstance(ProcessInstance processInstance) { - this.processInstance = processInstance; - } - - @Transient - public HistoricProcessInstance getHistoricProcessInstance() { - return historicProcessInstance; - } - - public void setHistoricProcessInstance(HistoricProcessInstance historicProcessInstance) { - this.historicProcessInstance = historicProcessInstance; - } - - @Transient - public ProcessDefinition getProcessDefinition() { - return processDefinition; - } - - public void setProcessDefinition(ProcessDefinition processDefinition) { - this.processDefinition = processDefinition; - } + private static final long serialVersionUID = 1L; + private String processInstanceId; + private String userId; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") + private Date startTime; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") + private Date endTime; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") + private Date realityStartTime; + + @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") + private Date realityEndTime; + private Date applyTime; + private String leaveType; + private String reason; + + //-- 临时属性 --// + + // 流程任务 + private Task task; + + private Map variables; + + // 运行中的流程实例 + private ProcessInstance processInstance; + + // 历史的流程实例 + private HistoricProcessInstance historicProcessInstance; + + // 流程定义 + private ProcessDefinition processDefinition; + + @Column + public String getProcessInstanceId() { + return processInstanceId; + } + + public void setProcessInstanceId(String processInstanceId) { + this.processInstanceId = processInstanceId; + } + + @Column + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "START_TIME") + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "END_TIME") + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + + @Column + @Temporal(TemporalType.TIMESTAMP) + public Date getApplyTime() { + return applyTime; + } + + public void setApplyTime(Date applyTime) { + this.applyTime = applyTime; + } + + @Column + public String getLeaveType() { + return leaveType; + } + + public void setLeaveType(String leaveType) { + this.leaveType = leaveType; + } + + @Column + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "REALITY_START_TIME") + public Date getRealityStartTime() { + return realityStartTime; + } + + public void setRealityStartTime(Date realityStartTime) { + this.realityStartTime = realityStartTime; + } + + @Temporal(TemporalType.TIMESTAMP) + @Column(name = "REALITY_END_TIME") + public Date getRealityEndTime() { + return realityEndTime; + } + + public void setRealityEndTime(Date realityEndTime) { + this.realityEndTime = realityEndTime; + } + + @Transient + public Task getTask() { + return task; + } + + public void setTask(Task task) { + this.task = task; + } + + @Transient + public Map getVariables() { + return variables; + } + + public void setVariables(Map variables) { + this.variables = variables; + } + + @Transient + public ProcessInstance getProcessInstance() { + return processInstance; + } + + public void setProcessInstance(ProcessInstance processInstance) { + this.processInstance = processInstance; + } + + @Transient + public HistoricProcessInstance getHistoricProcessInstance() { + return historicProcessInstance; + } + + public void setHistoricProcessInstance(HistoricProcessInstance historicProcessInstance) { + this.historicProcessInstance = historicProcessInstance; + } + + @Transient + public ProcessDefinition getProcessDefinition() { + return processDefinition; + } + + public void setProcessDefinition(ProcessDefinition processDefinition) { + this.processDefinition = processDefinition; + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/entity/oa/LeaveJpaEntity.java b/src/main/java/me/kafeitu/demo/activiti/entity/oa/LeaveJpaEntity.java new file mode 100644 index 0000000000..8a57283b49 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/entity/oa/LeaveJpaEntity.java @@ -0,0 +1,166 @@ +package me.kafeitu.demo.activiti.entity.oa; + +import java.io.Serializable; +import java.util.Date; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +import org.apache.commons.lang3.builder.ToStringBuilder; + +/** + * 请假的JPA映射实体 + * + * @author: Henry Yan + */ +@Entity(name = "LEAVE_JPA") +public class LeaveJpaEntity implements Serializable { + + private Long id; + private String processInstanceId; + private String userId; + private Date startTime; + private Date endTime; + private Date realityStartTime; + private Date realityEndTime; + private Date reportBackDate; + private Date applyTime; + private String leaveType; + private String reason; + + /** + * 部门领导是否同意 + */ + private String deptLeaderApproved; + + /** + * HR是否同意 + */ + private String hrApproved; + + @Id + @Column(name="ID") + @GeneratedValue(strategy = GenerationType.AUTO) + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + @Column(name = "APPLY_TIME") + public Date getApplyTime() { + return applyTime; + } + + public void setApplyTime(Date applyTime) { + this.applyTime = applyTime; + } + + @Column(name = "END_TIME") + public Date getEndTime() { + return endTime; + } + + public void setEndTime(Date endTime) { + this.endTime = endTime; + } + + @Column(name = "LEAVE_TYPE") + public String getLeaveType() { + return leaveType; + } + + public void setLeaveType(String leaveType) { + this.leaveType = leaveType; + } + + @Column(name = "PROCESS_INSTANCE_ID") + public String getProcessInstanceId() { + return processInstanceId; + } + + public void setProcessInstanceId(String processInstanceId) { + this.processInstanceId = processInstanceId; + } + + @Column(name = "REALITY_END_TIME") + public Date getRealityEndTime() { + return realityEndTime; + } + + public void setRealityEndTime(Date realityEndTime) { + this.realityEndTime = realityEndTime; + } + + @Column(name = "REALITY_START_TIME") + public Date getRealityStartTime() { + return realityStartTime; + } + + public void setRealityStartTime(Date realityStartTime) { + this.realityStartTime = realityStartTime; + } + + @Column(name = "REASON") + public String getReason() { + return reason; + } + + public void setReason(String reason) { + this.reason = reason; + } + + @Column(name = "START_TIME") + public Date getStartTime() { + return startTime; + } + + public void setStartTime(Date startTime) { + this.startTime = startTime; + } + + @Column(name = "USER_ID") + public String getUserId() { + return userId; + } + + public void setUserId(String userId) { + this.userId = userId; + } + + @Column(name = "REPORT_BACK_DATE") + public Date getReportBackDate() { + return reportBackDate; + } + + public void setReportBackDate(Date reportBackDate) { + this.reportBackDate = reportBackDate; + } + + @Column + public String getDeptLeaderApproved() { + return deptLeaderApproved; + } + + public void setDeptLeaderApproved(String deptLeaderApproved) { + this.deptLeaderApproved = deptLeaderApproved; + } + + @Column + public String getHrApproved() { + return hrApproved; + } + + public void setHrApproved(String hrApproved) { + this.hrApproved = hrApproved; + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this); + } +} diff --git a/src/main/java/me/kafeitu/demo/activiti/service/SetMailInfo.java b/src/main/java/me/kafeitu/demo/activiti/service/SetMailInfo.java new file mode 100644 index 0000000000..5e9ad0f154 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/service/SetMailInfo.java @@ -0,0 +1,38 @@ +package me.kafeitu.demo.activiti.service; + +import java.util.Calendar; +import java.util.Date; + +import org.activiti.engine.IdentityService; +import org.activiti.engine.delegate.DelegateExecution; +import org.activiti.engine.delegate.ExecutionListener; +import org.activiti.engine.identity.User; + +/** + * 请假流程--邮件任务监听器,用于设置发送邮件时的一些变量 + * + * @author henryyan + */ +public class SetMailInfo implements ExecutionListener { + + private static final long serialVersionUID = 1L; + + @Override + public void notify(DelegateExecution execution) throws Exception { + IdentityService identityService = execution.getEngineServices().getIdentityService(); + String applyUserId = (String) execution.getVariable("applyUserId"); + User user = identityService.createUserQuery().userId(applyUserId).singleResult(); + String to = user.getEmail(); + execution.setVariableLocal("to", to); + String userName = user.getFirstName() + " " + user.getLastName(); + execution.setVariableLocal("name", userName); + + // 超时提醒时间设置,请假结束时间+1天 + Date endDate = (Date) execution.getVariable("endDate"); + Calendar ca = Calendar.getInstance(); + ca.setTime(endDate); + ca.add(Calendar.DAY_OF_MONTH, 1); + execution.setVariableLocal("reportBackTimeout", ca.getTime()); + } + +} \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowProcessDefinitionService.java b/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowProcessDefinitionService.java index 1d92319863..26770ad2b3 100644 --- a/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowProcessDefinitionService.java +++ b/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowProcessDefinitionService.java @@ -1,13 +1,11 @@ package me.kafeitu.demo.activiti.service.activiti; -import java.io.IOException; -import java.io.InputStream; -import java.util.zip.ZipInputStream; - +import me.kafeitu.demo.activiti.util.WorkflowUtils; import org.activiti.engine.HistoryService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.history.HistoricProcessInstance; +import org.activiti.engine.repository.Deployment; import org.activiti.engine.repository.ProcessDefinition; import org.apache.commons.lang3.ArrayUtils; import org.slf4j.Logger; @@ -18,128 +16,148 @@ import org.springframework.core.io.ResourceLoader; import org.springframework.stereotype.Service; +import java.io.IOException; +import java.io.InputStream; +import java.util.List; +import java.util.zip.ZipInputStream; + /** * 工作流中流程以及流程实例相关Service - * - * @author HenryYan * + * @author HenryYan */ @Service public class WorkflowProcessDefinitionService { - protected Logger logger = LoggerFactory.getLogger(getClass()); - - @Autowired - protected RuntimeService runtimeService; - - @Autowired - protected RepositoryService repositoryService; - - @Autowired - protected HistoryService historyService; - - /** - * 根据流程实例ID查询流程定义对象{@link ProcessDefinition} - * @param processInstanceId 流程实例ID - * @return 流程定义对象{@link ProcessDefinition} - */ - public ProcessDefinition findProcessDefinitionByPid(String processInstanceId) { - HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery() - .processInstanceId(processInstanceId).singleResult(); - String processDefinitionId = historicProcessInstance.getProcessDefinitionId(); - ProcessDefinition processDefinition = findProcessDefinition(processDefinitionId); - return processDefinition; - } - - /** - * 根据流程定义ID查询流程定义对象{@link ProcessDefinition} - * @param processDefinitionId 流程定义对象ID - * @return 流程定义对象{@link ProcessDefinition} - */ - public ProcessDefinition findProcessDefinition(String processDefinitionId) { - ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() - .processDefinitionId(processDefinitionId).singleResult(); - return processDefinition; - } - - /** - * 部署classpath下面的流程定义 - *

从属性配置文件中获取属性workflow.modules扫描**deployments**

- *

然后从每个**deployments/${module}**查找在属性配置文件中的属性**workflow.module.keys.${submodule}** - *

配置实例: - *

-	 *	#workflow for deploy
-	 *	workflow.modules=budget,erp,oa
-	 *	workflow.module.keys.budget=budget
-	 *	workflow.module.keys.erp=acceptInsurance,billing,effectInsurance,endorsement,payment
-	 *	workflow.module.keys.oa=caruse,leave,officalstamp,officesupply,out,overtime
-	 *	

- * @param processKey 流程定义KEY - * @throws Exception - */ - public void deployFromClasspath(String... processKey) throws Exception { - ResourceLoader resourceLoader = new DefaultResourceLoader(); - String[] processKeys = { "leave", "leave-dynamic-from", "leave-formkey", "dispatch" }; - for (String loopProcessKey : processKeys) { - - /* - * 需要过滤指定流程 - */ - if (ArrayUtils.isNotEmpty(processKey)) { - if (ArrayUtils.contains(processKey, loopProcessKey)) { - logger.debug("hit module of {}", processKey); - deploySingleProcess(resourceLoader, loopProcessKey); - } else { - logger.debug("module: {} not equals process key: {}, ignore and continue find next.", loopProcessKey, - processKey); - } - } else { - /* - * 所有流程 - */ - deploySingleProcess(resourceLoader, loopProcessKey); - } - } - } - - /** - * 部署单个流程定义 - * @param resourceLoader {@link ResourceLoader} - * @param processKey 模块名称 - * @param subModule 流程定义名称 - * @throws IOException 找不到zip文件时 - */ - private void deploySingleProcess(ResourceLoader resourceLoader, String processKey) throws IOException { - String classpathResourceUrl = "classpath:/deployments/" + processKey + ".bar"; - logger.debug("read workflow from: {}", classpathResourceUrl); - Resource resource = resourceLoader.getResource(classpathResourceUrl); - InputStream inputStream = resource.getInputStream(); - if (inputStream == null) { - logger.warn("ignore deploy workflow module: {}", classpathResourceUrl); - } else { - logger.debug("finded workflow module: {}, deploy it!", classpathResourceUrl); - ZipInputStream zis = new ZipInputStream(inputStream); - repositoryService.createDeployment().addZipInputStream(zis).deploy(); - } - } - - /** - * 重新部署单个流程定义 - * @param processKey 流程定义KEY - * @throws Exception - * @see #deployFromClasspath - */ - public void redeploy(String... processKey) throws Exception { - this.deployFromClasspath(processKey); - } - - /** - * 重新部署所有流程定义,调用:{@link #deployFromClasspath()}完成功能 - * @throws Exception - * @see #deployFromClasspath - */ - public void deployAllFromClasspath() throws Exception { - this.deployFromClasspath(); - } + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + protected RuntimeService runtimeService; + + @Autowired + protected RepositoryService repositoryService; + + @Autowired + protected HistoryService historyService; + + /** + * 根据流程实例ID查询流程定义对象{@link ProcessDefinition} + * + * @param processInstanceId 流程实例ID + * @return 流程定义对象{@link ProcessDefinition} + */ + public ProcessDefinition findProcessDefinitionByPid(String processInstanceId) { + HistoricProcessInstance historicProcessInstance = historyService.createHistoricProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + String processDefinitionId = historicProcessInstance.getProcessDefinitionId(); + ProcessDefinition processDefinition = findProcessDefinition(processDefinitionId); + return processDefinition; + } + + /** + * 根据流程定义ID查询流程定义对象{@link ProcessDefinition} + * + * @param processDefinitionId 流程定义对象ID + * @return 流程定义对象{@link ProcessDefinition} + */ + public ProcessDefinition findProcessDefinition(String processDefinitionId) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult(); + return processDefinition; + } + + /** + * 部署classpath下面的流程定义 + *

+ * 从属性配置文件中获取属性workflow.modules扫描**deployments** + *

+ *

+ * 然后从每个**deployments/${module}**查找在属性配置文件中的属性**workflow.module.keys.${ + * submodule}** + *

+ * 配置实例: + *

+ *

+     * #workflow for deploy
+     * workflow.modules=budget,erp,oa
+     * workflow.module.keys.budget=budget
+     * workflow.module.keys.erp=acceptInsurance,billing,effectInsurance,endorsement,payment
+     * workflow.module.keys.oa=caruse,leave,officalstamp,officesupply,out,overtime
+     * 
+ *

+ *

+ * + * @param processKey 流程定义KEY + * @throws Exception + */ + public void deployFromClasspath(String exportDir, String... processKey) throws Exception { + ResourceLoader resourceLoader = new DefaultResourceLoader(); + String[] processKeys = {"leave", "leave-dynamic-from", "leave-formkey", "dispatch"}; + for (String loopProcessKey : processKeys) { + + /* + * 需要过滤指定流程 + */ + if (ArrayUtils.isNotEmpty(processKey)) { + if (ArrayUtils.contains(processKey, loopProcessKey)) { + logger.debug("hit module of {}", (Object[]) processKey); + deploySingleProcess(resourceLoader, loopProcessKey, exportDir); + } else { + logger.debug("module: {} not equals process key: {}, ignore and continue find next.", loopProcessKey, processKey); + } + } else { + /* + * 所有流程 + */ + deploySingleProcess(resourceLoader, loopProcessKey, exportDir); + } + } + } + + /** + * 部署单个流程定义 + * + * @param resourceLoader {@link ResourceLoader} + * @param processKey 模块名称 + * @throws IOException 找不到zip文件时 + */ + private void deploySingleProcess(ResourceLoader resourceLoader, String processKey, String exportDir) throws IOException { + String classpathResourceUrl = "classpath:/deployments/" + processKey + ".bar"; + logger.debug("read workflow from: {}", classpathResourceUrl); + Resource resource = resourceLoader.getResource(classpathResourceUrl); + InputStream inputStream = resource.getInputStream(); + if (inputStream == null) { + logger.warn("ignore deploy workflow module: {}", classpathResourceUrl); + } else { + logger.debug("finded workflow module: {}, deploy it!", classpathResourceUrl); + ZipInputStream zis = new ZipInputStream(inputStream); + Deployment deployment = repositoryService.createDeployment().addZipInputStream(zis).deploy(); + + // export diagram + List list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list(); + for (ProcessDefinition processDefinition : list) { + WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir); + } + } + } + + /** + * 重新部署单个流程定义 + * + * @param processKey 流程定义KEY + * @throws Exception + * @see #deployFromClasspath + */ + public void redeploy(String exportDir, String... processKey) throws Exception { + this.deployFromClasspath(exportDir, processKey); + } + + /** + * 重新部署所有流程定义,调用:{@link #deployFromClasspath()}完成功能 + * + * @throws Exception + * @see #deployFromClasspath + */ + public void deployAllFromClasspath(String exportDir) throws Exception { + this.deployFromClasspath(exportDir); + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowTraceService.java b/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowTraceService.java index 65736b7b93..8eadf03dd2 100644 --- a/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowTraceService.java +++ b/src/main/java/me/kafeitu/demo/activiti/service/activiti/WorkflowTraceService.java @@ -1,13 +1,6 @@ package me.kafeitu.demo.activiti.service.activiti; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - import me.kafeitu.demo.activiti.util.WorkflowUtils; - import org.activiti.engine.IdentityService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; @@ -24,12 +17,14 @@ import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; import org.apache.commons.beanutils.PropertyUtils; -import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import java.util.*; + /** * 工作流跟踪相关Service * @@ -37,181 +32,184 @@ */ @Component public class WorkflowTraceService { - protected Logger logger = LoggerFactory.getLogger(getClass()); - - @Autowired - protected RuntimeService runtimeService; - - @Autowired - protected TaskService taskService; - - @Autowired - protected RepositoryService repositoryService; - - @Autowired - protected IdentityService identityService; - - /** - * 流程跟踪图 - * @param processInstanceId 流程实例ID - * @return 封装了各种节点信息 - */ - public List> traceProcess(String processInstanceId) throws Exception { - Execution execution = runtimeService.createExecutionQuery().executionId(processInstanceId).singleResult();//执行实例 - Object property = PropertyUtils.getProperty(execution, "activityId"); - String activityId = ""; - if (property != null) { - activityId = property.toString(); - } - ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId) - .singleResult(); - ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService) - .getDeployedProcessDefinition(processInstance.getProcessDefinitionId()); - List activitiList = processDefinition.getActivities();//获得当前任务的所有节点 - - List> activityInfos = new ArrayList>(); - for (ActivityImpl activity : activitiList) { - - boolean currentActiviti = false; - String id = activity.getId(); - - // 当前节点 - if (id.equals(activityId)) { - currentActiviti = true; - } - - Map activityImageInfo = packageSingleActivitiInfo(activity, processInstance, currentActiviti); - - activityInfos.add(activityImageInfo); - } - - return activityInfos; - } - - /** - * 封装输出信息,包括:当前节点的X、Y坐标、变量信息、任务类型、任务描述 - * @param activity - * @param processInstance - * @param currentActiviti - * @return - */ - private Map packageSingleActivitiInfo(ActivityImpl activity, ProcessInstance processInstance, - boolean currentActiviti) throws Exception { - Map vars = new HashMap(); - Map activityInfo = new HashMap(); - activityInfo.put("currentActiviti", currentActiviti); - setPosition(activity, activityInfo); - setWidthAndHeight(activity, activityInfo); - - Map properties = activity.getProperties(); - vars.put("任务类型", WorkflowUtils.parseToZhType(properties.get("type").toString())); - - ActivityBehavior activityBehavior = activity.getActivityBehavior(); - logger.debug("activityBehavior={}", activityBehavior); - if (activityBehavior instanceof UserTaskActivityBehavior) { - - Task currentTask = null; + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + protected RuntimeService runtimeService; + + @Autowired + protected TaskService taskService; + + @Autowired + protected RepositoryService repositoryService; + + @Autowired + protected IdentityService identityService; + + /** + * 流程跟踪图 + * + * @param processInstanceId 流程实例ID + * @return 封装了各种节点信息 + */ + public List> traceProcess(String processInstanceId) throws Exception { + Execution execution = runtimeService.createExecutionQuery().executionId(processInstanceId).singleResult();//执行实例 + Object property = PropertyUtils.getProperty(execution, "activityId"); + String activityId = ""; + if (property != null) { + activityId = property.toString(); + } + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId) + .singleResult(); + ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService) + .getDeployedProcessDefinition(processInstance.getProcessDefinitionId()); + List activitiList = processDefinition.getActivities();//获得当前任务的所有节点 + + List> activityInfos = new ArrayList>(); + for (ActivityImpl activity : activitiList) { + + boolean currentActiviti = false; + String id = activity.getId(); + + // 当前节点 + if (id.equals(activityId)) { + currentActiviti = true; + } + + Map activityImageInfo = packageSingleActivitiInfo(activity, processInstance, currentActiviti); + + activityInfos.add(activityImageInfo); + } + + return activityInfos; + } + + /** + * 封装输出信息,包括:当前节点的X、Y坐标、变量信息、任务类型、任务描述 + * + * @param activity + * @param processInstance + * @param currentActiviti + * @return + */ + private Map packageSingleActivitiInfo(ActivityImpl activity, ProcessInstance processInstance, + boolean currentActiviti) throws Exception { + Map vars = new HashMap(); + Map activityInfo = new HashMap(); + activityInfo.put("currentActiviti", currentActiviti); + setPosition(activity, activityInfo); + setWidthAndHeight(activity, activityInfo); + + Map properties = activity.getProperties(); + vars.put("任务类型", WorkflowUtils.parseToZhType(properties.get("type").toString())); + + ActivityBehavior activityBehavior = activity.getActivityBehavior(); + logger.debug("activityBehavior={}", activityBehavior); + if (activityBehavior instanceof UserTaskActivityBehavior) { + + Task currentTask = null; /* - * 当前节点的task + * 当前节点的task */ - if (currentActiviti) { - currentTask = getCurrentTaskInfo(processInstance); - } + if (currentActiviti) { + currentTask = getCurrentTaskInfo(processInstance); + } /* * 当前任务的分配角色 */ - UserTaskActivityBehavior userTaskActivityBehavior = (UserTaskActivityBehavior) activityBehavior; - TaskDefinition taskDefinition = userTaskActivityBehavior.getTaskDefinition(); - Set candidateGroupIdExpressions = taskDefinition.getCandidateGroupIdExpressions(); - if (!candidateGroupIdExpressions.isEmpty()) { - - // 任务的处理角色 - setTaskGroup(vars, candidateGroupIdExpressions); - - // 当前处理人 - if (currentTask != null) { - setCurrentTaskAssignee(vars, currentTask); - } - } - } - - vars.put("节点说明", properties.get("documentation")); - - String description = activity.getProcessDefinition().getDescription(); - vars.put("描述", description); - - logger.debug("trace variables: {}", vars); - activityInfo.put("vars", vars); - return activityInfo; - } - - private void setTaskGroup(Map vars, Set candidateGroupIdExpressions) { - String roles = ""; - for (Expression expression : candidateGroupIdExpressions) { - String expressionText = expression.getExpressionText(); - if (expressionText.startsWith("$")) { - expressionText = expressionText.replace("${insuranceType}", "life"); - } - String roleName = identityService.createGroupQuery().groupId(expressionText).singleResult().getName(); - roles += roleName; - } - vars.put("任务所属角色", roles); - } - - /** - * 设置当前处理人信息 - * @param vars - * @param currentTask - */ - private void setCurrentTaskAssignee(Map vars, Task currentTask) { - String assignee = currentTask.getAssignee(); - if (assignee != null) { - User assigneeUser = identityService.createUserQuery().userId(assignee).singleResult(); - String userInfo = assigneeUser.getFirstName() + " " + assigneeUser.getLastName(); - vars.put("当前处理人", userInfo); - } - } - - /** - * 获取当前节点信息 - * @param processInstance - * @return - */ - private Task getCurrentTaskInfo(ProcessInstance processInstance) { - Task currentTask = null; - try { - String activitiId = (String) PropertyUtils.getProperty(processInstance, "activityId"); - logger.debug("current activity id: {}", activitiId); - - currentTask = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskDefinitionKey(activitiId) - .singleResult(); - logger.debug("current task for processInstance: {}", ToStringBuilder.reflectionToString(currentTask)); - - } catch (Exception e) { - logger.error("can not get property activityId from processInstance: {}", processInstance); - } - return currentTask; - } - - /** - * 设置宽度、高度属性 - * @param activity - * @param activityInfo - */ - private void setWidthAndHeight(ActivityImpl activity, Map activityInfo) { - activityInfo.put("width", activity.getWidth()); - activityInfo.put("height", activity.getHeight()); - } - - /** - * 设置坐标位置 - * @param activity - * @param activityInfo - */ - private void setPosition(ActivityImpl activity, Map activityInfo) { - activityInfo.put("x", activity.getX()); - activityInfo.put("y", activity.getY()); - } + UserTaskActivityBehavior userTaskActivityBehavior = (UserTaskActivityBehavior) activityBehavior; + TaskDefinition taskDefinition = userTaskActivityBehavior.getTaskDefinition(); + Set candidateGroupIdExpressions = taskDefinition.getCandidateGroupIdExpressions(); + if (!candidateGroupIdExpressions.isEmpty()) { + + // 任务的处理角色 + setTaskGroup(vars, candidateGroupIdExpressions); + + // 当前处理人 + if (currentTask != null) { + setCurrentTaskAssignee(vars, currentTask); + } + } + } + + vars.put("节点说明", properties.get("documentation")); + + String description = activity.getProcessDefinition().getDescription(); + vars.put("描述", description); + + logger.debug("trace variables: {}", vars); + activityInfo.put("vars", vars); + return activityInfo; + } + + private void setTaskGroup(Map vars, Set candidateGroupIdExpressions) { + String roles = ""; + for (Expression expression : candidateGroupIdExpressions) { + String expressionText = expression.getExpressionText(); + String roleName = identityService.createGroupQuery().groupId(expressionText).singleResult().getName(); + roles += roleName; + } + vars.put("任务所属角色", roles); + } + + /** + * 设置当前处理人信息 + * + * @param vars + * @param currentTask + */ + private void setCurrentTaskAssignee(Map vars, Task currentTask) { + String assignee = currentTask.getAssignee(); + if (assignee != null) { + User assigneeUser = identityService.createUserQuery().userId(assignee).singleResult(); + String userInfo = assigneeUser.getFirstName() + " " + assigneeUser.getLastName(); + vars.put("当前处理人", userInfo); + } + } + + /** + * 获取当前节点信息 + * + * @param processInstance + * @return + */ + private Task getCurrentTaskInfo(ProcessInstance processInstance) { + Task currentTask = null; + try { + String activitiId = (String) PropertyUtils.getProperty(processInstance, "activityId"); + logger.debug("current activity id: {}", activitiId); + + currentTask = taskService.createTaskQuery().processInstanceId(processInstance.getId()).taskDefinitionKey(activitiId) + .singleResult(); + logger.debug("current task for processInstance: {}", ToStringBuilder.reflectionToString(currentTask)); + + } catch (Exception e) { + logger.error("can not get property activityId from processInstance: {}", processInstance); + } + return currentTask; + } + + /** + * 设置宽度、高度属性 + * + * @param activity + * @param activityInfo + */ + private void setWidthAndHeight(ActivityImpl activity, Map activityInfo) { + activityInfo.put("width", activity.getWidth()); + activityInfo.put("height", activity.getHeight()); + } + + /** + * 设置坐标位置 + * + * @param activity + * @param activityInfo + */ + private void setPosition(ActivityImpl activity, Map activityInfo) { + activityInfo.put("x", activity.getX()); + activityInfo.put("y", activity.getY()); + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/service/oa/dispatch/DispatchWorkflowService.java b/src/main/java/me/kafeitu/demo/activiti/service/oa/dispatch/DispatchWorkflowService.java index 99712b223f..b5fc327617 100644 --- a/src/main/java/me/kafeitu/demo/activiti/service/oa/dispatch/DispatchWorkflowService.java +++ b/src/main/java/me/kafeitu/demo/activiti/service/oa/dispatch/DispatchWorkflowService.java @@ -5,7 +5,7 @@ import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.runtime.Execution; -import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -13,53 +13,53 @@ /** * 发文会签流程Service - * + * * @author henryyan */ @Service public class DispatchWorkflowService { - private Logger logger = LoggerFactory.getLogger(getClass()); + private Logger logger = LoggerFactory.getLogger(getClass()); - @Autowired - protected RuntimeService runtimeService; + @Autowired + protected RuntimeService runtimeService; - @Autowired - protected TaskService taskService; + @Autowired + protected TaskService taskService; - @Autowired - protected HistoryService historyService; + @Autowired + protected HistoryService historyService; - @Autowired - private IdentityService identityService; + @Autowired + private IdentityService identityService; - /** - * 是否允许结束会签(多实例) - * 参数的含义请参考用户手册 - */ - public Boolean canComplete(Execution execution, Integer rate, Integer nrOfInstances, Integer nrOfActiveInstances, Integer nrOfCompletedInstances, - Integer loopCounter) { - String agreeCounterName = "agreeCounter"; - Object agreeCounter = runtimeService.getVariable(execution.getId(), agreeCounterName); - - if (agreeCounter == null) { - // 初始化计数器 - runtimeService.setVariable(execution.getId(), agreeCounterName, 1); - } else { - // 计数器累加 - Integer integerCounter = (Integer) runtimeService.getVariable(execution.getId(), agreeCounterName); - runtimeService.setVariable(execution.getId(), agreeCounterName, ++integerCounter); + /** + * 是否允许结束会签(多实例) + * 参数的含义请参考用户手册 + */ + public Boolean canComplete(Execution execution, Integer rate, Integer nrOfInstances, Integer nrOfActiveInstances, Integer nrOfCompletedInstances, + Integer loopCounter) { + String agreeCounterName = "agreeCounter"; + Object agreeCounter = runtimeService.getVariable(execution.getId(), agreeCounterName); + + if (agreeCounter == null) { + // 初始化计数器 + runtimeService.setVariable(execution.getId(), agreeCounterName, 1); + } else { + // 计数器累加 + Integer integerCounter = (Integer) runtimeService.getVariable(execution.getId(), agreeCounterName); + runtimeService.setVariable(execution.getId(), agreeCounterName, ++integerCounter); + } + + logger.debug("execution: {}" + ToStringBuilder.reflectionToString(execution)); + logger.debug("rate={}, nrOfInstances={}, nrOfActiveInstances={}, nrOfComptetedInstances={}, loopCounter={}", new Object[]{rate, nrOfInstances, + nrOfActiveInstances, nrOfCompletedInstances, loopCounter}); + + // 计算通过的比例,以此决定是否结束会签 + Double completeRate = new Double(nrOfCompletedInstances) / nrOfInstances; + boolean canComlete = completeRate * 100 >= rate; + logger.debug("rate: {}, completeRate: {}, canComlete={}", new Object[]{rate, completeRate, canComlete}); + return canComlete; } - - logger.debug("execution: {}" + ToStringBuilder.reflectionToString(execution)); - logger.debug("rate={}, nrOfInstances={}, nrOfActiveInstances={}, nrOfComptetedInstances={}, loopCounter={}", new Object[] { rate, nrOfInstances, - nrOfActiveInstances, nrOfCompletedInstances, loopCounter }); - - // 计算通过的比例,以此决定是否结束会签 - Double completeRate = new Double(nrOfCompletedInstances) / nrOfInstances; - boolean canComlete = completeRate * 100 >= rate; - logger.debug("rate: {}, completeRate: {}, canComlete={}", new Object[] { rate, completeRate, canComlete }); - return canComlete; - } } diff --git a/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/AfterModifyApplyContentProcessor.java b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/AfterModifyApplyContentProcessor.java index d9341970ac..6ba7eea5b2 100644 --- a/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/AfterModifyApplyContentProcessor.java +++ b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/AfterModifyApplyContentProcessor.java @@ -1,9 +1,6 @@ package me.kafeitu.demo.activiti.service.oa.leave; -import java.util.Date; - import me.kafeitu.demo.activiti.entity.oa.Leave; - import org.activiti.engine.RuntimeService; import org.activiti.engine.delegate.DelegateTask; import org.activiti.engine.delegate.TaskListener; @@ -12,6 +9,8 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import java.util.Date; + /** * 调整请假内容处理器 * @@ -20,27 +19,29 @@ @Component @Transactional public class AfterModifyApplyContentProcessor implements TaskListener { - - @Autowired - LeaveManager leaveManager; - - @Autowired - RuntimeService runtimeService; - - /* (non-Javadoc) - * @see org.activiti.engine.delegate.TaskListener#notify(org.activiti.engine.delegate.DelegateTask) - */ - public void notify(DelegateTask delegateTask) { - String processInstanceId = delegateTask.getProcessInstanceId(); - ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); - Leave leave = leaveManager.getLeave(new Long(processInstance.getBusinessKey())); - - leave.setLeaveType((String) delegateTask.getVariable("leaveType")); - leave.setStartTime((Date) delegateTask.getVariable("startTime")); - leave.setEndTime((Date) delegateTask.getVariable("endTime")); - leave.setReason((String) delegateTask.getVariable("reason")); - - leaveManager.saveLeave(leave); - } + + private static final long serialVersionUID = 1L; + + @Autowired + LeaveManager leaveManager; + + @Autowired + RuntimeService runtimeService; + + /* (non-Javadoc) + * @see org.activiti.engine.delegate.TaskListener#notify(org.activiti.engine.delegate.DelegateTask) + */ + public void notify(DelegateTask delegateTask) { + String processInstanceId = delegateTask.getProcessInstanceId(); + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + Leave leave = leaveManager.getLeave(new Long(processInstance.getBusinessKey())); + + leave.setLeaveType((String) delegateTask.getVariable("leaveType")); + leave.setStartTime((Date) delegateTask.getVariable("startTime")); + leave.setEndTime((Date) delegateTask.getVariable("endTime")); + leave.setReason((String) delegateTask.getVariable("reason")); + + leaveManager.saveLeave(leave); + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveEntityManager.java b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveEntityManager.java new file mode 100644 index 0000000000..92846e711c --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveEntityManager.java @@ -0,0 +1,45 @@ +package me.kafeitu.demo.activiti.service.oa.leave; + +import java.util.Date; +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import me.kafeitu.demo.activiti.entity.oa.LeaveJpaEntity; +import org.activiti.engine.delegate.DelegateExecution; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 请假实体JPA 实体管理器 + * @author: Henry Yan + */ +@Service +public class LeaveEntityManager { + + @PersistenceContext + private EntityManager entityManager; + + @Transactional + public LeaveJpaEntity newLeave(DelegateExecution execution) { + LeaveJpaEntity leave = new LeaveJpaEntity(); + leave.setProcessInstanceId(execution.getProcessInstanceId()); + leave.setUserId(execution.getVariable("applyUserId").toString()); + leave.setStartTime((Date) execution.getVariable("startTime")); + leave.setEndTime((Date) execution.getVariable("endTime")); + leave.setLeaveType(execution.getVariable("leaveType").toString()); + leave.setReason(execution.getVariable("reason").toString()); + leave.setApplyTime(new Date()); + entityManager.persist(leave); + return leave; + } + + @Transactional + public void save(LeaveJpaEntity leave) { + entityManager.persist(leave); + } + + public LeaveJpaEntity getLeave(Long id) { + return entityManager.find(LeaveJpaEntity.class, id); + } + +} \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveManager.java b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveManager.java index 29afaac02b..d6c0d87b28 100644 --- a/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveManager.java +++ b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveManager.java @@ -1,14 +1,13 @@ package me.kafeitu.demo.activiti.service.oa.leave; -import java.util.Date; - import me.kafeitu.demo.activiti.dao.LeaveDao; import me.kafeitu.demo.activiti.entity.oa.Leave; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import java.util.Date; + /** * 请假实体管理 * @@ -18,23 +17,23 @@ @Transactional(readOnly = true) public class LeaveManager { - private LeaveDao leaveDao; + private LeaveDao leaveDao; - public Leave getLeave(Long id) { - return leaveDao.findOne(id); - } + public Leave getLeave(Long id) { + return leaveDao.findOne(id); + } - @Transactional(readOnly = false) - public void saveLeave(Leave entity) { - if (entity.getId() == null) { - entity.setApplyTime(new Date()); - } - leaveDao.save(entity); - } + @Transactional(readOnly = false) + public void saveLeave(Leave entity) { + if (entity.getId() == null) { + entity.setApplyTime(new Date()); + } + leaveDao.save(entity); + } - @Autowired - public void setLeaveDao(LeaveDao leaveDao) { - this.leaveDao = leaveDao; - } + @Autowired + public void setLeaveDao(LeaveDao leaveDao) { + this.leaveDao = leaveDao; + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveProcessEndListener.java b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveProcessEndListener.java new file mode 100644 index 0000000000..8c04c7436a --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveProcessEndListener.java @@ -0,0 +1,33 @@ +package me.kafeitu.demo.activiti.service.oa.leave; + +import me.kafeitu.demo.activiti.dao.ActivitiDao; +import org.activiti.engine.delegate.DelegateExecution; +import org.activiti.engine.delegate.ExecutionListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 请假流程结束监听器 + * + * @author: Henry Yan + */ +@Service +@Transactional +public class LeaveProcessEndListener implements ExecutionListener { + + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + ActivitiDao activitiDao; + + @Override + public void notify(DelegateExecution execution) throws Exception { + String processInstanceId = execution.getProcessInstanceId(); + + int i = activitiDao.deleteFormPropertyByProcessInstanceId(processInstanceId); + logger.debug("清理了 {} 条历史表单数据", i); + } +} diff --git a/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveWorkflowService.java b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveWorkflowService.java index d21ebc1ff6..66246b9dc4 100644 --- a/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveWorkflowService.java +++ b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/LeaveWorkflowService.java @@ -5,16 +5,19 @@ import java.util.Map; import me.kafeitu.demo.activiti.entity.oa.Leave; - +import me.kafeitu.demo.activiti.util.Page; import org.activiti.engine.HistoryService; import org.activiti.engine.IdentityService; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.history.HistoricProcessInstance; +import org.activiti.engine.history.HistoricProcessInstanceQuery; import org.activiti.engine.repository.ProcessDefinition; import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.runtime.ProcessInstanceQuery; import org.activiti.engine.task.Task; +import org.activiti.engine.task.TaskQuery; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -30,160 +33,173 @@ @Transactional public class LeaveWorkflowService { - private static Logger logger = LoggerFactory.getLogger(LeaveWorkflowService.class); - - private LeaveManager leaveManager; - - private RuntimeService runtimeService; - - protected TaskService taskService; - - protected HistoryService historyService; - - protected RepositoryService repositoryService; - - @Autowired - private IdentityService identityService; - - /** - * 启动流程 - * @param entity - */ - public ProcessInstance startWorkflow(Leave entity, Map variables) { - leaveManager.saveLeave(entity); - logger.debug("save entity: {}", entity); - String businessKey = entity.getId().toString(); - - // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中 - identityService.setAuthenticatedUserId(entity.getUserId()); - - ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("leave", businessKey, variables); - String processInstanceId = processInstance.getId(); - entity.setProcessInstanceId(processInstanceId); - logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[] { "leave", businessKey, - processInstanceId, variables }); - return processInstance; - } - - /** - * 查询待办任务 - * - * @param userId 用户ID - * @return - */ - @Transactional(readOnly = true) - public List findTodoTasks(String userId) { - List results = new ArrayList(); - List tasks = new ArrayList(); - - // 根据当前人的ID查询 - List todoList = taskService.createTaskQuery().processDefinitionKey("leave").taskAssignee(userId).active().orderByTaskPriority().desc() - .orderByTaskCreateTime().desc().list(); - - // 根据当前人未签收的任务 - List unsignedTasks = taskService.createTaskQuery().processDefinitionKey("leave").taskCandidateUser(userId).active().orderByTaskPriority().desc() - .orderByTaskCreateTime().desc().list(); - - // 合并 - tasks.addAll(todoList); - tasks.addAll(unsignedTasks); - - // 根据流程的业务ID查询实体并关联 - for (Task task : tasks) { - String processInstanceId = task.getProcessInstanceId(); - ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active() - .singleResult(); - String businessKey = processInstance.getBusinessKey(); - Leave leave = leaveManager.getLeave(new Long(businessKey)); - leave.setTask(task); - leave.setProcessInstance(processInstance); - leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId())); - results.add(leave); - } - return results; - } - - /** - * 读取运行中的流程 - * @return - */ - @Transactional(readOnly = true) - public List findRunningProcessInstaces() { - List results = new ArrayList(); - List list = runtimeService.createProcessInstanceQuery().processDefinitionKey("leave").active().list(); - - // 关联业务实体 - for (ProcessInstance processInstance : list) { - String businessKey = processInstance.getBusinessKey(); - Leave leave = leaveManager.getLeave(new Long(businessKey)); - leave.setProcessInstance(processInstance); - leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId())); - results.add(leave); - - // 设置当前任务信息 - List tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).active().orderByTaskCreateTime() - .desc().listPage(0, 1); - leave.setTask(tasks.get(0)); - - } - return results; - } - - /** - * 读取运行中的流程 - * @return - */ - @Transactional(readOnly = true) - public List findFinishedProcessInstaces() { - List results = new ArrayList(); - List list = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("leave") - .finished().list(); - - // 关联业务实体 - for (HistoricProcessInstance historicProcessInstance : list) { - String businessKey = historicProcessInstance.getBusinessKey(); - Leave leave = leaveManager.getLeave(new Long(businessKey)); - leave.setProcessDefinition(getProcessDefinition(historicProcessInstance.getProcessDefinitionId())); - leave.setHistoricProcessInstance(historicProcessInstance); - results.add(leave); - } - return results; - } - - /** - * 查询流程定义对象 - * @param processDefinitionId 流程定义ID - * @return - */ - protected ProcessDefinition getProcessDefinition(String processDefinitionId) { - ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() - .processDefinitionId(processDefinitionId).singleResult(); - return processDefinition; - } - - @Autowired - public void setLeaveManager(LeaveManager leaveManager) { - this.leaveManager = leaveManager; - } - - @Autowired - public void setRuntimeService(RuntimeService runtimeService) { - this.runtimeService = runtimeService; - } - - @Autowired - public void setTaskService(TaskService taskService) { - this.taskService = taskService; - } - - @Autowired - public void setHistoryService(HistoryService historyService) { - this.historyService = historyService; - } - - @Autowired - public void setRepositoryService(RepositoryService repositoryService) { - this.repositoryService = repositoryService; - } + private static Logger logger = LoggerFactory.getLogger(LeaveWorkflowService.class); + + private LeaveManager leaveManager; + + private RuntimeService runtimeService; + + protected TaskService taskService; + + protected HistoryService historyService; + + protected RepositoryService repositoryService; + + @Autowired + private IdentityService identityService; + + /** + * 启动流程 + * + * @param entity + */ + public ProcessInstance startWorkflow(Leave entity, Map variables) { + leaveManager.saveLeave(entity); + logger.debug("save entity: {}", entity); + String businessKey = entity.getId().toString(); + + ProcessInstance processInstance = null; + try { + // 用来设置启动流程的人员ID,引擎会自动把用户ID保存到activiti:initiator中 + identityService.setAuthenticatedUserId(entity.getUserId()); + + processInstance = runtimeService.startProcessInstanceByKey("leave", businessKey, variables); + String processInstanceId = processInstance.getId(); + entity.setProcessInstanceId(processInstanceId); + logger.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[]{"leave", businessKey, processInstanceId, variables}); + } finally { + identityService.setAuthenticatedUserId(null); + } + return processInstance; + } + + /** + * 查询待办任务 + * + * @param userId 用户ID + * @return + */ + @Transactional(readOnly = true) + public List findTodoTasks(String userId, Page page, int[] pageParams) { + List results = new ArrayList(); + + // 根据当前人的ID查询 + TaskQuery taskQuery = taskService.createTaskQuery().taskCandidateOrAssigned(userId); + List tasks = taskQuery.list(); + + // 根据流程的业务ID查询实体并关联 + for (Task task : tasks) { + String processInstanceId = task.getProcessInstanceId(); + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).active().singleResult(); + if (processInstance == null) { + continue; + } + String businessKey = processInstance.getBusinessKey(); + if (businessKey == null) { + continue; + } + Leave leave = leaveManager.getLeave(new Long(businessKey)); + leave.setTask(task); + leave.setProcessInstance(processInstance); + leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId())); + results.add(leave); + } + + page.setTotalCount(taskQuery.count()); + page.setResult(results); + return results; + } + + /** + * 读取运行中的流程 + * + * @return + */ + @Transactional(readOnly = true) + public List findRunningProcessInstaces(Page page, int[] pageParams) { + List results = new ArrayList(); + ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery().processDefinitionKey("leave").active().orderByProcessInstanceId().desc(); + List list = query.listPage(pageParams[0], pageParams[1]); + + // 关联业务实体 + for (ProcessInstance processInstance : list) { + String businessKey = processInstance.getBusinessKey(); + if (businessKey == null) { + continue; + } + Leave leave = leaveManager.getLeave(new Long(businessKey)); + leave.setProcessInstance(processInstance); + leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId())); + results.add(leave); + + // 设置当前任务信息 + List tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).active().orderByTaskCreateTime().desc().listPage(0, 1); + leave.setTask(tasks.get(0)); + } + + page.setTotalCount(query.count()); + page.setResult(results); + return results; + } + + /** + * 读取已结束中的流程 + * + * @return + */ + @Transactional(readOnly = true) + public List findFinishedProcessInstaces(Page page, int[] pageParams) { + List results = new ArrayList(); + HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("leave").finished().orderByProcessInstanceEndTime().desc(); + List list = query.listPage(pageParams[0], pageParams[1]); + + // 关联业务实体 + for (HistoricProcessInstance historicProcessInstance : list) { + String businessKey = historicProcessInstance.getBusinessKey(); + Leave leave = leaveManager.getLeave(new Long(businessKey)); + leave.setProcessDefinition(getProcessDefinition(historicProcessInstance.getProcessDefinitionId())); + leave.setHistoricProcessInstance(historicProcessInstance); + results.add(leave); + } + page.setTotalCount(query.count()); + page.setResult(results); + return results; + } + + /** + * 查询流程定义对象 + * + * @param processDefinitionId 流程定义ID + * @return + */ + protected ProcessDefinition getProcessDefinition(String processDefinitionId) { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult(); + return processDefinition; + } + + @Autowired + public void setLeaveManager(LeaveManager leaveManager) { + this.leaveManager = leaveManager; + } + + @Autowired + public void setRuntimeService(RuntimeService runtimeService) { + this.runtimeService = runtimeService; + } + + @Autowired + public void setTaskService(TaskService taskService) { + this.taskService = taskService; + } + + @Autowired + public void setHistoryService(HistoryService historyService) { + this.historyService = historyService; + } + + @Autowired + public void setRepositoryService(RepositoryService repositoryService) { + this.repositoryService = repositoryService; + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/ReportBackEndProcessor.java b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/ReportBackEndProcessor.java index 21cd662053..cb88f27e35 100644 --- a/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/ReportBackEndProcessor.java +++ b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/ReportBackEndProcessor.java @@ -1,9 +1,6 @@ package me.kafeitu.demo.activiti.service.oa.leave; -import java.util.Date; - import me.kafeitu.demo.activiti.entity.oa.Leave; - import org.activiti.engine.RuntimeService; import org.activiti.engine.delegate.DelegateTask; import org.activiti.engine.delegate.TaskListener; @@ -12,6 +9,8 @@ import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import java.util.Date; + /** * 销假后处理器 *

设置销假时间

@@ -23,26 +22,28 @@ @Transactional public class ReportBackEndProcessor implements TaskListener { - @Autowired - LeaveManager leaveManager; - - @Autowired - RuntimeService runtimeService; - - /* (non-Javadoc) - * @see org.activiti.engine.delegate.TaskListener#notify(org.activiti.engine.delegate.DelegateTask) - */ - public void notify(DelegateTask delegateTask) { - String processInstanceId = delegateTask.getProcessInstanceId(); - ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); - Leave leave = leaveManager.getLeave(new Long(processInstance.getBusinessKey())); - - Object realityStartTime = delegateTask.getVariable("realityStartTime"); - leave.setRealityStartTime((Date) realityStartTime); - Object realityEndTime = delegateTask.getVariable("realityEndTime"); - leave.setRealityEndTime((Date) realityEndTime); - - leaveManager.saveLeave(leave); - } + private static final long serialVersionUID = 1L; + + @Autowired + LeaveManager leaveManager; + + @Autowired + RuntimeService runtimeService; + + /* (non-Javadoc) + * @see org.activiti.engine.delegate.TaskListener#notify(org.activiti.engine.delegate.DelegateTask) + */ + public void notify(DelegateTask delegateTask) { + String processInstanceId = delegateTask.getProcessInstanceId(); + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + Leave leave = leaveManager.getLeave(new Long(processInstance.getBusinessKey())); + + Object realityStartTime = delegateTask.getVariable("realityStartTime"); + leave.setRealityStartTime((Date) realityStartTime); + Object realityEndTime = delegateTask.getVariable("realityEndTime"); + leave.setRealityEndTime((Date) realityEndTime); + + leaveManager.saveLeave(leave); + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/VariableCreateListener.java b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/VariableCreateListener.java new file mode 100644 index 0000000000..89b11b2663 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/service/oa/leave/VariableCreateListener.java @@ -0,0 +1,39 @@ +package me.kafeitu.demo.activiti.service.oa.leave; + +import org.activiti.engine.delegate.event.ActivitiEvent; +import org.activiti.engine.delegate.event.ActivitiEventListener; +import org.activiti.engine.delegate.event.ActivitiVariableEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 引擎的全局监听器 + * @author: Henry Yan + */ +@Service +@Transactional +public class VariableCreateListener implements ActivitiEventListener { + + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Override + public void onEvent(ActivitiEvent event) { + switch (event.getType()) { + + case VARIABLE_CREATED: + ActivitiVariableEvent variableEvent = (ActivitiVariableEvent) event; + System.out.println("创建了变量: " + variableEvent.getVariableName() + ", 值:" + variableEvent.getVariableValue()); + break; + + default: + System.out.println("Event received: " + event.getType()); + } + } + + @Override + public boolean isFailOnException() { + return false; + } +} diff --git a/src/main/java/me/kafeitu/demo/activiti/util/DateConverter.java b/src/main/java/me/kafeitu/demo/activiti/util/DateConverter.java index 8b4ca94898..b40a427fd7 100644 --- a/src/main/java/me/kafeitu/demo/activiti/util/DateConverter.java +++ b/src/main/java/me/kafeitu/demo/activiti/util/DateConverter.java @@ -1,95 +1,95 @@ package me.kafeitu.demo.activiti.util; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; - import org.apache.commons.beanutils.Converter; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.apache.log4j.Logger; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + public class DateConverter implements Converter { - private static final Logger logger = Logger.getLogger(DateConverter.class); - - private static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; - - private static final String DATETIME_PATTERN_NO_SECOND = "yyyy-MM-dd HH:mm"; - - private static final String DATE_PATTERN = "yyyy-MM-dd"; - - private static final String MONTH_PATTERN = "yyyy-MM"; - - @SuppressWarnings("rawtypes") - public Object convert(Class type, Object value) { - Object result = null; - if (type == Date.class) { - try { - result = doConvertToDate(value); - } catch (ParseException e) { - e.printStackTrace(); - } - } else if (type == String.class) { - result = doConvertToString(value); - } - return result; - } - - /** - * Convert String to Date - * - * @param value - * @return - * @throws ParseException - */ - private Date doConvertToDate(Object value) throws ParseException { - Date result = null; - - if (value instanceof String) { - result = DateUtils.parseDate((String) value, new String[] { DATE_PATTERN, DATETIME_PATTERN, - DATETIME_PATTERN_NO_SECOND, MONTH_PATTERN }); - - // all patterns failed, try a milliseconds constructor - if (result == null && StringUtils.isNotEmpty((String) value)) { - - try { - result = new Date(new Long((String) value).longValue()); - } catch (Exception e) { - logger.error("Converting from milliseconds to Date fails!"); - e.printStackTrace(); - } - - } - - } else if (value instanceof Object[]) { - // let's try to convert the first element only - Object[] array = (Object[]) value; - - if ((array != null) && (array.length >= 1)) { - value = array[0]; - result = doConvertToDate(value); - } - - } else if (Date.class.isAssignableFrom(value.getClass())) { - result = (Date) value; - } - return result; - } - - /** - * Convert Date to String - * - * @param value - * @return - */ - private String doConvertToString(Object value) { - SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATETIME_PATTERN); - String result = null; - if (value instanceof Date) { - result = simpleDateFormat.format(value); - } - return result; - } - -} \ No newline at end of file + private static final Logger logger = Logger.getLogger(DateConverter.class); + + private static final String DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; + + private static final String DATETIME_PATTERN_NO_SECOND = "yyyy-MM-dd HH:mm"; + + private static final String DATE_PATTERN = "yyyy-MM-dd"; + + private static final String MONTH_PATTERN = "yyyy-MM"; + + @SuppressWarnings("rawtypes") + public Object convert(Class type, Object value) { + Object result = null; + if (type == Date.class) { + try { + result = doConvertToDate(value); + } catch (ParseException e) { + e.printStackTrace(); + } + } else if (type == String.class) { + result = doConvertToString(value); + } + return result; + } + + /** + * Convert String to Date + * + * @param value + * @return + * @throws ParseException + */ + private Date doConvertToDate(Object value) throws ParseException { + Date result = null; + + if (value instanceof String) { + result = DateUtils.parseDate((String) value, new String[]{DATE_PATTERN, DATETIME_PATTERN, + DATETIME_PATTERN_NO_SECOND, MONTH_PATTERN}); + + // all patterns failed, try a milliseconds constructor + if (result == null && StringUtils.isNotEmpty((String) value)) { + + try { + result = new Date(new Long((String) value).longValue()); + } catch (Exception e) { + logger.error("Converting from milliseconds to Date fails!"); + e.printStackTrace(); + } + + } + + } else if (value instanceof Object[]) { + // let's try to convert the first element only + Object[] array = (Object[]) value; + + if (array.length >= 1) { + value = array[0]; + result = doConvertToDate(value); + } + + } else if (Date.class.isAssignableFrom(value.getClass())) { + result = (Date) value; + } + return result; + } + + /** + * Convert Date to String + * + * @param value + * @return + */ + private String doConvertToString(Object value) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATETIME_PATTERN); + String result = null; + if (value instanceof Date) { + result = simpleDateFormat.format(value); + } + return result; + } + +} diff --git a/src/main/java/me/kafeitu/demo/activiti/util/LinkedProperties.java b/src/main/java/me/kafeitu/demo/activiti/util/LinkedProperties.java new file mode 100644 index 0000000000..9fcfff00d4 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/util/LinkedProperties.java @@ -0,0 +1,93 @@ +package me.kafeitu.demo.activiti.util; + +import java.io.PrintStream; +import java.io.PrintWriter; +import java.util.*; + +/** + * 有序Properties + */ +public class LinkedProperties extends Properties { + private static final long serialVersionUID = 1L; + private Map linkMap = new LinkedHashMap(); + + public void clear() { + linkMap.clear(); + } + + public boolean contains(Object value) { + return linkMap.containsValue(value); + } + + public boolean containsKey(Object key) { + return linkMap.containsKey(key); + } + + public boolean containsValue(Object value) { + return linkMap.containsValue(value); + } + + public Enumeration elements() { + throw new RuntimeException("Method elements is not supported in LinkedProperties class"); + } + + public Set entrySet() { + return linkMap.entrySet(); + } + + public boolean equals(Object o) { + return linkMap.equals(o); + } + + public Object get(Object key) { + return linkMap.get(key); + } + + public String getProperty(String key) { + Object oval = get(key); //here the class Properties uses super.get() + if (oval == null) return null; + return (oval instanceof String) ? (String) oval : null; //behavior of standard properties + } + + public boolean isEmpty() { + return linkMap.isEmpty(); + } + + public Enumeration keys() { + Set keys = linkMap.keySet(); + return Collections.enumeration(keys); + } + + public Set keySet() { + return linkMap.keySet(); + } + + public void list(PrintStream out) { + this.list(new PrintWriter(out, true)); + } + + public void list(PrintWriter out) { + out.println("-- listing properties --"); + for (Map.Entry e : (Set) this.entrySet()) { + String key = (String) e.getKey(); + String val = (String) e.getValue(); + if (val.length() > 40) { + val = val.substring(0, 37) + "..."; + } + out.println(key + "=" + val); + } + } + + public Object put(Object key, Object value) { + return linkMap.put(key, value); + } + + public int size() { + return linkMap.size(); + } + + public Collection values() { + return linkMap.values(); + } + +} \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/util/Page.java b/src/main/java/me/kafeitu/demo/activiti/util/Page.java new file mode 100644 index 0000000000..36c2f4f81e --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/util/Page.java @@ -0,0 +1,258 @@ +package me.kafeitu.demo.activiti.util; + +import com.google.common.collect.Lists; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; + +/** + * @author HenryYan + */ +public class Page { + + // -- 公共变量 --// + public static final String ASC = "asc"; + public static final String DESC = "desc"; + + // -- 分页参数 --// + protected int pageNo = 1; + protected int pageSize = -1; + protected String orderBy = null; + protected String order = null; + protected boolean autoCount = true; + + // -- 返回结果 --// + protected List result = Lists.newArrayList(); + protected long totalCount = -1; + + // -- 构造函数 --// + public Page() { + } + + public Page(int pageSize) { + this.pageSize = pageSize; + } + + // -- 分页参数访问函数 --// + + /** + * 获得当前页的页号,序号从1开始,默认为1. + */ + public int getPageNo() { + return pageNo; + } + + /** + * 设置当前页的页号,序号从1开始,低于1时自动调整为1. + */ + public void setPageNo(final int pageNo) { + this.pageNo = pageNo; + + if (pageNo < 1) { + this.pageNo = 1; + } + } + + /** + * 返回Page对象自身的setPageNo函数,可用于连续设置。 + */ + public Page pageNo(final int thePageNo) { + setPageNo(thePageNo); + return this; + } + + /** + * 获得每页的记录数量, 默认为-1. + */ + public int getPageSize() { + return pageSize; + } + + /** + * 设置每页的记录数量. + */ + public void setPageSize(final int pageSize) { + this.pageSize = pageSize; + } + + /** + * 返回Page对象自身的setPageSize函数,可用于连续设置。 + */ + public Page pageSize(final int thePageSize) { + setPageSize(thePageSize); + return this; + } + + /** + * 根据pageNo和pageSize计算当前页第一条记录在总结果集中的位置,序号从1开始. + */ + public int getFirst() { + return ((pageNo - 1) * pageSize) + 1; + } + + /** + * 获得排序字段,无默认值. 多个排序字段时用','分隔. + */ + public String getOrderBy() { + return orderBy; + } + + /** + * 设置排序字段,多个排序字段时用','分隔. + */ + public void setOrderBy(final String orderBy) { + this.orderBy = orderBy; + } + + /** + * 返回Page对象自身的setOrderBy函数,可用于连续设置。 + */ + public Page orderBy(final String theOrderBy) { + setOrderBy(theOrderBy); + return this; + } + + /** + * 获得排序方向, 无默认值. + */ + public String getOrder() { + return order; + } + + /** + * 设置排序方式向. + * + * @param order 可选值为desc或asc,多个排序字段时用','分隔. + */ + public void setOrder(final String order) { + String lowcaseOrder = StringUtils.lowerCase(order); + + // 检查order字符串的合法值 + String[] orders = StringUtils.split(lowcaseOrder, ','); + for (String orderStr : orders) { + if (!StringUtils.equals(DESC, orderStr) && !StringUtils.equals(ASC, orderStr)) { + throw new IllegalArgumentException("排序方向" + orderStr + "不是合法值"); + } + } + + this.order = lowcaseOrder; + } + + /** + * 返回Page对象自身的setOrder函数,可用于连续设置。 + */ + public Page order(final String theOrder) { + setOrder(theOrder); + return this; + } + + /** + * 是否已设置排序字段,无默认值. + */ + public boolean isOrderBySetted() { + return (StringUtils.isNotBlank(orderBy) && StringUtils.isNotBlank(order)); + } + + /** + * 获得查询对象时是否先自动执行count查询获取总记录数, 默认为false. + */ + public boolean isAutoCount() { + return autoCount; + } + + /** + * 设置查询对象时是否自动先执行count查询获取总记录数. + */ + public void setAutoCount(final boolean autoCount) { + this.autoCount = autoCount; + } + + /** + * 返回Page对象自身的setAutoCount函数,可用于连续设置。 + */ + public Page autoCount(final boolean theAutoCount) { + setAutoCount(theAutoCount); + return this; + } + + // -- 访问查询结果函数 --// + + /** + * 获得页内的记录列表. + */ + public List getResult() { + return result; + } + + /** + * 设置页内的记录列表. + */ + public void setResult(final List result) { + this.result = result; + } + + /** + * 获得总记录数, 默认值为-1. + */ + public long getTotalCount() { + return totalCount; + } + + /** + * 设置总记录数. + */ + public void setTotalCount(final long totalCount) { + this.totalCount = totalCount; + } + + /** + * 根据pageSize与totalCount计算总页数, 默认值为-1. + */ + public long getTotalPages() { + if (totalCount < 0) { + return -1; + } + + long count = totalCount / pageSize; + if (totalCount % pageSize > 0) { + count++; + } + return count; + } + + /** + * 是否还有下一页. + */ + public boolean isHasNext() { + return (pageNo + 1 <= getTotalPages()); + } + + /** + * 取得下页的页号, 序号从1开始. 当前页为尾页时仍返回尾页序号. + */ + public int getNextPage() { + if (isHasNext()) { + return pageNo + 1; + } else { + return pageNo; + } + } + + /** + * 是否还有上一页. + */ + public boolean isHasPre() { + return (pageNo - 1 >= 1); + } + + /** + * 取得上页的页号, 序号从1开始. 当前页为首页时返回首页序号. + */ + public int getPrePage() { + if (isHasPre()) { + return pageNo - 1; + } else { + return pageNo; + } + } +} diff --git a/src/main/java/me/kafeitu/demo/activiti/util/PageUtil.java b/src/main/java/me/kafeitu/demo/activiti/util/PageUtil.java new file mode 100644 index 0000000000..4150d7020a --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/util/PageUtil.java @@ -0,0 +1,26 @@ +package me.kafeitu.demo.activiti.util; + +import org.apache.commons.lang3.StringUtils; + +import javax.servlet.http.HttpServletRequest; + +/** + * 分页工具 + * + * @author henryyan + */ +public class PageUtil { + + public static int PAGE_SIZE = 15; + + public static int[] init(Page page, HttpServletRequest request) { + int pageNumber = Integer.parseInt(StringUtils.defaultIfBlank(request.getParameter("p"), "1")); + page.setPageNo(pageNumber); + int pageSize = Integer.parseInt(StringUtils.defaultIfBlank(request.getParameter("ps"), String.valueOf(PAGE_SIZE))); + page.setPageSize(pageSize); + int firstResult = page.getFirst() - 1; + int maxResults = page.getPageSize(); + return new int[]{firstResult, maxResults}; + } + +} diff --git a/src/main/java/me/kafeitu/demo/activiti/util/ProcessDefinitionCache.java b/src/main/java/me/kafeitu/demo/activiti/util/ProcessDefinitionCache.java index f569d20889..acb808ff20 100644 --- a/src/main/java/me/kafeitu/demo/activiti/util/ProcessDefinitionCache.java +++ b/src/main/java/me/kafeitu/demo/activiti/util/ProcessDefinitionCache.java @@ -1,8 +1,6 @@ package me.kafeitu.demo.activiti.util; -import java.util.List; -import java.util.Map; - +import com.google.common.collect.Maps; import org.activiti.engine.RepositoryService; import org.activiti.engine.impl.RepositoryServiceImpl; import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; @@ -10,64 +8,65 @@ import org.activiti.engine.repository.ProcessDefinition; import org.apache.commons.lang3.ObjectUtils; -import com.google.common.collect.Maps; +import java.util.List; +import java.util.Map; /** * 流程定义缓存 - * + * * @author henryyan */ public class ProcessDefinitionCache { - private static Map map = Maps.newHashMap(); + private static Map map = Maps.newHashMap(); - private static Map> activities = Maps.newHashMap(); + private static Map> activities = Maps.newHashMap(); - private static Map singleActivity = Maps.newHashMap(); + private static Map singleActivity = Maps.newHashMap(); - private static RepositoryService repositoryService; + private static RepositoryService repositoryService; - public static ProcessDefinition get(String processDefinitionId) { - ProcessDefinition processDefinition = map.get(processDefinitionId); - if (processDefinition == null) { - processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(processDefinitionId); - if (processDefinition != null) { - put(processDefinitionId, processDefinition); - } + public static ProcessDefinition get(String processDefinitionId) { + ProcessDefinition processDefinition = map.get(processDefinitionId); + if (processDefinition == null) { + processDefinition = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService).getDeployedProcessDefinition(processDefinitionId); + if (processDefinition != null) { + put(processDefinitionId, processDefinition); + } + } + return processDefinition; } - return processDefinition; - } - public static void put(String processDefinitionId, ProcessDefinition processDefinition) { - map.put(processDefinitionId, processDefinition); - ProcessDefinitionEntity pde = (ProcessDefinitionEntity) processDefinition; - activities.put(processDefinitionId, pde.getActivities()); - for (ActivityImpl activityImpl : pde.getActivities()) { - singleActivity.put(processDefinitionId + "_" + activityImpl.getId(), activityImpl); + public static void put(String processDefinitionId, ProcessDefinition processDefinition) { + map.put(processDefinitionId, processDefinition); + ProcessDefinitionEntity pde = (ProcessDefinitionEntity) processDefinition; + activities.put(processDefinitionId, pde.getActivities()); + for (ActivityImpl activityImpl : pde.getActivities()) { + singleActivity.put(processDefinitionId + "_" + activityImpl.getId(), activityImpl); + } } - } - public static ActivityImpl getActivity(String processDefinitionId, String activityId) { - ProcessDefinition processDefinition = get(processDefinitionId); - if (processDefinition != null) { - ActivityImpl activityImpl = singleActivity.get(processDefinitionId + "_" + activityId); - if (activityImpl != null) { - return activityImpl; - } + public static ActivityImpl getActivity(String processDefinitionId, String activityId) { + ProcessDefinition processDefinition = get(processDefinitionId); + if (processDefinition != null) { + ActivityImpl activityImpl = singleActivity.get(processDefinitionId + "_" + activityId); + if (activityImpl != null) { + return activityImpl; + } + } + return null; } - return null; - } - public static String getActivityName(String processDefinitionId, String activityId) { - ActivityImpl activity = getActivity(processDefinitionId, activityId); - if (activity != null) { - return ObjectUtils.toString(activity.getProperty("name")); + public static String getActivityName(String processDefinitionId, String activityId) { + ActivityImpl activity = getActivity(processDefinitionId, activityId); + if (activity != null) { + return ObjectUtils.toString(activity.getProperty("name")); + } + return null; } - return null; - } - public static void setRepositoryService(RepositoryService repositoryService) { - ProcessDefinitionCache.repositoryService = repositoryService; - } + public static void setRepositoryService(RepositoryService repositoryService) { + ProcessDefinitionCache.repositoryService = repositoryService; + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/util/PropertyFileUtil.java b/src/main/java/me/kafeitu/demo/activiti/util/PropertyFileUtil.java index cbc175a0fc..5d1fcdc92b 100644 --- a/src/main/java/me/kafeitu/demo/activiti/util/PropertyFileUtil.java +++ b/src/main/java/me/kafeitu/demo/activiti/util/PropertyFileUtil.java @@ -2,128 +2,244 @@ import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Properties; import java.util.Set; -import me.kafeitu.modules.utils.PropertiesLoader; - +import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import org.springframework.util.DefaultPropertiesPersister; +import org.springframework.util.PropertiesPersister; /** * 系统属性工具类 * * @author HenryYan - * */ public class PropertyFileUtil { - - private static Logger logger = LoggerFactory.getLogger(PropertyFileUtil.class); - - private static Properties properties; - - /** - * 初始化读取配置文件,读取的文件列表位于classpath下面的application-files.properties
- * - * 多个配置文件会用最后面的覆盖相同属性值 - * - * @throws IOException 读取属性文件时 - */ - public static void init() throws IOException { - String fileNames = "application-files.properties"; - innerInit(fileNames); - } - - /** - * 初始化读取配置文件,读取的文件列表位于classpath下面的application-[type]-files.properties
- * - * 多个配置文件会用最后面的覆盖相同属性值 - * - * @param type 配置文件类型,application-[type]-files.properties - * - * @throws IOException 读取属性文件时 - */ - public static void init(String type) throws IOException { - String fileNames = "application-" + type + "-files.properties"; - innerInit(fileNames); - } - - /** - * 内部处理 - * @param fileNames - * @throws IOException - */ - private static void innerInit(String fileNames) throws IOException { - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - InputStream resourceAsStream = loader.getResourceAsStream(fileNames); - - Properties files = new Properties(); - files.load(resourceAsStream); - - Set fileKeySet = files.keySet(); - String[] propFiles = new String[fileKeySet.size()]; - List fileList = new ArrayList(); - - fileList.addAll(files.keySet()); - for (int i = 0; i < propFiles.length; i++) { - String fileKey = fileList.get(i).toString(); - - // 倒序加入到数组中,按照配置文件中的顺序覆盖相同名字的变量 - propFiles[propFiles.length - i - 1] = files.getProperty(fileKey); - } - - logger.debug("读取属性文件:{}", propFiles); - PropertiesLoader propertiesLoader = new PropertiesLoader(propFiles); - properties = propertiesLoader.getProperties(); - Set keySet = properties.keySet(); - for (Object key : keySet) { - logger.debug("property: {}, value: {}", key, properties.getProperty(key.toString())); - } - } - - /** - * 获取所有的key - * @return - */ - public static Set getKeys() { - return properties.keySet(); - } - - /** - * 获取属性值 - * @param key 键 - * @return 值 - */ - public static String get(String key) { - String propertyValue = properties.getProperty(key); - logger.debug("获取属性:{},值:{}", key, propertyValue); - return propertyValue; - } - - /** - * 获取属性值 - * @param key 键 - * @param defaultValue 默认值 - * @return 值 - */ - public static String get(String key, String defaultValue) { - String propertyValue = properties.getProperty(key); - String value = StringUtils.defaultString(propertyValue, defaultValue); - logger.debug("获取属性:{},值:{}", key, value); - return value; - } - - /** - * 向内存添加属性 - * @param key 键 - * @param value 值 - */ - public static void add(String key, String value) { - properties.put(key, value); - logger.debug("通过方法添加属性到内存:{},值:{}", key, value); - } -} + + private static final String DEFAULT_ENCODING = "UTF-8"; + private static Logger logger = LoggerFactory.getLogger(PropertyFileUtil.class); + private static Properties properties; + private static PropertiesPersister propertiesPersister = new DefaultPropertiesPersister(); + private static ResourceLoader resourceLoader = new DefaultResourceLoader(); + private static Properties activePropertyFiles = null; + private static String PROFILE_ID = StringUtils.EMPTY; + public static boolean initialized = false; // 是否已初始化 + + /** + * 初始化读取配置文件,读取的文件列表位于classpath下面的application-files.properties
+ *

+ * 多个配置文件会用最后面的覆盖相同属性值 + * + * @throws IOException 读取属性文件时 + */ + public static void init() throws IOException { + String fileNames = "application-files.properties"; + PROFILE_ID = StringUtils.EMPTY; + innerInit(fileNames); + activePropertyFiles(fileNames); + initialized = true; + } + + /** + * 初始化读取配置文件,读取的文件列表位于classpath下面的application-[type]-files.properties
+ *

+ * 多个配置文件会用最后面的覆盖相同属性值 + * + * @param profile 配置文件类型,application-[profile]-files.properties + * @throws IOException 读取属性文件时 + */ + public static void init(String profile) throws IOException { + if (StringUtils.isBlank(profile)) { + init(); + } else { + PROFILE_ID = profile; + String fileNames = "application-" + profile + "-files.properties"; + innerInit(fileNames); + } + initialized = true; + } + + /** + * 内部处理 + * + * @param fileName + * @throws IOException + */ + private static void innerInit(String fileName) throws IOException { + String[] propFiles = activePropertyFiles(fileName); + logger.debug("读取属性文件:{}", ArrayUtils.toString(propFiles)); + properties = loadProperties(propFiles); + Set keySet = properties.keySet(); + for (Object key : keySet) { + logger.debug("property: {}, value: {}", key, properties.getProperty(key.toString())); + } + } + + /** + * 获取读取的资源文件列表 + * + * @param fileName + * @return + * @throws IOException + */ + private static String[] activePropertyFiles(String fileName) throws IOException { + logger.info("读取" + fileName); + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + InputStream resourceAsStream = loader.getResourceAsStream(fileName); + // 默认的Properties实现使用HashMap算法,为了保持原有顺序使用有序Map + activePropertyFiles = new LinkedProperties(); + activePropertyFiles.load(resourceAsStream); + + Set fileKeySet = activePropertyFiles.keySet(); + String[] propFiles = new String[fileKeySet.size()]; + List fileList = new ArrayList(); + + fileList.addAll(activePropertyFiles.keySet()); + for (int i = 0; i < propFiles.length; i++) { + String fileKey = fileList.get(i).toString(); + propFiles[i] = activePropertyFiles.getProperty(fileKey); + } + return propFiles; + } + + /** + * 载入多个properties文件, 相同的属性在最后载入的文件中的值将会覆盖之前的载入. + * 文件路径使用Spring Resource格式, 文件编码使用UTF-8. + * + * @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer + */ + public static Properties loadProperties(String... resourcesPaths) throws IOException { + Properties props = new Properties(); + + for (String location : resourcesPaths) { + + // 剔除classpath路径协议 + location = location.replace("classpath*:/", ""); + + logger.debug("Loading properties file from:" + location); + + InputStream is = null; + try { + Resource resource = resourceLoader.getResource(location); + is = resource.getInputStream(); + propertiesPersister.load(props, new InputStreamReader(is, DEFAULT_ENCODING)); + } catch (IOException ex) { + logger.info("Could not load properties from classpath:" + location + ": " + ex.getMessage()); + } finally { + if (is != null) { + is.close(); + } + } + } + return props; + } + + /** + * 获取所有的key + * + * @return + */ + public static Set getKeys() { + return properties.stringPropertyNames(); + } + + /** + * 获取键值对Map + * + * @return + */ + public static Map getKeyValueMap() { + Set keys = getKeys(); + Map values = new HashMap(); + for (String key : keys) { + values.put(key, get(key)); + } + return values; + } + + /** + * 获取属性值 + * + * @param key 键 + * @return 值 + */ + public static String get(String key) { + if (!initialized) { + try { + init(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + String propertyValue = properties.getProperty(key); + if (logger.isDebugEnabled()) { + logger.debug("获取属性:{},值:{}", key, propertyValue); + } + return propertyValue; + } + + /** + * 获取属性值 + * + * @param key 键 + * @param defaultValue 默认值 + * @return 值 + */ + public static String get(String key, String defaultValue) { + if (!initialized) { + try { + init(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + String propertyValue = properties.getProperty(key); + String value = StringUtils.defaultString(propertyValue, defaultValue); + if (logger.isDebugEnabled()) { + logger.debug("获取属性:{},值:{}", key, value); + } + return value; + } + + /** + * 判断key对应的value是否和期待的一致 + * @param key + * @param expectValue + * @return + */ + public static boolean equalsWith(String key, String expectValue) { + String value = get(key); + return StringUtils.equals(value, expectValue); + } + + /** + * 向内存添加属性 + * + * @param key 键 + * @param value 值 + */ + public static void add(String key, String value) { + properties.put(key, value); + logger.debug("通过方法添加属性到内存:{},值:{}", key, value); + } + + public static Properties getActivePropertyFiles() { + return activePropertyFiles; + } + + public static String getProfile() { + return PROFILE_ID; + } +} \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/util/PropertyType.java b/src/main/java/me/kafeitu/demo/activiti/util/PropertyType.java index bd433a7ff5..d17f080592 100644 --- a/src/main/java/me/kafeitu/demo/activiti/util/PropertyType.java +++ b/src/main/java/me/kafeitu/demo/activiti/util/PropertyType.java @@ -8,16 +8,16 @@ * @author HenryYan */ public enum PropertyType { - S(String.class), I(Integer.class), L(Long.class), F(Float.class), N(Double.class), D(Date.class), SD(java.sql.Date.class), B( - Boolean.class); + S(String.class), I(Integer.class), L(Long.class), F(Float.class), N(Double.class), D(Date.class), SD(java.sql.Date.class), B( + Boolean.class); - private Class clazz; + private Class clazz; - private PropertyType(Class clazz) { - this.clazz = clazz; - } + private PropertyType(Class clazz) { + this.clazz = clazz; + } - public Class getValue() { - return clazz; - } + public Class getValue() { + return clazz; + } } \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/util/UserUtil.java b/src/main/java/me/kafeitu/demo/activiti/util/UserUtil.java index 2496576e2d..dcdb8f6f74 100644 --- a/src/main/java/me/kafeitu/demo/activiti/util/UserUtil.java +++ b/src/main/java/me/kafeitu/demo/activiti/util/UserUtil.java @@ -1,9 +1,9 @@ package me.kafeitu.demo.activiti.util; -import javax.servlet.http.HttpSession; - import org.activiti.engine.identity.User; +import javax.servlet.http.HttpSession; + /** * 用户工具类 * @@ -11,25 +11,27 @@ */ public class UserUtil { - public static final String USER = "user"; + public static final String USER = "user"; - /** - * 设置用户到session - * @param session - * @param user - */ - public static void saveUserToSession(HttpSession session, User user) { - session.setAttribute(USER, user); - } + /** + * 设置用户到session + * + * @param session + * @param user + */ + public static void saveUserToSession(HttpSession session, User user) { + session.setAttribute(USER, user); + } - /** - * 从Session获取当前用户信息 - * @param session - * @return - */ - public static User getUserFromSession(HttpSession session) { - Object attribute = session.getAttribute(USER); - return attribute == null ? null : (User) attribute; - } + /** + * 从Session获取当前用户信息 + * + * @param session + * @return + */ + public static User getUserFromSession(HttpSession session) { + Object attribute = session.getAttribute(USER); + return attribute == null ? null : (User) attribute; + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/util/Variable.java b/src/main/java/me/kafeitu/demo/activiti/util/Variable.java index edf1135b41..ef2bbe8bdc 100644 --- a/src/main/java/me/kafeitu/demo/activiti/util/Variable.java +++ b/src/main/java/me/kafeitu/demo/activiti/util/Variable.java @@ -1,64 +1,66 @@ package me.kafeitu.demo.activiti.util; -import java.util.HashMap; -import java.util.Map; - import jodd.util.StringUtil; - import org.apache.commons.beanutils.ConvertUtils; +import java.util.HashMap; +import java.util.Map; + public class Variable { - private String keys; - private String values; - private String types; - - public String getKeys() { - return keys; - } - - public void setKeys(String keys) { - this.keys = keys; - } - - public String getValues() { - return values; - } - - public void setValues(String values) { - this.values = values; - } - - public String getTypes() { - return types; - } - - public void setTypes(String types) { - this.types = types; - } - - public Map getVariableMap() { - Map vars = new HashMap(); - - ConvertUtils.register(new DateConverter(), java.util.Date.class); - - if (StringUtil.isBlank(keys)) { - return vars; - } - - String[] arrayKey = keys.split(","); - String[] arrayValue = values.split(","); - String[] arrayType = types.split(","); - for (int i = 0; i < arrayKey.length; i++) { - String key = arrayKey[i]; - String value = arrayValue[i]; - String type = arrayType[i]; - - Class targetType = Enum.valueOf(PropertyType.class, type).getValue(); - Object objectValue = ConvertUtils.convert(value, targetType); - vars.put(key, objectValue); - } - return vars; - } + private String keys; + private String values; + private String types; + + public String getKeys() { + return keys; + } + + public void setKeys(String keys) { + this.keys = keys; + } + + public String getValues() { + return values; + } + + public void setValues(String values) { + this.values = values; + } + + public String getTypes() { + return types; + } + + public void setTypes(String types) { + this.types = types; + } + + public Map getVariableMap() { + Map vars = new HashMap(); + + ConvertUtils.register(new DateConverter(), java.util.Date.class); + + if (StringUtil.isBlank(keys)) { + return vars; + } + + String[] arrayKey = keys.split(","); + String[] arrayValue = values.split(","); + String[] arrayType = types.split(","); + for (int i = 0; i < arrayKey.length; i++) { + if ("".equals(arrayKey[i]) || "".equals(arrayValue[i]) || "".equals(arrayType[i])) { + continue; + } + String key = arrayKey[i]; + String value = arrayValue[i]; + String type = arrayType[i]; + + Class targetType = Enum.valueOf(PropertyType.class, type).getValue(); + Object objectValue = ConvertUtils.convert(value, targetType); + vars.put(key, objectValue); + } + return vars; + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/util/WorkflowUtils.java b/src/main/java/me/kafeitu/demo/activiti/util/WorkflowUtils.java index 72085c17be..13e9bf7b3e 100644 --- a/src/main/java/me/kafeitu/demo/activiti/util/WorkflowUtils.java +++ b/src/main/java/me/kafeitu/demo/activiti/util/WorkflowUtils.java @@ -1,30 +1,83 @@ package me.kafeitu.demo.activiti.util; +import org.activiti.engine.RepositoryService; +import org.activiti.engine.repository.ProcessDefinition; +import org.apache.commons.io.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; import java.util.Map; /** - * - * * @author HenryYan */ public class WorkflowUtils { - /** - * 转换流程节点类型为中文说明 - * @param type 英文名称 - * @return 翻译后的中文名称 - */ - public static String parseToZhType(String type) { - Map types = new HashMap(); - types.put("userTask", "用户任务"); - types.put("serviceTask", "系统任务"); - types.put("startEvent", "开始节点"); - types.put("endEvent", "结束节点"); - types.put("exclusiveGateway", "条件判断节点(系统自动根据条件处理)"); - types.put("inclusiveGateway", "并行处理任务"); - types.put("callActivity", "子流程"); - return types.get(type) == null ? type: types.get(type); - } - + private static Logger logger = LoggerFactory.getLogger(WorkflowUtils.class); + + /** + * 转换流程节点类型为中文说明 + * + * @param type 英文名称 + * @return 翻译后的中文名称 + */ + public static String parseToZhType(String type) { + Map types = new HashMap(); + types.put("userTask", "用户任务"); + types.put("serviceTask", "系统任务"); + types.put("startEvent", "开始节点"); + types.put("endEvent", "结束节点"); + types.put("exclusiveGateway", "条件判断节点(系统自动根据条件处理)"); + types.put("inclusiveGateway", "并行处理任务"); + types.put("callActivity", "子流程"); + return types.get(type) == null ? type : types.get(type); + } + + /** + * 导出图片文件到硬盘 + * + * @return 文件的全路径 + */ + public static String exportDiagramToFile(RepositoryService repositoryService, ProcessDefinition processDefinition, String exportDir) throws IOException { + String diagramResourceName = processDefinition.getDiagramResourceName(); + String key = processDefinition.getKey(); + int version = processDefinition.getVersion(); + String diagramPath = ""; + + InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), diagramResourceName); + byte[] b = new byte[resourceAsStream.available()]; + + @SuppressWarnings("unused") + int len = -1; + resourceAsStream.read(b, 0, b.length); + + // create file if not exist + String diagramDir = exportDir + "/" + key + "/" + version; + File diagramDirFile = new File(diagramDir); + if (!diagramDirFile.exists()) { + diagramDirFile.mkdirs(); + } + diagramPath = diagramDir + "/" + diagramResourceName; + File file = new File(diagramPath); + + // 文件存在退出 + if (file.exists()) { + // 文件大小相同时直接返回否则重新创建文件(可能损坏) + logger.debug("diagram exist, ignore... : {}", diagramPath); + return diagramPath; + } else { + file.createNewFile(); + } + + logger.debug("export diagram to : {}", diagramPath); + + // wirte bytes to file + FileUtils.writeByteArrayToFile(file, b, true); + return diagramPath; + } + } diff --git a/src/main/java/me/kafeitu/demo/activiti/util/cache/CacheListener.java b/src/main/java/me/kafeitu/demo/activiti/util/cache/CacheListener.java new file mode 100644 index 0000000000..5ac71f4bba --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/util/cache/CacheListener.java @@ -0,0 +1,59 @@ +package me.kafeitu.demo.activiti.util.cache; + +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; +import org.infinispan.notifications.Listener; +import org.infinispan.notifications.cachelistener.annotation.CacheEntryCreated; +import org.infinispan.notifications.cachelistener.annotation.CacheEntryEvicted; +import org.infinispan.notifications.cachelistener.annotation.CacheEntryModified; +import org.infinispan.notifications.cachelistener.annotation.CacheEntryRemoved; +import org.infinispan.notifications.cachelistener.event.CacheEntryCreatedEvent; +import org.infinispan.notifications.cachelistener.event.CacheEntryEvictedEvent; +import org.infinispan.notifications.cachelistener.event.CacheEntryModifiedEvent; +import org.infinispan.notifications.cachelistener.event.CacheEntryRemovedEvent; +import org.infinispan.notifications.cachemanagerlistener.annotation.CacheStarted; +import org.infinispan.notifications.cachemanagerlistener.annotation.CacheStopped; +import org.infinispan.notifications.cachemanagerlistener.event.CacheStartedEvent; +import org.infinispan.notifications.cachemanagerlistener.event.CacheStoppedEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Joram Barrez + */ +@SuppressWarnings("deprecation") +@Listener +public class CacheListener { + + private static final Logger logger = LoggerFactory.getLogger(CacheListener.class); + + @CacheStarted + public void cacheStarted(CacheStartedEvent event) { + logger.info("Distributed cache started"); + } + + @CacheStopped + public void cacheStopped(CacheStoppedEvent event) { + logger.info("Distributed cache stopped"); + } + + @CacheEntryModified + public void cacheEntryModified(CacheEntryModifiedEvent event) { + logger.info("Cache entry with key '" + event.getKey() + " modified in cache (local cache size = " + event.getCache().size() + ")"); + } + + @CacheEntryCreated + public void cacheEntryCreated(CacheEntryCreatedEvent event) { + logger.info("Cache entry with key '" + event.getKey() + " added to cache (local cache size = " + event.getCache().size() + ")"); + } + + @CacheEntryRemoved + public void cacheEntryRemoved(CacheEntryRemovedEvent event) { + logger.info("Cache entry with key '" + event.getKey() + " removed from cache (local cache size = " + event.getCache().size() + ")"); + } + + @CacheEntryEvicted + public void cacheEntryEvicted(CacheEntryEvictedEvent event) { + logger.info("Cache entry with key '" + event.getKey() + " evicted from cache (local cache size = " + event.getCache().size() + ")"); + } + +} \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/util/cache/DistributedCache.java b/src/main/java/me/kafeitu/demo/activiti/util/cache/DistributedCache.java new file mode 100644 index 0000000000..8d4d486905 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/util/cache/DistributedCache.java @@ -0,0 +1,42 @@ +package me.kafeitu.demo.activiti.util.cache; + +import org.activiti.engine.impl.persistence.deploy.DeploymentCache; +import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity; +import org.infinispan.Cache; +import org.infinispan.manager.CacheContainer; +import org.infinispan.manager.DefaultCacheManager; + +/** + * @author Joram Barrez + */ +public class DistributedCache implements DeploymentCache { + + protected Cache cache; + + public DistributedCache() { + try { + CacheContainer manager = new DefaultCacheManager("inifispan-cfg.xml"); + this.cache = manager.getCache(); + this.cache.addListener(new CacheListener()); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public ProcessDefinitionEntity get(String id) { + return cache.get(id); + } + + public void add(String id, ProcessDefinitionEntity processDefinitionEntity) { + cache.put(id, processDefinitionEntity); + } + + public void remove(String id) { + cache.remove(id); + } + + public void clear() { + cache.clear(); + } + +} \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/web/LoginController.java b/src/main/java/me/kafeitu/demo/activiti/web/LoginController.java index 1a1c60da1f..035888c2ec 100644 --- a/src/main/java/me/kafeitu/demo/activiti/web/LoginController.java +++ b/src/main/java/me/kafeitu/demo/activiti/web/LoginController.java @@ -5,15 +5,15 @@ /** * 登录页面 - * + * * @author HenryYan */ @Controller public class LoginController { - @RequestMapping(value = "/login") - public String login() { - return "login"; - } - + @RequestMapping(value = "/login") + public String login() { + return "login"; + } + } diff --git a/src/main/java/me/kafeitu/demo/activiti/web/MainController.java b/src/main/java/me/kafeitu/demo/activiti/web/MainController.java index 44efe8dab5..48266ac8cd 100644 --- a/src/main/java/me/kafeitu/demo/activiti/web/MainController.java +++ b/src/main/java/me/kafeitu/demo/activiti/web/MainController.java @@ -12,14 +12,14 @@ @RequestMapping("/main") public class MainController { - @RequestMapping(value = "/index") - public String index() { - return "/main/index"; - } - - @RequestMapping(value = "/welcome") - public String welcome() { - return "/main/welcome"; - } - + @RequestMapping(value = "/index") + public String index() { + return "/main/index"; + } + + @RequestMapping(value = "/welcome") + public String welcome() { + return "/main/welcome"; + } + } diff --git a/src/main/java/me/kafeitu/demo/activiti/web/form/dynamic/DynamicFormController.java b/src/main/java/me/kafeitu/demo/activiti/web/form/dynamic/DynamicFormController.java index 7262a7b68d..9b5fb6f9b1 100644 --- a/src/main/java/me/kafeitu/demo/activiti/web/form/dynamic/DynamicFormController.java +++ b/src/main/java/me/kafeitu/demo/activiti/web/form/dynamic/DynamicFormController.java @@ -1,17 +1,18 @@ package me.kafeitu.demo.activiti.web.form.dynamic; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; - import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import me.kafeitu.demo.activiti.util.Page; +import me.kafeitu.demo.activiti.util.PageUtil; import me.kafeitu.demo.activiti.util.UserUtil; - import org.activiti.engine.FormService; import org.activiti.engine.HistoryService; import org.activiti.engine.IdentityService; @@ -20,11 +21,14 @@ import org.activiti.engine.TaskService; import org.activiti.engine.form.FormProperty; import org.activiti.engine.history.HistoricProcessInstance; +import org.activiti.engine.history.HistoricProcessInstanceQuery; import org.activiti.engine.identity.User; import org.activiti.engine.impl.form.StartFormDataImpl; import org.activiti.engine.impl.form.TaskFormDataImpl; import org.activiti.engine.repository.ProcessDefinition; +import org.activiti.engine.repository.ProcessDefinitionQuery; import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.runtime.ProcessInstanceQuery; import org.activiti.engine.task.Task; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -34,6 +38,7 @@ import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.support.RedirectAttributes; @@ -42,267 +47,347 @@ * 动态表单Controller * 了解不同表单请访问:http://www.kafeitu.me/activiti/2012/08/05/diff-activiti * -workflow-forms.html - * + * * @author HenryYan */ @Controller @RequestMapping(value = "/form/dynamic") public class DynamicFormController { - private Logger logger = LoggerFactory.getLogger(getClass()); - - @Autowired - private RepositoryService repositoryService; - - @Autowired - private FormService formService; - - @Autowired - private TaskService taskService; - - @Autowired - private IdentityService identityService; + private Logger logger = LoggerFactory.getLogger(getClass()); + @Autowired + private RepositoryService repositoryService; + @Autowired + private FormService formService; + @Autowired + private TaskService taskService; + @Autowired + private IdentityService identityService; + @Autowired + private HistoryService historyService; + @Autowired + private RuntimeService runtimeService; - @Autowired - private HistoryService historyService; - - @Autowired - private RuntimeService runtimeService; + /** + * 动态form流程列表 + * + * @param model + * @return + */ + @RequestMapping(value = {"process-list", ""}) + public ModelAndView processDefinitionList(Model model, @RequestParam(value = "processType", required = false) String processType, HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/form/dynamic/dynamic-form-process-list", Collections.singletonMap("processType", processType)); + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + + if (!StringUtils.equals(processType, "all")) { + /* + * 只读取动态表单的流程 + */ + ProcessDefinitionQuery query1 = repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave-dynamic-from").active().orderByDeploymentId().desc(); + List list = query1.listPage(pageParams[0], pageParams[1]); + + ProcessDefinitionQuery query2 = repositoryService.createProcessDefinitionQuery().processDefinitionKey("dispatch").active().orderByDeploymentId().desc(); + List dispatchList = query2.listPage(pageParams[0], pageParams[1]); + + ProcessDefinitionQuery query3 = repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave-jpa").active().orderByDeploymentId().desc(); + List list3 = query3.listPage(pageParams[0], pageParams[1]); + + list.addAll(list3); + list.addAll(dispatchList); + + page.setResult(list); + page.setTotalCount(query1.count() + query2.count()); + } else { + // 读取所有流程 + ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery().active().orderByDeploymentId().desc(); + List list = query.list(); + page.setResult(list); + page.setTotalCount(query.count()); + } - /** - * 动态form流程列表 - * - * @param model - * @return - */ - @RequestMapping(value = { "process-list", "" }) - public ModelAndView processDefinitionList(Model model) { - ModelAndView mav = new ModelAndView("/form/dynamic/dynamic-form-process-list"); + mav.addObject("page", page); + return mav; + } - /* - * 只读取动态表单:leave-dynamic-from + /** + * 初始化启动流程,读取启动流程的表单字段来渲染start form */ - List list = repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave-dynamic-from").active().list(); - List dispatchList = repositoryService.createProcessDefinitionQuery().processDefinitionKey("dispatch").active().list(); - list.addAll(dispatchList); - mav.addObject("processes", list); - return mav; - } - - /** - * 读取启动流程的表单字段 - */ - @RequestMapping(value = "get-form/start/{processDefinitionId}") - @ResponseBody - @SuppressWarnings("unchecked") - public Map findStartForm(@PathVariable("processDefinitionId") String processDefinitionId) throws Exception { - Map result = new HashMap(); - StartFormDataImpl startFormData = (StartFormDataImpl) formService.getStartFormData(processDefinitionId); - startFormData.setProcessDefinition(null); + @RequestMapping(value = "get-form/start/{processDefinitionId}") + @ResponseBody + @SuppressWarnings("unchecked") + public Map findStartForm(@PathVariable("processDefinitionId") String processDefinitionId) throws Exception { + Map result = new HashMap(); + StartFormDataImpl startFormData = (StartFormDataImpl) formService.getStartFormData(processDefinitionId); + startFormData.setProcessDefinition(null); /* * 读取enum类型数据,用于下拉框 */ - List formProperties = startFormData.getFormProperties(); - for (FormProperty formProperty : formProperties) { - Map values = (Map) formProperty.getType().getInformation("values"); - if (values != null) { - for (Entry enumEntry : values.entrySet()) { - logger.debug("enum, key: {}, value: {}", enumEntry.getKey(), enumEntry.getValue()); + List formProperties = startFormData.getFormProperties(); + for (FormProperty formProperty : formProperties) { + Map values = (Map) formProperty.getType().getInformation("values"); + if (values != null) { + for (Entry enumEntry : values.entrySet()) { + logger.debug("enum, key: {}, value: {}", enumEntry.getKey(), enumEntry.getValue()); + } + result.put("enum_" + formProperty.getId(), values); + } } - result.put("enum_" + formProperty.getId(), values); - } - } - result.put("form", startFormData); + result.put("form", startFormData); - return result; - } + return result; + } - /** - * 读取Task的表单 - */ - @SuppressWarnings("unchecked") - @RequestMapping(value = "get-form/task/{taskId}") - @ResponseBody - public Map findTaskForm(@PathVariable("taskId") String taskId) throws Exception { - Map result = new HashMap(); - TaskFormDataImpl taskFormData = (TaskFormDataImpl) formService.getTaskFormData(taskId); + /** + * 读取Task的表单 + */ + @SuppressWarnings("unchecked") + @RequestMapping(value = "get-form/task/{taskId}") + @ResponseBody + public Map findTaskForm(@PathVariable("taskId") String taskId) throws Exception { + Map result = new HashMap(); + TaskFormDataImpl taskFormData = (TaskFormDataImpl) formService.getTaskFormData(taskId); - // 设置task为null,否则输出json的时候会报错 - taskFormData.setTask(null); + // 设置task为null,否则输出json的时候会报错 + taskFormData.setTask(null); - result.put("taskFormData", taskFormData); + result.put("taskFormData", taskFormData); /* * 读取enum类型数据,用于下拉框 */ - List formProperties = taskFormData.getFormProperties(); - for (FormProperty formProperty : formProperties) { - Map values = (Map) formProperty.getType().getInformation("values"); - if (values != null) { - for (Entry enumEntry : values.entrySet()) { - logger.debug("enum, key: {}, value: {}", enumEntry.getKey(), enumEntry.getValue()); + List formProperties = taskFormData.getFormProperties(); + for (FormProperty formProperty : formProperties) { + Map values = (Map) formProperty.getType().getInformation("values"); + if (values != null) { + for (Entry enumEntry : values.entrySet()) { + logger.debug("enum, key: {}, value: {}", enumEntry.getKey(), enumEntry.getValue()); + } + result.put(formProperty.getId(), values); + } } - result.put(formProperty.getId(), values); - } - } - return result; - } - - /** - * 提交task的并保存form - */ - @RequestMapping(value = "task/complete/{taskId}") - @SuppressWarnings("unchecked") - public String completeTask(@PathVariable("taskId") String taskId, RedirectAttributes redirectAttributes, HttpServletRequest request) { - Map formProperties = new HashMap(); - - // 从request中读取参数然后转换 - Map parameterMap = request.getParameterMap(); - Set> entrySet = parameterMap.entrySet(); - for (Entry entry : entrySet) { - String key = entry.getKey(); - - // fp_的意思是form paremeter - if (StringUtils.defaultString(key).startsWith("fp_")) { - formProperties.put(key.split("_")[1], entry.getValue()[0]); - } + return result; } - logger.debug("start form parameters: {}", formProperties); + /** + * 办理任务,提交task的并保存form + */ + @RequestMapping(value = "task/complete/{taskId}") + @SuppressWarnings("unchecked") + public String completeTask(@PathVariable("taskId") String taskId, @RequestParam(value = "processType", required = false) String processType, + RedirectAttributes redirectAttributes, HttpServletRequest request) { + Map formProperties = new HashMap(); + + // 从request中读取参数然后转换 + Map parameterMap = request.getParameterMap(); + Set> entrySet = parameterMap.entrySet(); + for (Entry entry : entrySet) { + String key = entry.getKey(); + + // fp_的意思是form paremeter + if (StringUtils.defaultString(key).startsWith("fp_")) { + formProperties.put(key.split("_")[1], entry.getValue()[0]); + } + } - User user = UserUtil.getUserFromSession(request.getSession()); + logger.debug("start form parameters: {}", formProperties); - // 用户未登陆不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等 - if (user == null || StringUtils.isBlank(user.getId())) { - return "redirect:/login?timeout=true"; - } - identityService.setAuthenticatedUserId(user.getId()); - - formService.submitTaskFormData(taskId, formProperties); - - redirectAttributes.addFlashAttribute("message", "任务完成:taskId=" + taskId); - return "redirect:/form/dynamic/task/list"; - } - - /** - * 读取启动流程的表单字段 - */ - @RequestMapping(value = "start-process/{processDefinitionId}") - @SuppressWarnings("unchecked") - public String submitStartFormAndStartProcessInstance(@PathVariable("processDefinitionId") String processDefinitionId, RedirectAttributes redirectAttributes, - HttpServletRequest request) { - Map formProperties = new HashMap(); - - // 从request中读取参数然后转换 - Map parameterMap = request.getParameterMap(); - Set> entrySet = parameterMap.entrySet(); - for (Entry entry : entrySet) { - String key = entry.getKey(); - - // fp_的意思是form paremeter - if (StringUtils.defaultString(key).startsWith("fp_")) { - formProperties.put(key.split("_")[1], entry.getValue()[0]); - } + User user = UserUtil.getUserFromSession(request.getSession()); + + // 用户未登录不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等 + if (user == null || StringUtils.isBlank(user.getId())) { + return "redirect:/login?timeout=true"; + } + try { + identityService.setAuthenticatedUserId(user.getId()); + formService.submitTaskFormData(taskId, formProperties); + } finally { + identityService.setAuthenticatedUserId(null); + } + + redirectAttributes.addFlashAttribute("message", "任务完成:taskId=" + taskId); + return "redirect:/form/dynamic/task/list?processType=" + processType; } - logger.debug("start form parameters: {}", formProperties); + /** + * 提交启动流程 + */ + @RequestMapping(value = "start-process/{processDefinitionId}") + @SuppressWarnings("unchecked") + public String submitStartFormAndStartProcessInstance(@PathVariable("processDefinitionId") String processDefinitionId, + @RequestParam(value = "processType", required = false) String processType, + RedirectAttributes redirectAttributes, + HttpServletRequest request) { + Map formProperties = new HashMap(); + + // 从request中读取参数然后转换 + Map parameterMap = request.getParameterMap(); + Set> entrySet = parameterMap.entrySet(); + for (Entry entry : entrySet) { + String key = entry.getKey(); + + // fp_的意思是form paremeter + if (StringUtils.defaultString(key).startsWith("fp_")) { + formProperties.put(key.split("_")[1], entry.getValue()[0]); + } + } + + logger.debug("start form parameters: {}", formProperties); + + User user = UserUtil.getUserFromSession(request.getSession()); + // 用户未登录不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等 + if (user == null || StringUtils.isBlank(user.getId())) { + return "redirect:/login?timeout=true"; + } + ProcessInstance processInstance = null; + try { + identityService.setAuthenticatedUserId(user.getId()); + processInstance = formService.submitStartFormData(processDefinitionId, formProperties); + logger.debug("start a processinstance: {}", processInstance); + } finally { + identityService.setAuthenticatedUserId(null); + } + redirectAttributes.addFlashAttribute("message", "启动成功,流程ID:" + processInstance.getId()); - User user = UserUtil.getUserFromSession(request.getSession()); - // 用户未登陆不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等 - if (user == null || StringUtils.isBlank(user.getId())) { - return "redirect:/login?timeout=true"; + return "redirect:/form/dynamic/process-list?processType=" + processType; } - identityService.setAuthenticatedUserId(user.getId()); - ProcessInstance processInstance = formService.submitStartFormData(processDefinitionId, formProperties); - logger.debug("start a processinstance: {}", processInstance); + /** + * task列表 + * + * @param model + * @return + */ + @RequestMapping(value = "task/list") + public ModelAndView taskList(@RequestParam(value = "processType", required = false) String processType, + HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/form/dynamic/dynamic-form-task-list"); + User user = UserUtil.getUserFromSession(request.getSession()); + + List tasks = new ArrayList(); + + if (!StringUtils.equals(processType, "all")) { + /** + * 这里为了演示区分开自定义表单的请假流程,值读取leave-dynamic-from + * 在FormKeyController中有使用native方式查询的例子 + */ + + List dynamicFormTasks = taskService.createTaskQuery().processDefinitionKey("leave-dynamic-from") + .taskCandidateOrAssigned(user.getId()).active().orderByTaskId().desc().list(); + + List dispatchTasks = taskService.createTaskQuery().processDefinitionKey("dispatch") + .taskCandidateOrAssigned(user.getId()).active().orderByTaskId().desc().list(); + + List leaveJpaTasks = taskService.createTaskQuery().processDefinitionKey("leave-jpa") + .taskCandidateOrAssigned(user.getId()).active().orderByTaskId().desc().list(); + + tasks.addAll(dynamicFormTasks); + tasks.addAll(dispatchTasks); + tasks.addAll(leaveJpaTasks); + } else { + tasks = taskService.createTaskQuery().taskCandidateOrAssigned(user.getId()).active().orderByTaskId().desc().list(); + } - redirectAttributes.addFlashAttribute("message", "启动成功,流程ID:" + processInstance.getId()); - return "redirect:/form/dynamic/process-list"; - } + mav.addObject("tasks", tasks); + return mav; + } - /** - * task列表 - * - * @param model - * @return - */ - @RequestMapping(value = "task/list") - public ModelAndView taskList(Model model, HttpServletRequest request) { - ModelAndView mav = new ModelAndView("/form/dynamic/dynamic-form-task-list"); - User user = UserUtil.getUserFromSession(request.getSession()); + /** + * 签收任务 + */ + @RequestMapping(value = "task/claim/{id}") + public String claim(@PathVariable("id") String taskId, HttpSession session, + HttpServletRequest request, + RedirectAttributes redirectAttributes) { + String userId = UserUtil.getUserFromSession(session).getId(); + taskService.claim(taskId, userId); + redirectAttributes.addFlashAttribute("message", "任务已签收"); + return "redirect:/form/dynamic/task/list?processType=" + StringUtils.defaultString(request.getParameter("processType")); + } - List tasks = new ArrayList(); + /** + * 运行中的流程实例 + * + * @param model + * @return + */ + @RequestMapping(value = "process-instance/running/list") + public ModelAndView running(Model model, @RequestParam(value = "processType", required = false) String processType, + HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/form/running-list", Collections.singletonMap("processType", processType)); + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + + if (!StringUtils.equals(processType, "all")) { + ProcessInstanceQuery leaveDynamicQuery = runtimeService.createProcessInstanceQuery() + .processDefinitionKey("leave-dynamic-from").orderByProcessInstanceId().desc().active(); + List list = leaveDynamicQuery.listPage(pageParams[0], pageParams[1]); + + ProcessInstanceQuery dispatchQuery = runtimeService.createProcessInstanceQuery() + .processDefinitionKey("dispatch").active().orderByProcessInstanceId().desc(); + List list2 = dispatchQuery.listPage(pageParams[0], pageParams[1]); + list.addAll(list2); + + ProcessInstanceQuery leaveJpaQuery = runtimeService.createProcessInstanceQuery() + .processDefinitionKey("leave-jpa").active().orderByProcessInstanceId().desc(); + List list3 = leaveJpaQuery.listPage(pageParams[0], pageParams[1]); + list.addAll(list3); + + page.setResult(list); + page.setTotalCount(leaveDynamicQuery.count() + dispatchQuery.count()); + } else { + ProcessInstanceQuery dynamicQuery = runtimeService.createProcessInstanceQuery().orderByProcessInstanceId().desc().active(); + List list = dynamicQuery.listPage(pageParams[0], pageParams[1]); + page.setResult(list); + page.setTotalCount(dynamicQuery.count()); + } + mav.addObject("page", page); + return mav; + } /** - * 这里为了演示区分开自定义表单的请假流程,值读取leave-dynamic-from - * 在FormKeyController中有使用native方式查询的例子 + * 已结束的流程实例 + * + * @param model + * @return */ + @RequestMapping(value = "process-instance/finished/list") + public ModelAndView finished(Model model, @RequestParam(value = "processType", required = false) String processType, + HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/form/finished-list", Collections.singletonMap("processType", processType)); + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + + if (!StringUtils.equals(processType, "all")) { + HistoricProcessInstanceQuery leaveDynamicQuery = historyService.createHistoricProcessInstanceQuery() + .processDefinitionKey("leave-dynamic-from").finished().orderByProcessInstanceEndTime().desc(); + List list = leaveDynamicQuery.listPage(pageParams[0], pageParams[1]); + + HistoricProcessInstanceQuery dispatchQuery = historyService.createHistoricProcessInstanceQuery() + .processDefinitionKey("dispatch").finished().orderByProcessInstanceEndTime().desc(); + List list2 = dispatchQuery.listPage(pageParams[0], pageParams[1]); + + HistoricProcessInstanceQuery leaveJpaQuery = historyService.createHistoricProcessInstanceQuery() + .processDefinitionKey("leave-jpa").finished().orderByProcessInstanceEndTime().desc(); + List list3 = leaveJpaQuery.listPage(pageParams[0], pageParams[1]); + + list.addAll(list2); + list.addAll(list3); + + page.setResult(list); + page.setTotalCount(leaveDynamicQuery.count() + dispatchQuery.count()); + } else { + HistoricProcessInstanceQuery dynamicQuery = historyService.createHistoricProcessInstanceQuery() + .finished().orderByProcessInstanceEndTime().desc(); + List list = dynamicQuery.listPage(pageParams[0], pageParams[1]); + page.setResult(list); + page.setTotalCount(dynamicQuery.count()); + } - // 分配到当前登陆用户的任务 - List list = taskService.createTaskQuery().processDefinitionKey("leave-dynamic-from").taskAssignee(user.getId()).active().list(); - - // 为签收的任务 - List list2 = taskService.createTaskQuery().processDefinitionKey("leave-dynamic-from").taskCandidateUser(user.getId()).active().list(); - - tasks.addAll(list); - tasks.addAll(list2); - - List list3 = taskService.createTaskQuery().processDefinitionKey("dispatch").taskAssignee(user.getId()).active().list(); - - // 为签收的任务 - List list4 = taskService.createTaskQuery().processDefinitionKey("dispatch").taskCandidateUser(user.getId()).active().list(); - - tasks.addAll(list3); - tasks.addAll(list4); - - mav.addObject("tasks", tasks); - return mav; - } - - /** - * 签收任务 - */ - @RequestMapping(value = "task/claim/{id}") - public String claim(@PathVariable("id") String taskId, HttpSession session, RedirectAttributes redirectAttributes) { - String userId = UserUtil.getUserFromSession(session).getId(); - taskService.claim(taskId, userId); - redirectAttributes.addFlashAttribute("message", "任务已签收"); - return "redirect:/form/dynamic/task/list"; - } - - /** - * 运行中的流程实例 - * - * @param model - * @return - */ - @RequestMapping(value = "process-instance/running/list") - public ModelAndView running(Model model, HttpServletRequest request) { - ModelAndView mav = new ModelAndView("/form//running-list"); - List list = runtimeService.createProcessInstanceQuery().processDefinitionKey("leave-dynamic-from").active().list(); - List list2 = runtimeService.createProcessInstanceQuery().processDefinitionKey("dispatch").active().list(); - list.addAll(list2); - mav.addObject("list", list); - return mav; - } - - /** - * 已结束的流程实例 - * - * @param model - * @return - */ - @RequestMapping(value = "process-instance/finished/list") - public ModelAndView finished(Model model, HttpServletRequest request) { - ModelAndView mav = new ModelAndView("/form/finished-list"); - List list = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("leave-dynamic-from").finished().list(); - List list2 = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("dispatch").finished().list(); - list.addAll(list2); - mav.addObject("list", list); - return mav; - } + mav.addObject("page", page); + return mav; + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/web/form/formkey/FormKeyController.java b/src/main/java/me/kafeitu/demo/activiti/web/form/formkey/FormKeyController.java index f2f2e11e58..4c7dbfd5f7 100644 --- a/src/main/java/me/kafeitu/demo/activiti/web/form/formkey/FormKeyController.java +++ b/src/main/java/me/kafeitu/demo/activiti/web/form/formkey/FormKeyController.java @@ -1,28 +1,18 @@ package me.kafeitu.demo.activiti.web.form.formkey; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpSession; - +import me.kafeitu.demo.activiti.util.Page; +import me.kafeitu.demo.activiti.util.PageUtil; import me.kafeitu.demo.activiti.util.UserUtil; - -import org.activiti.engine.FormService; -import org.activiti.engine.HistoryService; -import org.activiti.engine.IdentityService; -import org.activiti.engine.ManagementService; -import org.activiti.engine.RepositoryService; -import org.activiti.engine.RuntimeService; -import org.activiti.engine.TaskService; +import org.activiti.engine.*; import org.activiti.engine.history.HistoricProcessInstance; +import org.activiti.engine.history.HistoricProcessInstanceQuery; import org.activiti.engine.identity.User; import org.activiti.engine.impl.persistence.entity.SuspensionState; import org.activiti.engine.repository.ProcessDefinition; +import org.activiti.engine.repository.ProcessDefinitionQuery; import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.runtime.ProcessInstanceQuery; +import org.activiti.engine.task.NativeTaskQuery; import org.activiti.engine.task.Task; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -36,224 +26,265 @@ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; + /** * 外置表单Controller * 了解不同表单请访问:http://www.kafeitu.me/activiti/2012/08/05/diff-activiti * -workflow-forms.html - * + * * @author HenryYan */ @Controller @RequestMapping(value = "/form/formkey") public class FormKeyController { - private Logger logger = LoggerFactory.getLogger(getClass()); - - @Autowired - private RepositoryService repositoryService; + private Logger logger = LoggerFactory.getLogger(getClass()); - @Autowired - private FormService formService; + @Autowired + private RepositoryService repositoryService; - @Autowired - private TaskService taskService; + @Autowired + private FormService formService; - @Autowired - private IdentityService identityService; + @Autowired + private TaskService taskService; - @Autowired - private HistoryService historyService; + @Autowired + private IdentityService identityService; - @Autowired - private RuntimeService runtimeService; + @Autowired + private HistoryService historyService; - @Autowired - private ManagementService managementService; + @Autowired + private RuntimeService runtimeService; - /** - * 动态form流程列表 - * - * @param model - * @return - */ - @RequestMapping(value = { "process-list", "" }) - public ModelAndView processDefinitionList(Model model) { - ModelAndView mav = new ModelAndView("/form/formkey/formkey-process-list"); + @Autowired + private ManagementService managementService; + /** + * 动态form流程列表 + * + * @param model + * @return + */ + @RequestMapping(value = {"process-list", ""}) + public ModelAndView processDefinitionList(Model model, HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/form/formkey/formkey-process-list"); + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); /* * 只读取动态表单:leave-formkey */ - List list = repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave-formkey").active().list(); - mav.addObject("processes", list); - return mav; - } - - /** - * 读取启动流程的表单内容 - */ - @RequestMapping(value = "get-form/start/{processDefinitionId}") - @ResponseBody - public Object findStartForm(@PathVariable("processDefinitionId") String processDefinitionId) throws Exception { - - // 根据流程定义ID读取外置表单 - Object startForm = formService.getRenderedStartForm(processDefinitionId); - - return startForm; - } - - /** - * 读取Task的表单 - */ - @RequestMapping(value = "get-form/task/{taskId}") - @ResponseBody - public Object findTaskForm(@PathVariable("taskId") String taskId) throws Exception { - Object renderedTaskForm = formService.getRenderedTaskForm(taskId); - return renderedTaskForm; - } - - /** - * 提交task的并保存form - */ - @RequestMapping(value = "task/complete/{taskId}") - @SuppressWarnings("unchecked") - public String completeTask(@PathVariable("taskId") String taskId, RedirectAttributes redirectAttributes, HttpServletRequest request) { - Map formProperties = new HashMap(); - - // 从request中读取参数然后转换 - Map parameterMap = request.getParameterMap(); - Set> entrySet = parameterMap.entrySet(); - for (Entry entry : entrySet) { - String key = entry.getKey(); + ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery().processDefinitionKey("leave-formkey").active().orderByDeploymentId().desc(); + List list = query.listPage(pageParams[0], pageParams[1]); - /* - * 参数结构:fq_reason,用_分割 fp的意思是form paremeter 最后一个是属性名称 - */ - if (StringUtils.defaultString(key).startsWith("fp_")) { - String[] paramSplit = key.split("_"); - formProperties.put(paramSplit[1], entry.getValue()[0]); - } + page.setResult(list); + page.setTotalCount(query.count()); + mav.addObject("page", page); + return mav; } - logger.debug("start form parameters: {}", formProperties); + /** + * 初始化启动流程,读取启动流程的表单内容来渲染start form + */ + @RequestMapping(value = "get-form/start/{processDefinitionId}") + @ResponseBody + public Object findStartForm(@PathVariable("processDefinitionId") String processDefinitionId) throws Exception { - User user = UserUtil.getUserFromSession(request.getSession()); + // 根据流程定义ID读取外置表单 + Object startForm = formService.getRenderedStartForm(processDefinitionId); - // 用户未登陆不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等 - if (user == null || StringUtils.isBlank(user.getId())) { - return "redirect:/login?timeout=true"; + return startForm; } - identityService.setAuthenticatedUserId(user.getId()); - - formService.submitTaskFormData(taskId, formProperties); - - redirectAttributes.addFlashAttribute("message", "任务完成:taskId=" + taskId); - return "redirect:/form/formkey/task/list"; - } - - /** - * 读取启动流程的表单字段 - */ - @RequestMapping(value = "start-process/{processDefinitionId}") - @SuppressWarnings("unchecked") - public String submitStartFormAndStartProcessInstance(@PathVariable("processDefinitionId") String processDefinitionId, RedirectAttributes redirectAttributes, - HttpServletRequest request) { - Map formProperties = new HashMap(); - - // 从request中读取参数然后转换 - Map parameterMap = request.getParameterMap(); - Set> entrySet = parameterMap.entrySet(); - for (Entry entry : entrySet) { - String key = entry.getKey(); - - // fp_的意思是form paremeter - if (StringUtils.defaultString(key).startsWith("fp_")) { - formProperties.put(key.split("_")[1], entry.getValue()[0]); - } + + /** + * 读取Task的表单 + */ + @RequestMapping(value = "get-form/task/{taskId}") + @ResponseBody + public Object findTaskForm(@PathVariable("taskId") String taskId) throws Exception { + Object renderedTaskForm = formService.getRenderedTaskForm(taskId); + return renderedTaskForm; } - logger.debug("start form parameters: {}", formProperties); + /** + * 办理任务,提交task的并保存form + */ + @RequestMapping(value = "task/complete/{taskId}") + @SuppressWarnings("unchecked") + public String completeTask(@PathVariable("taskId") String taskId, RedirectAttributes redirectAttributes, HttpServletRequest request) { + Map formProperties = new HashMap(); + + // 从request中读取参数然后转换 + Map parameterMap = request.getParameterMap(); + Set> entrySet = parameterMap.entrySet(); + for (Entry entry : entrySet) { + String key = entry.getKey(); - User user = UserUtil.getUserFromSession(request.getSession()); - // 用户未登陆不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等 - if (user == null || StringUtils.isBlank(user.getId())) { - return "redirect:/login?timeout=true"; + /* + * 参数结构:fq_reason,用_分割 fp的意思是form paremeter 最后一个是属性名称 + */ + if (StringUtils.defaultString(key).startsWith("fp_")) { + String[] paramSplit = key.split("_"); + formProperties.put(paramSplit[1], entry.getValue()[0]); + } + } + + logger.debug("start form parameters: {}", formProperties); + + User user = UserUtil.getUserFromSession(request.getSession()); + + // 用户未登录不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等 + if (user == null || StringUtils.isBlank(user.getId())) { + return "redirect:/login?timeout=true"; + } + try { + identityService.setAuthenticatedUserId(user.getId()); + + formService.submitTaskFormData(taskId, formProperties); + } finally { + identityService.setAuthenticatedUserId(null); + } + + redirectAttributes.addFlashAttribute("message", "任务完成:taskId=" + taskId); + return "redirect:/form/formkey/task/list"; } - identityService.setAuthenticatedUserId(user.getId()); - - ProcessInstance processInstance = formService.submitStartFormData(processDefinitionId, formProperties); - logger.debug("start a processinstance: {}", processInstance); - - redirectAttributes.addFlashAttribute("message", "启动成功,流程ID:" + processInstance.getId()); - return "redirect:/form/dynamic/process-list"; - } - - /** - * task列表 - * - * @param model - * @return - */ - @RequestMapping(value = "task/list") - public ModelAndView taskList(Model model, HttpServletRequest request) { - ModelAndView mav = new ModelAndView("/form/formkey/formkey-task-list"); - User user = UserUtil.getUserFromSession(request.getSession()); /** - * 这里为了演示区分开自定义表单的请假流程,值读取leave-formkey + * 读取启动流程的表单字段 */ + @RequestMapping(value = "start-process/{processDefinitionId}") + @SuppressWarnings("unchecked") + public String submitStartFormAndStartProcessInstance(@PathVariable("processDefinitionId") String processDefinitionId, RedirectAttributes redirectAttributes, + HttpServletRequest request) { + Map formProperties = new HashMap(); + + // 从request中读取参数然后转换 + Map parameterMap = request.getParameterMap(); + Set> entrySet = parameterMap.entrySet(); + for (Entry entry : entrySet) { + String key = entry.getKey(); + + // fp_的意思是form paremeter + if (StringUtils.defaultString(key).startsWith("fp_")) { + formProperties.put(key.split("_")[1], entry.getValue()[0]); + } + } + + logger.debug("start form parameters: {}", formProperties); + + User user = UserUtil.getUserFromSession(request.getSession()); + // 用户未登录不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等 + if (user == null || StringUtils.isBlank(user.getId())) { + return "redirect:/login?timeout=true"; + } + try { + identityService.setAuthenticatedUserId(user.getId()); + + ProcessInstance processInstance = formService.submitStartFormData(processDefinitionId, formProperties); + logger.debug("start a processinstance: {}", processInstance); + + redirectAttributes.addFlashAttribute("message", "启动成功,流程ID:" + processInstance.getId()); + } finally { + identityService.setAuthenticatedUserId(null); + } + + return "redirect:/form/dynamic/process-list"; + } - // 已经签收的或者直接分配到当前人的任务 - String asigneeSql = "select distinct RES.* from ACT_RU_TASK RES inner join ACT_RE_PROCDEF D on RES.PROC_DEF_ID_ = D.ID_ WHERE RES.ASSIGNEE_ = #{userId}" - + " and D.KEY_ = #{processDefinitionKey} and RES.SUSPENSION_STATE_ = #{suspensionState}"; - - // 当前人在候选人或者候选组范围之内 - String needClaimSql = "select distinct RES.* from ACT_RU_TASK RES inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES.ID_ inner join ACT_RE_PROCDEF D on RES.PROC_DEF_ID_ = D.ID_ WHERE" - + " D.KEY_ = #{processDefinitionKey} and RES.ASSIGNEE_ is null and I.TYPE_ = 'candidate'" - + " and ( I.USER_ID_ = #{userId} or I.GROUP_ID_ IN (select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = #{userId} ) )" - + " and RES.SUSPENSION_STATE_ = #{suspensionState}"; - List tasks = taskService.createNativeTaskQuery().sql(asigneeSql + "union all " + needClaimSql).parameter("processDefinitionKey", "leave-formkey") - .parameter("suspensionState", SuspensionState.ACTIVE.getStateCode()).parameter("userId", user.getId()).list(); - - mav.addObject("tasks", tasks); - return mav; - } - - /** - * 签收任务 - */ - @RequestMapping(value = "task/claim/{id}") - public String claim(@PathVariable("id") String taskId, HttpSession session, RedirectAttributes redirectAttributes) { - String userId = UserUtil.getUserFromSession(session).getId(); - taskService.claim(taskId, userId); - redirectAttributes.addFlashAttribute("message", "任务已签收"); - return "redirect:/form/formkey/task/list"; - } - - /** - * 运行中的流程实例 - * - * @param model - * @return - */ - @RequestMapping(value = "process-instance/running/list") - public ModelAndView running(Model model, HttpServletRequest request) { - ModelAndView mav = new ModelAndView("/form/running-list"); - List list = runtimeService.createProcessInstanceQuery().processDefinitionKey("leave-formkey").active().list(); - mav.addObject("list", list); - return mav; - } - /** - * 已结束的流程实例 - * - * @param model - * @return - */ - @RequestMapping(value = "process-instance/finished/list") - public ModelAndView finished(Model model, HttpServletRequest request) { - ModelAndView mav = new ModelAndView("/form/finished-list"); - List list = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("leave-formkey").finished().list(); - mav.addObject("list", list); - return mav; - } + /** + * task列表 + * + * @param model + * @return + */ + @RequestMapping(value = "task/list") + public ModelAndView taskList(Model model, HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/form/formkey/formkey-task-list"); + User user = UserUtil.getUserFromSession(request.getSession()); + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + + /** + * 这里为了演示区分开自定义表单的请假流程,值读取leave-formkey + */ + + // 已经签收的或者直接分配到当前人的任务 + String asigneeSql = "select distinct RES.* from ACT_RU_TASK RES inner join ACT_RE_PROCDEF D on RES.PROC_DEF_ID_ = D.ID_ WHERE RES.ASSIGNEE_ = #{userId}" + + " and D.KEY_ = #{processDefinitionKey} and RES.SUSPENSION_STATE_ = #{suspensionState}"; + + // 当前人在候选人或者候选组范围之内 + String needClaimSql = "select distinct RES1.* from ACT_RU_TASK RES1 inner join ACT_RU_IDENTITYLINK I on I.TASK_ID_ = RES1.ID_ inner join ACT_RE_PROCDEF D1 on RES1.PROC_DEF_ID_ = D1.ID_ WHERE" + + " D1.KEY_ = #{processDefinitionKey} and RES1.ASSIGNEE_ is null and I.TYPE_ = 'candidate'" + + " and ( I.USER_ID_ = #{userId} or I.GROUP_ID_ IN (select g.GROUP_ID_ from ACT_ID_MEMBERSHIP g where g.USER_ID_ = #{userId} ) )" + + " and RES1.SUSPENSION_STATE_ = #{suspensionState}"; + String sql = asigneeSql + " union all " + needClaimSql; + NativeTaskQuery query = taskService.createNativeTaskQuery().sql(sql) + .parameter("processDefinitionKey", "leave-formkey").parameter("suspensionState", SuspensionState.ACTIVE.getStateCode()) + .parameter("userId", user.getId()); + List tasks = query.listPage(pageParams[0], pageParams[1]); + + page.setResult(tasks); + page.setTotalCount(query.sql("select count(*) from (" + sql + ") as CT").count()); + mav.addObject("page", page); + return mav; + } + + /** + * 签收任务 + */ + @RequestMapping(value = "task/claim/{id}") + public String claim(@PathVariable("id") String taskId, HttpSession session, RedirectAttributes redirectAttributes) { + String userId = UserUtil.getUserFromSession(session).getId(); + taskService.claim(taskId, userId); + redirectAttributes.addFlashAttribute("message", "任务已签收"); + return "redirect:/form/formkey/task/list"; + } + + /** + * 运行中的流程实例 + * + * @param model + * @return + */ + @RequestMapping(value = "process-instance/running/list") + public ModelAndView running(Model model, HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/form/running-list"); + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery().processDefinitionKey("leave-formkey").active().orderByProcessInstanceId().desc(); + List list = query.listPage(pageParams[0], pageParams[1]); + page.setResult(list); + page.setTotalCount(query.count()); + mav.addObject("page", page); + return mav; + } + + /** + * 已结束的流程实例 + * + * @param model + * @return + */ + @RequestMapping(value = "process-instance/finished/list") + public ModelAndView finished(Model model, HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/form/finished-list"); + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery().processDefinitionKey("leave-formkey").orderByProcessInstanceEndTime().desc().finished(); + List list = query.listPage(pageParams[0], pageParams[1]); + + page.setResult(list); + page.setTotalCount(query.count()); + mav.addObject("page", page); + return mav; + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/web/identify/UseController.java b/src/main/java/me/kafeitu/demo/activiti/web/identify/UseController.java index 8abbefbd49..d38262db6a 100644 --- a/src/main/java/me/kafeitu/demo/activiti/web/identify/UseController.java +++ b/src/main/java/me/kafeitu/demo/activiti/web/identify/UseController.java @@ -1,11 +1,6 @@ package me.kafeitu.demo.activiti.web.identify; -import java.util.List; - -import javax.servlet.http.HttpSession; - import me.kafeitu.demo.activiti.util.UserUtil; - import org.activiti.engine.IdentityService; import org.activiti.engine.identity.Group; import org.activiti.engine.identity.User; @@ -17,6 +12,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; +import javax.servlet.http.HttpSession; +import java.util.List; + /** * 用户相关控制器 * @@ -26,54 +24,55 @@ @RequestMapping("/user") public class UseController { - private static Logger logger = LoggerFactory.getLogger(UseController.class); - - // Activiti Identify Service - private IdentityService identityService; - - /** - * 登录系统 - * @param userName - * @param password - * @param session - * @return - */ - @RequestMapping(value = "/logon") - public String logon(@RequestParam("username") String userName, @RequestParam("password") String password, HttpSession session) { - logger.debug("logon request: {username={}, password={}}", userName, password); - boolean checkPassword = identityService.checkPassword(userName, password); - if (checkPassword) { - - // read user from database - User user = identityService.createUserQuery().userId(userName).singleResult(); - UserUtil.saveUserToSession(session, user); - - List groupList = identityService.createGroupQuery().groupMember(userName).list(); - session.setAttribute("groups", groupList); - - String[] groupNames = new String[groupList.size()]; - for (int i = 0; i < groupNames.length; i++) { - System.out.println(groupList.get(i).getName()); - groupNames[i] = groupList.get(i).getName(); - } - - session.setAttribute("groupNames", ArrayUtils.toString(groupNames)); - - return "redirect:/main/index"; - } else { - return "redirect:/login?error=true"; - } - } - - @RequestMapping(value = "/logout") - public String logout(HttpSession session) { - session.removeAttribute("user"); - return "/login"; - } - - @Autowired - public void setIdentityService(IdentityService identityService) { - this.identityService = identityService; - } + private static Logger logger = LoggerFactory.getLogger(UseController.class); + + // Activiti Identify Service + private IdentityService identityService; + + /** + * 登录系统 + * + * @param userName + * @param password + * @param session + * @return + */ + @RequestMapping(value = "/logon") + public String logon(@RequestParam("username") String userName, @RequestParam("password") String password, HttpSession session) { + logger.debug("logon request: {username={}, password={}}", userName, password); + boolean checkPassword = identityService.checkPassword(userName, password); + if (checkPassword) { + + // read user from database + User user = identityService.createUserQuery().userId(userName).singleResult(); + UserUtil.saveUserToSession(session, user); + + List groupList = identityService.createGroupQuery().groupMember(userName).list(); + session.setAttribute("groups", groupList); + + String[] groupNames = new String[groupList.size()]; + for (int i = 0; i < groupNames.length; i++) { + System.out.println(groupList.get(i).getName()); + groupNames[i] = groupList.get(i).getName(); + } + + session.setAttribute("groupNames", ArrayUtils.toString(groupNames)); + + return "redirect:/main/index"; + } else { + return "redirect:/login?error=true"; + } + } + + @RequestMapping(value = "/logout") + public String logout(HttpSession session) { + session.removeAttribute("user"); + return "/login"; + } + + @Autowired + public void setIdentityService(IdentityService identityService) { + this.identityService = identityService; + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/web/management/DatabaseController.java b/src/main/java/me/kafeitu/demo/activiti/web/management/DatabaseController.java new file mode 100644 index 0000000000..c961b21c5f --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/web/management/DatabaseController.java @@ -0,0 +1,66 @@ +package me.kafeitu.demo.activiti.web.management; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.TreeMap; +import javax.servlet.http.HttpServletRequest; + +import me.kafeitu.demo.activiti.util.Page; +import me.kafeitu.demo.activiti.util.PageUtil; +import org.activiti.engine.ManagementService; +import org.activiti.engine.management.TableMetaData; +import org.activiti.engine.management.TablePage; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.ModelAndView; + +/** + * 数据库查询控制器 + * User: henryyan + */ +@Controller +@RequestMapping("/management/database") +public class DatabaseController { + + @Autowired + ManagementService managementService; + + @RequestMapping("") + public ModelAndView index(@RequestParam(value = "tableName", required = false) String tableName, HttpServletRequest request) { + ModelAndView mav = new ModelAndView("management/database"); + + // 读取表 + Map tableCount = managementService.getTableCount(); + List keys = new ArrayList(); + keys.addAll(tableCount.keySet()); + Collections.sort(keys); + + TreeMap sortedTableCount = new TreeMap(); + + for (String key : keys) { + sortedTableCount.put(key, tableCount.get(key)); + } + + mav.addObject("tableCount", sortedTableCount); + + // 读取表记录 + if (StringUtils.isNotBlank(tableName)) { + TableMetaData tableMetaData = managementService.getTableMetaData(tableName); + mav.addObject("tableMetaData", tableMetaData); + Page> page = new Page>(10); + int[] pageParams = PageUtil.init(page, request); + TablePage tablePages = managementService.createTablePageQuery().tableName(tableName).listPage(pageParams[0], pageParams[1]); + + page.setResult(tablePages.getRows()); + page.setTotalCount(tableCount.get(tableName)); + mav.addObject("page", page); + } + return mav; + } + +} diff --git a/src/main/java/me/kafeitu/demo/activiti/web/management/IdentityController.java b/src/main/java/me/kafeitu/demo/activiti/web/management/IdentityController.java new file mode 100644 index 0000000000..3835e3775e --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/web/management/IdentityController.java @@ -0,0 +1,205 @@ +package me.kafeitu.demo.activiti.web.management; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; + +import me.kafeitu.demo.activiti.util.Page; +import me.kafeitu.demo.activiti.util.PageUtil; +import org.activiti.engine.IdentityService; +import org.activiti.engine.identity.Group; +import org.activiti.engine.identity.GroupQuery; +import org.activiti.engine.identity.User; +import org.activiti.engine.identity.UserQuery; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +/** + * 用户、组控制器 + * User: henry + */ +@Controller +@RequestMapping("/management/identity") +public class IdentityController { + + @Autowired + IdentityService identityService; + + private static final String[] INNER_GROUPS = {"admin", "user", "hr", "deptLeader"}; + + private static final String[] INNER_USERS = {"admin", "kafeitu", "hruser", "leaderuser"}; + + /** + * 组列表 + * + * @param request + * @return + */ + @RequestMapping("group/list") + public ModelAndView groupList(HttpServletRequest request) { + ModelAndView mav = new ModelAndView("management/group-list"); + + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + + GroupQuery groupQuery = identityService.createGroupQuery(); + List groupList = groupQuery.listPage(pageParams[0], pageParams[1]); + + page.setResult(groupList); + page.setTotalCount(groupQuery.count()); + mav.addObject("page", page); + + return mav; + } + + /** + * 保存Group + * + * @return + */ + @RequestMapping(value = "group/save", method = RequestMethod.POST) + public String saveGroup(@RequestParam("groupId") String groupId, + @RequestParam("groupName") String groupName, + @RequestParam("type") String type, + RedirectAttributes redirectAttributes) { + Group group = identityService.createGroupQuery().groupId(groupId).singleResult(); + if (group == null) { + group = identityService.newGroup(groupId); + } + group.setName(groupName); + group.setType(type); + identityService.saveGroup(group); + redirectAttributes.addFlashAttribute("message", "成功添加组[" + groupName + "]"); + return "redirect:/management/identity/group/list"; + } + + /** + * 删除Group + */ + @RequestMapping(value = "group/delete/{groupId}", method = RequestMethod.GET) + public String deleteGroup(@PathVariable("groupId") String groupId, + RedirectAttributes redirectAttributes) { + if (ArrayUtils.contains(INNER_GROUPS, groupId)) { + redirectAttributes.addFlashAttribute("errorMsg", "组[" + groupId + "]属于Demo固定数据不可删除!"); + return "redirect:/management/identity/group/list"; + } + + identityService.deleteGroup(groupId); + redirectAttributes.addFlashAttribute("message", "成功删除组[" + groupId + "]"); + return "redirect:/management/identity/group/list"; + } + + /** + * 用户列表 + * + * @param request + * @return + */ + @RequestMapping("user/list") + public ModelAndView userList(HttpServletRequest request) { + ModelAndView mav = new ModelAndView("management/user-list"); + + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + + UserQuery userQuery = identityService.createUserQuery(); + List userList = userQuery.listPage(pageParams[0], pageParams[1]); + + // 查询每个人的分组,这样的写法比较耗费性能、时间,仅供读者参考 + Map> groupOfUserMap = new HashMap>(); + for (User user : userList) { + List groupList = identityService.createGroupQuery().groupMember(user.getId()).list(); + groupOfUserMap.put(user.getId(), groupList); + } + + page.setResult(userList); + page.setTotalCount(userQuery.count()); + mav.addObject("page", page); + mav.addObject("groupOfUserMap", groupOfUserMap); + + // 读取所有组 + List groups = identityService.createGroupQuery().list(); + mav.addObject("allGroup", groups); + + return mav; + } + + /** + * 保存User + * + * @param redirectAttributes + * @return + */ + @RequestMapping(value = "user/save", method = RequestMethod.POST) + public String saveUser(@RequestParam("userId") String userId, + @RequestParam("firstName") String firstName, + @RequestParam("lastName") String lastName, + @RequestParam(value = "password", required = false) String password, + @RequestParam(value = "email", required = false) String email, + RedirectAttributes redirectAttributes) { + User user = identityService.createUserQuery().userId(userId).singleResult(); + if (user == null) { + user = identityService.newUser(userId); + } + user.setFirstName(firstName); + user.setLastName(lastName); + user.setEmail(email); + if (StringUtils.isNotBlank(password)) { + user.setPassword(password); + } + identityService.saveUser(user); + redirectAttributes.addFlashAttribute("message", "成功添加用户[" + firstName + " " + lastName + "]"); + return "redirect:/management/identity/user/list"; + } + + /** + * 删除User + */ + @RequestMapping(value = "user/delete/{userId}", method = RequestMethod.GET) + public String deleteUser(@PathVariable("userId") String userId, + RedirectAttributes redirectAttributes) { + if (ArrayUtils.contains(INNER_USERS, userId)) { + redirectAttributes.addFlashAttribute("errorMsg", "用户[" + userId + "]属于Demo固定数据不可删除!"); + return "redirect:/management/identity/user/list"; + } + + identityService.deleteUser(userId); + redirectAttributes.addFlashAttribute("message", "成功删除用户[" + userId + "]"); + return "redirect:/management/identity/user/list"; + } + + /** + * 为用户设置所属组 + * @param userId + * @param groupIds + * @return + */ + @RequestMapping(value = "group/set", method = RequestMethod.POST) + public String groupForUser(@RequestParam("userId") String userId, @RequestParam("group") String[] groupIds, + RedirectAttributes redirectAttributes) { + + if (ArrayUtils.contains(INNER_USERS, userId)) { + redirectAttributes.addFlashAttribute("errorMsg", "用户[" + userId + "]属于Demo固定数据不可更改!"); + return "redirect:/management/identity/user/list"; + } + + List groupInDb = identityService.createGroupQuery().groupMember(userId).list(); + for (Group group : groupInDb) { + identityService.deleteMembership(userId, group.getId()); + } + for (String group : groupIds) { + identityService.createMembership(userId, group); + } + return "redirect:/management/identity/user/list"; + } + +} diff --git a/src/main/java/me/kafeitu/demo/activiti/web/management/JobController.java b/src/main/java/me/kafeitu/demo/activiti/web/management/JobController.java new file mode 100644 index 0000000000..ba8013d7f6 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/web/management/JobController.java @@ -0,0 +1,123 @@ +package me.kafeitu.demo.activiti.web.management; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.servlet.http.HttpServletRequest; + +import me.kafeitu.demo.activiti.util.Page; +import me.kafeitu.demo.activiti.util.PageUtil; +import org.activiti.engine.ManagementService; +import org.activiti.engine.runtime.Job; +import org.activiti.engine.runtime.JobQuery; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.servlet.ModelAndView; + +/** + * 作业控制器 + * User: henryyan + */ +@Controller +@RequestMapping(value = "/management/job") +public class JobController { + + @Autowired + ManagementService managementService; + + public static Map JOB_TYPES = new HashMap(); + + static { + JOB_TYPES.put("activate-processdefinition", "激活流程定义"); + JOB_TYPES.put("timer-intermediate-transition", "中间定时"); + JOB_TYPES.put("timer-transition", "边界定时"); + JOB_TYPES.put("timer-start-event", "定时启动流程"); + JOB_TYPES.put("suspend-processdefinition", "挂起流程定义"); + JOB_TYPES.put("async-continuation", "异步锁"); + } + + /** + * Job列表 + * + * @return + */ + @RequestMapping(value = "list") + public ModelAndView jobList(HttpServletRequest request) { + ModelAndView mav = new ModelAndView("management/job-list"); + JobQuery jobQuery = managementService.createJobQuery(); + + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + List jobList = jobQuery.listPage(pageParams[0], pageParams[1]); + + page.setResult(jobList); + page.setTotalCount(jobQuery.count()); + + Map exceptionStacktraces = new HashMap(); + for (Job job : jobList) { + if (StringUtils.isNotBlank(job.getExceptionMessage())) { + exceptionStacktraces.put(job.getId(), managementService.getJobExceptionStacktrace(job.getId())); + } + } + + mav.addObject("page", page); + mav.addObject("exceptionStacktraces", exceptionStacktraces); + mav.addObject("JOB_TYPES", JOB_TYPES); + + return mav; + } + + /** + * 删除作业 + * + * @param jobId + * @return + */ + @RequestMapping(value = "delete/{jobId}") + public String deleteJob(@PathVariable("jobId") String jobId) { + managementService.deleteJob(jobId); + return "redirect:/management/job/list"; + } + + /** + * 执行作业 + * + * @param jobId + * @return + */ + @RequestMapping(value = "execute/{jobId}") + public String executeJob(@PathVariable("jobId") String jobId) { + managementService.executeJob(jobId); + return "redirect:/management/job/list"; + } + + /** + * 更改作业可重试次数 + * + * @param jobId + * @return + */ + @RequestMapping(value = "change/retries/{jobId}") + public String changeRetries(@PathVariable("jobId") String jobId, @RequestParam("retries") int retries) { + managementService.setJobRetries(jobId, retries); + return "redirect:/management/job/list"; + } + + /** + * 读取作业异常信息 + * + * @param jobId + * @return + */ + @RequestMapping(value = "stacktrace/{jobId}") + @ResponseBody + public String getJobExceptionStacktrace(@PathVariable("jobId") String jobId) { + return managementService.getJobExceptionStacktrace(jobId); + } + +} diff --git a/src/main/java/me/kafeitu/demo/activiti/web/management/ProcessEngineInfoController.java b/src/main/java/me/kafeitu/demo/activiti/web/management/ProcessEngineInfoController.java new file mode 100644 index 0000000000..d5855fe5de --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/web/management/ProcessEngineInfoController.java @@ -0,0 +1,41 @@ +package me.kafeitu.demo.activiti.web.management; + +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.activiti.engine.ManagementService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.servlet.ModelAndView; + +/** + * 作业控制器 + * User: henryyan + */ +@Controller +@RequestMapping(value = "/management/engine") +public class ProcessEngineInfoController { + + @Autowired + ManagementService managementService; + + @RequestMapping("") + public ModelAndView info() { + ModelAndView mav = new ModelAndView("management/engine-info"); + Map engineProperties = managementService.getProperties(); + mav.addObject("engineProperties", engineProperties); + + Map systemProperties = new HashMap(); + Properties systemProperties11 = System.getProperties(); + Set objects = systemProperties11.keySet(); + for (Object object : objects) { + systemProperties.put(object.toString(), systemProperties11.get(object.toString()).toString()); + } + mav.addObject("systemProperties", systemProperties); + return mav; + } + +} diff --git a/src/main/java/me/kafeitu/demo/activiti/web/oa/leave/LeaveController.java b/src/main/java/me/kafeitu/demo/activiti/web/oa/leave/LeaveController.java index fcb175f0b5..1dc3bcdaf9 100644 --- a/src/main/java/me/kafeitu/demo/activiti/web/oa/leave/LeaveController.java +++ b/src/main/java/me/kafeitu/demo/activiti/web/oa/leave/LeaveController.java @@ -1,17 +1,12 @@ package me.kafeitu.demo.activiti.web.oa.leave; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.servlet.http.HttpSession; - import me.kafeitu.demo.activiti.entity.oa.Leave; import me.kafeitu.demo.activiti.service.oa.leave.LeaveManager; import me.kafeitu.demo.activiti.service.oa.leave.LeaveWorkflowService; +import me.kafeitu.demo.activiti.util.Page; +import me.kafeitu.demo.activiti.util.PageUtil; import me.kafeitu.demo.activiti.util.UserUtil; import me.kafeitu.demo.activiti.util.Variable; - import org.activiti.engine.ActivitiException; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; @@ -30,6 +25,11 @@ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.util.HashMap; +import java.util.Map; + /** * 请假控制器,包含保存、启动流程 * @@ -39,147 +39,161 @@ @RequestMapping(value = "/oa/leave") public class LeaveController { - private Logger logger = LoggerFactory.getLogger(getClass()); - - @Autowired - protected LeaveManager leaveManager; - - @Autowired - protected LeaveWorkflowService workflowService; - - @Autowired - protected RuntimeService runtimeService; - - @Autowired - protected TaskService taskService; - - @RequestMapping(value = { "apply", "" }) - public String createForm(Model model) { - model.addAttribute("leave", new Leave()); - return "/oa/leave/leaveApply"; - } - - /** - * 启动请假流程 - * @param leave - */ - @RequestMapping(value = "start", method = RequestMethod.POST) - public String startWorkflow(Leave leave, RedirectAttributes redirectAttributes, HttpSession session) { - try { - User user = UserUtil.getUserFromSession(session); - // 用户未登陆不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等 - if (user == null || StringUtils.isBlank(user.getId())) { - return "redirect:/login?timeout=true"; - } - leave.setUserId(user.getId()); - Map variables = new HashMap(); - ProcessInstance processInstance = workflowService.startWorkflow(leave, variables); - redirectAttributes.addFlashAttribute("message", "流程已启动,流程ID:" + processInstance.getId()); - } catch (ActivitiException e) { - if (e.getMessage().indexOf("no processes deployed with key") != -1) { - logger.warn("没有部署流程!", e); - redirectAttributes.addFlashAttribute("error", "没有部署流程,请在[工作流]->[流程管理]页面点击<重新部署流程>"); - } else { - logger.error("启动请假流程失败:", e); - redirectAttributes.addFlashAttribute("error", "系统内部错误!"); - } - } catch (Exception e) { - logger.error("启动请假流程失败:", e); - redirectAttributes.addFlashAttribute("error", "系统内部错误!"); - } - return "redirect:/oa/leave/apply"; - } - - /** - * 任务列表 - * @param leave - */ - @RequestMapping(value = "list/task") - public ModelAndView taskList(HttpSession session) { - ModelAndView mav = new ModelAndView("/oa/leave/taskList"); - String userId = UserUtil.getUserFromSession(session).getId(); - List results = workflowService.findTodoTasks(userId); - mav.addObject("leaves", results); - return mav; - } - - /** - * 读取运行中的流程实例 - * @return - */ - @RequestMapping(value = "list/running") - public ModelAndView runningList() { - ModelAndView mav = new ModelAndView("/oa/leave/running"); - List results = workflowService.findRunningProcessInstaces(); - mav.addObject("leaves", results); - return mav; - } - - /** - * 读取运行中的流程实例 - * @return - */ - @RequestMapping(value = "list/finished") - public ModelAndView finishedList() { - ModelAndView mav = new ModelAndView("/oa/leave/finished"); - List results = workflowService.findFinishedProcessInstaces(); - mav.addObject("leaves", results); - return mav; - } - - /** - * 签收任务 - */ - @RequestMapping(value = "task/claim/{id}") - public String claim(@PathVariable("id") String taskId, HttpSession session, RedirectAttributes redirectAttributes) { - String userId = UserUtil.getUserFromSession(session).getId(); - taskService.claim(taskId, userId); - redirectAttributes.addFlashAttribute("message", "任务已签收"); - return "redirect:/oa/leave/list/task"; - } - - /** - * 读取详细数据 - * @param id - * @return - */ - @RequestMapping(value = "detail/{id}") - @ResponseBody - public Leave getLeave(@PathVariable("id") Long id) { - Leave leave = leaveManager.getLeave(id); - return leave; - } - - /** - * 读取详细数据 - * @param id - * @return - */ - @RequestMapping(value = "detail-with-vars/{id}/{taskId}") - @ResponseBody - public Leave getLeaveWithVars(@PathVariable("id") Long id, @PathVariable("taskId") String taskId) { - Leave leave = leaveManager.getLeave(id); - Map variables = taskService.getVariables(taskId); - leave.setVariables(variables); - return leave; - } - - /** - * 完成任务 - * @param id - * @return - */ - @RequestMapping(value = "complete/{id}", method = { RequestMethod.POST, RequestMethod.GET }) - @ResponseBody - public String complete(@PathVariable("id") String taskId, Variable var) { - try { - Map variables = var.getVariableMap(); - taskService.complete(taskId, variables); - return "success"; - } catch (Exception e) { - logger.error("error on complete task {}, variables={}", new Object[] { taskId, var.getVariableMap(), e }); - return "error"; - } - } + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + protected LeaveManager leaveManager; + + @Autowired + protected LeaveWorkflowService workflowService; + + @Autowired + protected RuntimeService runtimeService; + + @Autowired + protected TaskService taskService; + + @RequestMapping(value = {"apply", ""}) + public String createForm(Model model) { + model.addAttribute("leave", new Leave()); + return "/oa/leave/leaveApply"; + } + + /** + * 启动请假流程 + * + * @param leave + */ + @RequestMapping(value = "start", method = RequestMethod.POST) + public String startWorkflow(Leave leave, RedirectAttributes redirectAttributes, HttpSession session) { + try { + User user = UserUtil.getUserFromSession(session); + // 用户未登录不能操作,实际应用使用权限框架实现,例如Spring Security、Shiro等 + if (user == null || StringUtils.isBlank(user.getId())) { + return "redirect:/login?timeout=true"; + } + leave.setUserId(user.getId()); + Map variables = new HashMap(); + ProcessInstance processInstance = workflowService.startWorkflow(leave, variables); + redirectAttributes.addFlashAttribute("message", "流程已启动,流程ID:" + processInstance.getId()); + } catch (ActivitiException e) { + if (e.getMessage().indexOf("no processes deployed with key") != -1) { + logger.warn("没有部署流程!", e); + redirectAttributes.addFlashAttribute("error", "没有部署流程,请在[工作流]->[流程管理]页面点击<重新部署流程>"); + } else { + logger.error("启动请假流程失败:", e); + redirectAttributes.addFlashAttribute("error", "系统内部错误!"); + } + } catch (Exception e) { + logger.error("启动请假流程失败:", e); + redirectAttributes.addFlashAttribute("error", "系统内部错误!"); + } + return "redirect:/oa/leave/apply"; + } + + /** + * 任务列表 + * + * @param leave + */ + @RequestMapping(value = "list/task") + public ModelAndView taskList(HttpSession session, HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/oa/leave/taskList"); + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + + String userId = UserUtil.getUserFromSession(session).getId(); + workflowService.findTodoTasks(userId, page, pageParams); + mav.addObject("page", page); + return mav; + } + + /** + * 读取运行中的流程实例 + * + * @return + */ + @RequestMapping(value = "list/running") + public ModelAndView runningList(HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/oa/leave/running"); + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + workflowService.findRunningProcessInstaces(page, pageParams); + mav.addObject("page", page); + return mav; + } + + /** + * 读取运行中的流程实例 + * + * @return + */ + @RequestMapping(value = "list/finished") + public ModelAndView finishedList(HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/oa/leave/finished"); + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + workflowService.findFinishedProcessInstaces(page, pageParams); + mav.addObject("page", page); + return mav; + } + + /** + * 签收任务 + */ + @RequestMapping(value = "task/claim/{id}") + public String claim(@PathVariable("id") String taskId, HttpSession session, RedirectAttributes redirectAttributes) { + String userId = UserUtil.getUserFromSession(session).getId(); + taskService.claim(taskId, userId); + redirectAttributes.addFlashAttribute("message", "任务已签收"); + return "redirect:/oa/leave/list/task"; + } + + /** + * 读取详细数据 + * + * @param id + * @return + */ + @RequestMapping(value = "detail/{id}") + @ResponseBody + public Leave getLeave(@PathVariable("id") Long id) { + Leave leave = leaveManager.getLeave(id); + return leave; + } + + /** + * 读取详细数据 + * + * @param id + * @return + */ + @RequestMapping(value = "detail-with-vars/{id}/{taskId}") + @ResponseBody + public Leave getLeaveWithVars(@PathVariable("id") Long id, @PathVariable("taskId") String taskId) { + Leave leave = leaveManager.getLeave(id); + Map variables = taskService.getVariables(taskId); + leave.setVariables(variables); + return leave; + } + + /** + * 完成任务 + * + * @param id + * @return + */ + @RequestMapping(value = "complete/{id}", method = {RequestMethod.POST, RequestMethod.GET}) + @ResponseBody + public String complete(@PathVariable("id") String taskId, Variable var) { + try { + Map variables = var.getVariableMap(); + taskService.complete(taskId, variables); + return "success"; + } catch (Exception e) { + logger.error("error on complete task {}, variables={}", new Object[]{taskId, var.getVariableMap(), e}); + return "error"; + } + } } diff --git a/src/main/java/me/kafeitu/demo/activiti/web/workflow/ActivitiController.java b/src/main/java/me/kafeitu/demo/activiti/web/workflow/ActivitiController.java index 08ffb3aad5..a59bdf25a1 100644 --- a/src/main/java/me/kafeitu/demo/activiti/web/workflow/ActivitiController.java +++ b/src/main/java/me/kafeitu/demo/activiti/web/workflow/ActivitiController.java @@ -1,33 +1,57 @@ package me.kafeitu.demo.activiti.web.workflow; +import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.zip.ZipInputStream; - +import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import me.kafeitu.demo.activiti.cmd.JumpActivityCmd; import me.kafeitu.demo.activiti.service.activiti.WorkflowProcessDefinitionService; import me.kafeitu.demo.activiti.service.activiti.WorkflowTraceService; +import me.kafeitu.demo.activiti.util.Page; +import me.kafeitu.demo.activiti.util.PageUtil; import me.kafeitu.demo.activiti.util.UserUtil; - -import org.activiti.engine.ActivitiException; +import me.kafeitu.demo.activiti.util.WorkflowUtils; +import org.activiti.bpmn.converter.BpmnXMLConverter; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.editor.constants.ModelDataJsonConstants; +import org.activiti.editor.language.json.converter.BpmnJsonConverter; +import org.activiti.engine.ManagementService; +import org.activiti.engine.ProcessEngineConfiguration; import org.activiti.engine.RepositoryService; import org.activiti.engine.RuntimeService; import org.activiti.engine.TaskService; import org.activiti.engine.identity.User; +import org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.activiti.engine.impl.context.Context; +import org.activiti.engine.impl.interceptor.Command; import org.activiti.engine.repository.Deployment; +import org.activiti.engine.repository.Model; import org.activiti.engine.repository.ProcessDefinition; +import org.activiti.engine.repository.ProcessDefinitionQuery; import org.activiti.engine.runtime.ProcessInstance; import org.activiti.engine.task.Task; +import org.activiti.image.ProcessDiagramGenerator; +import org.activiti.spring.ProcessEngineFactoryBean; import org.apache.commons.io.FilenameUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -39,270 +63,378 @@ /** * 流程管理控制器 - * + * * @author HenryYan */ @Controller @RequestMapping(value = "/workflow") public class ActivitiController { - protected Logger logger = LoggerFactory.getLogger(getClass()); + protected Logger logger = LoggerFactory.getLogger(getClass()); + + protected WorkflowProcessDefinitionService workflowProcessDefinitionService; + + protected RepositoryService repositoryService; - protected WorkflowProcessDefinitionService workflowProcessDefinitionService; + protected RuntimeService runtimeService; - protected RepositoryService repositoryService; + protected TaskService taskService; - protected RuntimeService runtimeService; + protected WorkflowTraceService traceService; - protected TaskService taskService; + @Autowired + ManagementService managementService; - protected WorkflowTraceService traceService; + protected static Map PROCESS_DEFINITION_CACHE = new HashMap(); - protected static Map PROCESS_DEFINITION_CACHE = new HashMap(); + @Autowired + ProcessEngineFactoryBean processEngine; - /** - * 流程定义列表 - * - * @return - */ - @RequestMapping(value = "/process-list") - public ModelAndView processList() { - ModelAndView mav = new ModelAndView("workflow/process-list"); + @Autowired + ProcessEngineConfiguration processEngineConfiguration; + + /** + * 流程定义列表 + * + * @return + */ + @RequestMapping(value = "/process-list") + public ModelAndView processList(HttpServletRequest request) { + ModelAndView mav = new ModelAndView("workflow/process-list"); /* * 保存两个对象,一个是ProcessDefinition(流程定义),一个是Deployment(流程部署) */ - List objects = new ArrayList(); + List objects = new ArrayList(); + + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); - List processDefinitionList = repositoryService.createProcessDefinitionQuery().list(); - for (ProcessDefinition processDefinition : processDefinitionList) { - String deploymentId = processDefinition.getDeploymentId(); - Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult(); - objects.add(new Object[] { processDefinition, deployment }); + ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery().orderByDeploymentId().desc(); + List processDefinitionList = processDefinitionQuery.listPage(pageParams[0], pageParams[1]); + for (ProcessDefinition processDefinition : processDefinitionList) { + String deploymentId = processDefinition.getDeploymentId(); + Deployment deployment = repositoryService.createDeploymentQuery().deploymentId(deploymentId).singleResult(); + objects.add(new Object[]{processDefinition, deployment}); + } + + page.setTotalCount(processDefinitionQuery.count()); + page.setResult(objects); + mav.addObject("page", page); + + return mav; } - mav.addObject("objects", objects); - - return mav; - } - - /** - * 部署全部流程 - * - * @return - * @throws Exception - */ - @RequestMapping(value = "/redeploy/all") - public String redeployAll() throws Exception { - workflowProcessDefinitionService.deployAllFromClasspath(); - return "redirect:/workflow/process-list"; - } - - /** - * 读取资源,通过部署ID - * - * @param deploymentId - * 流程部署的ID - * @param resourceName - * 资源名称(foo.xml|foo.png) - * @param response - * @throws Exception - */ - @RequestMapping(value = "/resource/deployment") - public void loadByDeployment(@RequestParam("deploymentId") String deploymentId, @RequestParam("resourceName") String resourceName, - HttpServletResponse response) throws Exception { - InputStream resourceAsStream = repositoryService.getResourceAsStream(deploymentId, resourceName); - byte[] b = new byte[1024]; - int len = -1; - while ((len = resourceAsStream.read(b, 0, 1024)) != -1) { - response.getOutputStream().write(b, 0, len); + /** + * 部署全部流程 + * + * @return + * @throws Exception + */ + @RequestMapping(value = "/redeploy/all") + public String redeployAll(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir) throws Exception { + workflowProcessDefinitionService.deployAllFromClasspath(exportDir); + return "redirect:/workflow/process-list"; } - } - - /** - * 读取资源,通过流程ID - * - * @param resourceType - * 资源类型(xml|image) - * @param processInstanceId - * 流程实例ID - * @param response - * @throws Exception - */ - @RequestMapping(value = "/resource/process-instance") - public void loadByProcessInstance(@RequestParam("type") String resourceType, @RequestParam("pid") String processInstanceId, HttpServletResponse response) - throws Exception { - InputStream resourceAsStream = null; - ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); - ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()) - .singleResult(); - - String resourceName = ""; - if (resourceType.equals("image")) { - resourceName = processDefinition.getDiagramResourceName(); - } else if (resourceType.equals("xml")) { - resourceName = processDefinition.getResourceName(); + + /** + * 读取资源,通过部署ID + * + * @param processDefinitionId 流程定义 + * @param resourceType 资源类型(xml|image) + * @throws Exception + */ + @RequestMapping(value = "/resource/read") + public void loadByDeployment(@RequestParam("processDefinitionId") String processDefinitionId, @RequestParam("resourceType") String resourceType, + HttpServletResponse response) throws Exception { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult(); + String resourceName = ""; + if (resourceType.equals("image")) { + resourceName = processDefinition.getDiagramResourceName(); + } else if (resourceType.equals("xml")) { + resourceName = processDefinition.getResourceName(); + } + InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName); + byte[] b = new byte[1024]; + int len = -1; + while ((len = resourceAsStream.read(b, 0, 1024)) != -1) { + response.getOutputStream().write(b, 0, len); + } + } + + /** + * 读取资源,通过流程ID + * + * @param resourceType 资源类型(xml|image) + * @param processInstanceId 流程实例ID + * @param response + * @throws Exception + */ + @RequestMapping(value = "/resource/process-instance") + public void loadByProcessInstance(@RequestParam("type") String resourceType, @RequestParam("pid") String processInstanceId, HttpServletResponse response) + throws Exception { + InputStream resourceAsStream = null; + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processInstance.getProcessDefinitionId()) + .singleResult(); + + String resourceName = ""; + if (resourceType.equals("image")) { + resourceName = processDefinition.getDiagramResourceName(); + } else if (resourceType.equals("xml")) { + resourceName = processDefinition.getResourceName(); + } + resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName); + byte[] b = new byte[1024]; + int len = -1; + while ((len = resourceAsStream.read(b, 0, 1024)) != -1) { + response.getOutputStream().write(b, 0, len); + } } - resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), resourceName); - byte[] b = new byte[1024]; - int len = -1; - while ((len = resourceAsStream.read(b, 0, 1024)) != -1) { - response.getOutputStream().write(b, 0, len); + + /** + * 删除部署的流程,级联删除流程实例 + * + * @param deploymentId 流程部署ID + */ + @RequestMapping(value = "/process/delete") + public String delete(@RequestParam("deploymentId") String deploymentId) { + repositoryService.deleteDeployment(deploymentId, true); + return "redirect:/workflow/process-list"; } - } - - /** - * 删除部署的流程,级联删除流程实例 - * - * @param deploymentId - * 流程部署ID - */ - @RequestMapping(value = "/process/delete") - public String delete(@RequestParam("deploymentId") String deploymentId) { - repositoryService.deleteDeployment(deploymentId, true); - return "redirect:/workflow/process-list"; - } - - /** - * 输出跟踪流程信息 - * - * @param processInstanceId - * @return - * @throws Exception - */ - @RequestMapping(value = "/process/trace") - @ResponseBody - public List> traceProcess(@RequestParam("pid") String processInstanceId) throws Exception { - List> activityInfos = traceService.traceProcess(processInstanceId); - return activityInfos; - } - - @RequestMapping(value = "/deploy") - public String deploy(@RequestParam(value = "file", required = false) MultipartFile file) { - - String fileName = file.getOriginalFilename(); - - try { - InputStream fileInputStream = file.getInputStream(); - - String extension = FilenameUtils.getExtension(fileName); - if (extension.equals("zip") || extension.equals("bar")) { - ZipInputStream zip = new ZipInputStream(fileInputStream); - repositoryService.createDeployment().addZipInputStream(zip).deploy(); - } else if (extension.equals("png")) { - repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy(); - } else if (fileName.indexOf("bpmn20.xml") != -1) { - repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy(); - } else if (extension.equals("bpmn")) { - /* - * bpmn扩展名特殊处理,转换为bpmn20.xml - */ - String baseName = FilenameUtils.getBaseName(fileName); - repositoryService.createDeployment().addInputStream(baseName + ".bpmn20.xml", fileInputStream).deploy(); - } else { - throw new ActivitiException("no support file type of " + extension); - } - } catch (Exception e) { - logger.error("error on deploy process, because of file input stream", e); + + /** + * 输出跟踪流程信息 + * + * @param processInstanceId + * @return + * @throws Exception + */ + @RequestMapping(value = "/process/trace") + @ResponseBody + public List> traceProcess(@RequestParam("pid") String processInstanceId) throws Exception { + List> activityInfos = traceService.traceProcess(processInstanceId); + return activityInfos; } - return "redirect:/workflow/process-list"; - } - - /** - * 待办任务--Portlet - */ - @RequestMapping(value = "/task/todo/list") - @ResponseBody - public List> todoList(HttpSession session) throws Exception { - User user = UserUtil.getUserFromSession(session); - List> result = new ArrayList>(); - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm"); - - // 已经签收的任务 - List todoList = taskService.createTaskQuery().taskAssignee(user.getId()).active().list(); - for (Task task : todoList) { - String processDefinitionId = task.getProcessDefinitionId(); - ProcessDefinition processDefinition = getProcessDefinition(processDefinitionId); - - Map singleTask = packageTaskInfo(sdf, task, processDefinition); - singleTask.put("status", "todo"); - result.add(singleTask); + /** + * 读取带跟踪的图片 + */ + @RequestMapping(value = "/process/trace/auto/{executionId}") + public void readResource(@PathVariable("executionId") String executionId, HttpServletResponse response) + throws Exception { + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(executionId).singleResult(); + BpmnModel bpmnModel = repositoryService.getBpmnModel(processInstance.getProcessDefinitionId()); + List activeActivityIds = runtimeService.getActiveActivityIds(executionId); + // 不使用spring请使用下面的两行代码 +// ProcessEngineImpl defaultProcessEngine = (ProcessEngineImpl) ProcessEngines.getDefaultProcessEngine(); +// Context.setProcessEngineConfiguration(defaultProcessEngine.getProcessEngineConfiguration()); + + // 使用spring注入引擎请使用下面的这行代码 + processEngineConfiguration = processEngine.getProcessEngineConfiguration(); + Context.setProcessEngineConfiguration((ProcessEngineConfigurationImpl) processEngineConfiguration); + + ProcessDiagramGenerator diagramGenerator = processEngineConfiguration.getProcessDiagramGenerator(); + InputStream imageStream = diagramGenerator.generateDiagram(bpmnModel, "png", activeActivityIds); + + // 输出资源内容到相应对象 + byte[] b = new byte[1024]; + int len; + while ((len = imageStream.read(b, 0, 1024)) != -1) { + response.getOutputStream().write(b, 0, len); + } } - // 等待签收的任务 - List toClaimList = taskService.createTaskQuery().taskCandidateUser(user.getId()).active().list(); - for (Task task : toClaimList) { - String processDefinitionId = task.getProcessDefinitionId(); - ProcessDefinition processDefinition = getProcessDefinition(processDefinitionId); + @RequestMapping(value = "/deploy") + public String deploy(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir, @RequestParam(value = "file", required = false) MultipartFile file) { + + String fileName = file.getOriginalFilename(); - Map singleTask = packageTaskInfo(sdf, task, processDefinition); - singleTask.put("status", "claim"); - result.add(singleTask); + try { + InputStream fileInputStream = file.getInputStream(); + Deployment deployment = null; + + String extension = FilenameUtils.getExtension(fileName); + if (extension.equals("zip") || extension.equals("bar")) { + ZipInputStream zip = new ZipInputStream(fileInputStream); + deployment = repositoryService.createDeployment().addZipInputStream(zip).deploy(); + } else { + deployment = repositoryService.createDeployment().addInputStream(fileName, fileInputStream).deploy(); + } + + List list = repositoryService.createProcessDefinitionQuery().deploymentId(deployment.getId()).list(); + + for (ProcessDefinition processDefinition : list) { + WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir); + } + + } catch (Exception e) { + logger.error("error on deploy process, because of file input stream", e); + } + + return "redirect:/workflow/process-list"; } - return result; - } - - private Map packageTaskInfo(SimpleDateFormat sdf, Task task, ProcessDefinition processDefinition) { - Map singleTask = new HashMap(); - singleTask.put("id", task.getId()); - singleTask.put("name", task.getName()); - singleTask.put("createTime", sdf.format(task.getCreateTime())); - singleTask.put("pdname", processDefinition.getName()); - singleTask.put("pdversion", processDefinition.getVersion()); - singleTask.put("pid", task.getProcessInstanceId()); - return singleTask; - } - - private ProcessDefinition getProcessDefinition(String processDefinitionId) { - ProcessDefinition processDefinition = PROCESS_DEFINITION_CACHE.get(processDefinitionId); - if (processDefinition == null) { - processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult(); - PROCESS_DEFINITION_CACHE.put(processDefinitionId, processDefinition); + @RequestMapping(value = "/process/convert-to-model/{processDefinitionId}") + public String convertToModel(@PathVariable("processDefinitionId") String processDefinitionId) + throws UnsupportedEncodingException, XMLStreamException { + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery() + .processDefinitionId(processDefinitionId).singleResult(); + InputStream bpmnStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(), + processDefinition.getResourceName()); + XMLInputFactory xif = XMLInputFactory.newInstance(); + InputStreamReader in = new InputStreamReader(bpmnStream, "UTF-8"); + XMLStreamReader xtr = xif.createXMLStreamReader(in); + BpmnModel bpmnModel = new BpmnXMLConverter().convertToBpmnModel(xtr); + + BpmnJsonConverter converter = new BpmnJsonConverter(); + com.fasterxml.jackson.databind.node.ObjectNode modelNode = converter.convertToJson(bpmnModel); + Model modelData = repositoryService.newModel(); + modelData.setKey(processDefinition.getKey()); + modelData.setName(processDefinition.getResourceName()); + modelData.setCategory(processDefinition.getDeploymentId()); + + ObjectNode modelObjectNode = new ObjectMapper().createObjectNode(); + modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, processDefinition.getName()); + modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1); + modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, processDefinition.getDescription()); + modelData.setMetaInfo(modelObjectNode.toString()); + + repositoryService.saveModel(modelData); + + repositoryService.addModelEditorSource(modelData.getId(), modelNode.toString().getBytes("utf-8")); + + return "redirect:/workflow/model/list"; } - return processDefinition; - } - - /** - * 挂起、激活流程实例 - */ - @RequestMapping(value = "processdefinition/update/{state}/{processDefinitionId}") - public String updateState(@PathVariable("state") String state, @PathVariable("processDefinitionId") String processDefinitionId, - RedirectAttributes redirectAttributes) { - if (state.equals("active")) { - redirectAttributes.addFlashAttribute("message", "已激活ID为[" + processDefinitionId + "]的流程定义。"); - repositoryService.activateProcessDefinitionById(processDefinitionId, true, null); - } else if (state.equals("suspend")) { - repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null); - redirectAttributes.addFlashAttribute("message", "已挂起ID为[" + processDefinitionId + "]的流程定义。"); + + /** + * 待办任务--Portlet + */ + @RequestMapping(value = "/task/todo/list") + @ResponseBody + public List> todoList(HttpSession session) throws Exception { + User user = UserUtil.getUserFromSession(session); + List> result = new ArrayList>(); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm"); + + // 已经签收的任务 + List todoList = taskService.createTaskQuery().taskAssignee(user.getId()).active().list(); + for (Task task : todoList) { + String processDefinitionId = task.getProcessDefinitionId(); + ProcessDefinition processDefinition = getProcessDefinition(processDefinitionId); + + Map singleTask = packageTaskInfo(sdf, task, processDefinition); + singleTask.put("status", "todo"); + result.add(singleTask); + } + + // 等待签收的任务 + List toClaimList = taskService.createTaskQuery().taskCandidateUser(user.getId()).active().list(); + for (Task task : toClaimList) { + String processDefinitionId = task.getProcessDefinitionId(); + ProcessDefinition processDefinition = getProcessDefinition(processDefinitionId); + + Map singleTask = packageTaskInfo(sdf, task, processDefinition); + singleTask.put("status", "claim"); + result.add(singleTask); + } + + return result; } - return "redirect:/workflow/process-list"; - } - - @Autowired - public void setWorkflowProcessDefinitionService(WorkflowProcessDefinitionService workflowProcessDefinitionService) { - this.workflowProcessDefinitionService = workflowProcessDefinitionService; - } - - @Autowired - public void setRepositoryService(RepositoryService repositoryService) { - this.repositoryService = repositoryService; - } - - @Autowired - public void setRuntimeService(RuntimeService runtimeService) { - this.runtimeService = runtimeService; - } - - @Autowired - public void setTraceService(WorkflowTraceService traceService) { - this.traceService = traceService; - } - - @Autowired - public void setTaskService(TaskService taskService) { - this.taskService = taskService; - } - -} + + private Map packageTaskInfo(SimpleDateFormat sdf, Task task, ProcessDefinition processDefinition) { + Map singleTask = new HashMap(); + singleTask.put("id", task.getId()); + singleTask.put("name", task.getName()); + singleTask.put("createTime", sdf.format(task.getCreateTime())); + singleTask.put("pdname", processDefinition.getName()); + singleTask.put("pdversion", processDefinition.getVersion()); + singleTask.put("pid", task.getProcessInstanceId()); + return singleTask; + } + + private ProcessDefinition getProcessDefinition(String processDefinitionId) { + ProcessDefinition processDefinition = PROCESS_DEFINITION_CACHE.get(processDefinitionId); + if (processDefinition == null) { + processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(processDefinitionId).singleResult(); + PROCESS_DEFINITION_CACHE.put(processDefinitionId, processDefinition); + } + return processDefinition; + } + + /** + * 挂起、激活流程实例 + */ + @RequestMapping(value = "processdefinition/update/{state}/{processDefinitionId}") + public String updateState(@PathVariable("state") String state, @PathVariable("processDefinitionId") String processDefinitionId, + RedirectAttributes redirectAttributes) { + if (state.equals("active")) { + redirectAttributes.addFlashAttribute("message", "已激活ID为[" + processDefinitionId + "]的流程定义。"); + repositoryService.activateProcessDefinitionById(processDefinitionId, true, null); + } else if (state.equals("suspend")) { + repositoryService.suspendProcessDefinitionById(processDefinitionId, true, null); + redirectAttributes.addFlashAttribute("message", "已挂起ID为[" + processDefinitionId + "]的流程定义。"); + } + return "redirect:/workflow/process-list"; + } + + /** + * 导出图片文件到硬盘 + * + * @return + */ + @RequestMapping(value = "export/diagrams") + @ResponseBody + public List exportDiagrams(@Value("#{APP_PROPERTIES['export.diagram.path']}") String exportDir) throws IOException { + List files = new ArrayList(); + List list = repositoryService.createProcessDefinitionQuery().list(); + + for (ProcessDefinition processDefinition : list) { + files.add(WorkflowUtils.exportDiagramToFile(repositoryService, processDefinition, exportDir)); + } + + return files; + } + + @RequestMapping(value = "activity/jump") + @ResponseBody + public boolean jump(@RequestParam("executionId") String executionId, + @RequestParam("activityId") String activityId) { + Command cmd = new JumpActivityCmd(executionId, activityId); + managementService.executeCommand(cmd); + return true; + } + + @RequestMapping(value = "bpmn/model/{processDefinitionId}") + @ResponseBody + public BpmnModel queryBpmnModel(@PathVariable("processDefinitionId") String processDefinitionId) { + BpmnModel bpmnModel = repositoryService.getBpmnModel(processDefinitionId); + return bpmnModel; + } + + @Autowired + public void setWorkflowProcessDefinitionService(WorkflowProcessDefinitionService workflowProcessDefinitionService) { + this.workflowProcessDefinitionService = workflowProcessDefinitionService; + } + + @Autowired + public void setRepositoryService(RepositoryService repositoryService) { + this.repositoryService = repositoryService; + } + + @Autowired + public void setRuntimeService(RuntimeService runtimeService) { + this.runtimeService = runtimeService; + } + + @Autowired + public void setTraceService(WorkflowTraceService traceService) { + this.traceService = traceService; + } + + @Autowired + public void setTaskService(TaskService taskService) { + this.taskService = taskService; + } + +} \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/web/workflow/ModelController.java b/src/main/java/me/kafeitu/demo/activiti/web/workflow/ModelController.java new file mode 100644 index 0000000000..2a8880baa2 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/web/workflow/ModelController.java @@ -0,0 +1,173 @@ +package me.kafeitu.demo.activiti.web.workflow; + +import java.io.ByteArrayInputStream; +import java.util.List; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.node.ObjectNode; +import org.activiti.bpmn.converter.BpmnXMLConverter; +import org.activiti.bpmn.model.BpmnModel; +import org.activiti.editor.constants.ModelDataJsonConstants; +import org.activiti.editor.language.json.converter.BpmnJsonConverter; +import org.activiti.engine.RepositoryService; +import org.activiti.engine.repository.Deployment; +import org.activiti.engine.repository.Model; +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +/** + * 流程模型控制器 + * + * @author henryyan + */ +@Controller +@RequestMapping(value = "/workflow/model") +public class ModelController { + + protected Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + RepositoryService repositoryService; + + /** + * 模型列表 + */ + @RequestMapping(value = "list") + public ModelAndView modelList() { + ModelAndView mav = new ModelAndView("workflow/model-list"); + List list = repositoryService.createModelQuery().list(); + mav.addObject("list", list); + return mav; + } + + /** + * 创建模型 + */ + @RequestMapping(value = "create", method = RequestMethod.POST) + public void create(@RequestParam("name") String name, @RequestParam("key") String key, @RequestParam("description") String description, + HttpServletRequest request, HttpServletResponse response) { + try { + ObjectMapper objectMapper = new ObjectMapper(); + ObjectNode editorNode = objectMapper.createObjectNode(); + editorNode.put("id", "canvas"); + editorNode.put("resourceId", "canvas"); + ObjectNode stencilSetNode = objectMapper.createObjectNode(); + stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#"); + editorNode.put("stencilset", stencilSetNode); + Model modelData = repositoryService.newModel(); + + ObjectNode modelObjectNode = objectMapper.createObjectNode(); + modelObjectNode.put(ModelDataJsonConstants.MODEL_NAME, name); + modelObjectNode.put(ModelDataJsonConstants.MODEL_REVISION, 1); + description = StringUtils.defaultString(description); + modelObjectNode.put(ModelDataJsonConstants.MODEL_DESCRIPTION, description); + modelData.setMetaInfo(modelObjectNode.toString()); + modelData.setName(name); + modelData.setKey(StringUtils.defaultString(key)); + + repositoryService.saveModel(modelData); + repositoryService.addModelEditorSource(modelData.getId(), editorNode.toString().getBytes("utf-8")); + + response.sendRedirect(request.getContextPath() + "/modeler.html?modelId=" + modelData.getId()); + } catch (Exception e) { + logger.error("创建模型失败:", e); + } + } + + /** + * 根据Model部署流程 + */ + @RequestMapping(value = "deploy/{modelId}") + public String deploy(@PathVariable("modelId") String modelId, RedirectAttributes redirectAttributes) { + try { + Model modelData = repositoryService.getModel(modelId); + ObjectNode modelNode = (ObjectNode) new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId())); + byte[] bpmnBytes = null; + + BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode); + bpmnBytes = new BpmnXMLConverter().convertToXML(model); + + String processName = modelData.getName() + ".bpmn20.xml"; + Deployment deployment = repositoryService.createDeployment().name(modelData.getName()).addString(processName, new String(bpmnBytes)).deploy(); + redirectAttributes.addFlashAttribute("message", "部署成功,部署ID=" + deployment.getId()); + } catch (Exception e) { + logger.error("根据模型部署流程失败:modelId={}", modelId, e); + } + return "redirect:/workflow/model/list"; + } + + /** + * 导出model对象为指定类型 + * + * @param modelId 模型ID + * @param type 导出文件类型(bpmn\json) + */ + @RequestMapping(value = "export/{modelId}/{type}") + public void export(@PathVariable("modelId") String modelId, + @PathVariable("type") String type, + HttpServletResponse response) { + try { + Model modelData = repositoryService.getModel(modelId); + BpmnJsonConverter jsonConverter = new BpmnJsonConverter(); + byte[] modelEditorSource = repositoryService.getModelEditorSource(modelData.getId()); + + JsonNode editorNode = new ObjectMapper().readTree(modelEditorSource); + BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode); + + // 处理异常 + if (bpmnModel.getMainProcess() == null) { + response.setStatus(HttpStatus.UNPROCESSABLE_ENTITY.value()); + response.getOutputStream().println("no main process, can't export for type: " + type); + response.flushBuffer(); + return; + } + + String filename = ""; + byte[] exportBytes = null; + + String mainProcessId = bpmnModel.getMainProcess().getId(); + + if (type.equals("bpmn")) { + + BpmnXMLConverter xmlConverter = new BpmnXMLConverter(); + exportBytes = xmlConverter.convertToXML(bpmnModel); + + filename = mainProcessId + ".bpmn20.xml"; + } else if (type.equals("json")) { + + exportBytes = modelEditorSource; + filename = mainProcessId + ".json"; + + } + + ByteArrayInputStream in = new ByteArrayInputStream(exportBytes); + IOUtils.copy(in, response.getOutputStream()); + + response.setHeader("Content-Disposition", "attachment; filename=" + filename); + response.flushBuffer(); + } catch (Exception e) { + logger.error("导出model的xml文件失败:modelId={}, type={}", modelId, type, e); + } + } + + @RequestMapping(value = "delete/{modelId}") + public String delete(@PathVariable("modelId") String modelId) { + repositoryService.deleteModel(modelId); + return "redirect:/workflow/model/list"; + } + +} diff --git a/src/main/java/me/kafeitu/demo/activiti/web/workflow/ProcessInstanceController.java b/src/main/java/me/kafeitu/demo/activiti/web/workflow/ProcessInstanceController.java index ce0da59a6c..b125752517 100644 --- a/src/main/java/me/kafeitu/demo/activiti/web/workflow/ProcessInstanceController.java +++ b/src/main/java/me/kafeitu/demo/activiti/web/workflow/ProcessInstanceController.java @@ -1,11 +1,10 @@ package me.kafeitu.demo.activiti.web.workflow; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; - +import me.kafeitu.demo.activiti.util.Page; +import me.kafeitu.demo.activiti.util.PageUtil; import org.activiti.engine.RuntimeService; import org.activiti.engine.runtime.ProcessInstance; +import org.activiti.engine.runtime.ProcessInstanceQuery; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; @@ -14,33 +13,43 @@ import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.support.RedirectAttributes; +import javax.servlet.http.HttpServletRequest; +import java.util.List; + @Controller @RequestMapping(value = "/workflow/processinstance") public class ProcessInstanceController { - @Autowired - private RuntimeService runtimeService; + @Autowired + private RuntimeService runtimeService; - @RequestMapping(value = "running") - public ModelAndView running(Model model, HttpServletRequest request) { - ModelAndView mav = new ModelAndView("/workflow/running-manage"); - List list = runtimeService.createProcessInstanceQuery().list(); - mav.addObject("list", list); - return mav; - } + @RequestMapping(value = "running") + public ModelAndView running(Model model, HttpServletRequest request) { + ModelAndView mav = new ModelAndView("/workflow/running-manage"); + Page page = new Page(PageUtil.PAGE_SIZE); + int[] pageParams = PageUtil.init(page, request); + + ProcessInstanceQuery processInstanceQuery = runtimeService.createProcessInstanceQuery(); + List list = processInstanceQuery.listPage(pageParams[0], pageParams[1]); + page.setResult(list); + page.setTotalCount(processInstanceQuery.count()); + mav.addObject("page", page); + return mav; + } - /** - * 挂起、激活流程实例 - */ - @RequestMapping(value = "update/{state}/{processInstanceId}") - public String updateState(@PathVariable("state") String state, @PathVariable("processInstanceId") String processInstanceId, RedirectAttributes redirectAttributes) { - if (state.equals("active")) { - redirectAttributes.addFlashAttribute("message", "已激活ID为[" + processInstanceId + "]的流程实例。"); - runtimeService.activateProcessInstanceById(processInstanceId); - } else if (state.equals("suspend")) { - runtimeService.suspendProcessInstanceById(processInstanceId); - redirectAttributes.addFlashAttribute("message", "已挂起ID为[" + processInstanceId + "]的流程实例。"); + /** + * 挂起、激活流程实例 + */ + @RequestMapping(value = "update/{state}/{processInstanceId}") + public String updateState(@PathVariable("state") String state, @PathVariable("processInstanceId") String processInstanceId, + RedirectAttributes redirectAttributes) { + if (state.equals("active")) { + redirectAttributes.addFlashAttribute("message", "已激活ID为[" + processInstanceId + "]的流程实例。"); + runtimeService.activateProcessInstanceById(processInstanceId); + } else if (state.equals("suspend")) { + runtimeService.suspendProcessInstanceById(processInstanceId); + redirectAttributes.addFlashAttribute("message", "已挂起ID为[" + processInstanceId + "]的流程实例。"); + } + return "redirect:/workflow/processinstance/running"; } - return "redirect:/workflow/processinstance/running"; - } } diff --git a/src/main/java/me/kafeitu/demo/activiti/webservice/LeaveWebService.java b/src/main/java/me/kafeitu/demo/activiti/webservice/LeaveWebService.java new file mode 100644 index 0000000000..f8daab76fd --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/webservice/LeaveWebService.java @@ -0,0 +1,24 @@ +package me.kafeitu.demo.activiti.webservice; + +import javax.jws.WebParam; +import javax.jws.WebResult; +import javax.jws.WebService; +import javax.xml.datatype.XMLGregorianCalendar; + +/** + * 请假WebService接口 + * @author: Henry Yan + */ +@WebService +public interface LeaveWebService { + + /** + * 是否需要总经理审批 + * @param startDate 请假开始时间 + * @param endDate 请假结束时间 + * @return true|false + */ + @WebResult(name="needed") + boolean generalManagerAudit(@WebParam(name = "startDate") XMLGregorianCalendar startDate, @WebParam(name = "endDate") XMLGregorianCalendar endDate) throws Exception; + +} diff --git a/src/main/java/me/kafeitu/demo/activiti/webservice/LeaveWebServiceImpl.java b/src/main/java/me/kafeitu/demo/activiti/webservice/LeaveWebServiceImpl.java new file mode 100644 index 0000000000..7f558523a8 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/webservice/LeaveWebServiceImpl.java @@ -0,0 +1,39 @@ +package me.kafeitu.demo.activiti.webservice; + +import java.util.Date; +import javax.jws.WebService; +import javax.xml.datatype.XMLGregorianCalendar; + +import jodd.datetime.JDateTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 请假WebService接口简单实现 + * @author: Henry Yan + */ +@WebService(endpointInterface = "me.kafeitu.demo.activiti.webservice.LeaveWebService", serviceName = "LeaveWebService") +public class LeaveWebServiceImpl implements LeaveWebService { + + protected Logger logger = LoggerFactory.getLogger(getClass()); + + /** + * 计算开始日期与结束日期相差天数 + * @throws java.text.ParseException + */ + public int daysBetween(Date startDate, Date endDate) { + JDateTime joddStartDate = new JDateTime(startDate); + JDateTime joddEndDate = new JDateTime(endDate); + int result = joddStartDate.daysBetween(joddEndDate); + logger.info("日期比较:startDate={}, endDate={}, 相差 {} 天。", startDate, endDate, result); + return result; + } + + @Override + public boolean generalManagerAudit(XMLGregorianCalendar startDate, XMLGregorianCalendar endDate) throws Exception { + Date innerStartDate = startDate.toGregorianCalendar().getTime(); + Date innerEndDate = endDate.toGregorianCalendar().getTime(); + int days = daysBetween(innerStartDate, innerEndDate); + return days > 3 ? true : false; + } +} \ No newline at end of file diff --git a/src/main/java/me/kafeitu/demo/activiti/webservice/LeaveWebserviceUtil.java b/src/main/java/me/kafeitu/demo/activiti/webservice/LeaveWebserviceUtil.java new file mode 100644 index 0000000000..3b905d0b03 --- /dev/null +++ b/src/main/java/me/kafeitu/demo/activiti/webservice/LeaveWebserviceUtil.java @@ -0,0 +1,53 @@ +package me.kafeitu.demo.activiti.webservice; + +import javax.xml.ws.Endpoint; + +import org.apache.cxf.endpoint.Server; + +/** + * 请假Webservice工具 + * @author: Henry Yan + */ +public class LeaveWebserviceUtil { + + public static final String WEBSERVICE_URL = "http://localhost:8088/leave"; + public static final String WEBSERVICE_WSDL_URL = WEBSERVICE_URL + "?wsdl"; + public static final String WEBSERVICE_URI = "http://webservice.kafeitu.me/"; + + private static Server server = null; + + /** + * 发布Webservice + */ + public static void startServer() { + if (server != null) { + System.out.println("WebService服务正在运行。。。"); + return; + } + LeaveWebService leaveWebService = new LeaveWebServiceImpl(); + /*JaxWsServerFactoryBean svrFactory = new JaxWsServerFactoryBean(); + svrFactory.setServiceClass(LeaveWebService.class); + svrFactory.setAddress(WEBSERVICE_URL); + svrFactory.setServiceBean(leaveWebService); + svrFactory.getInInterceptors().add(new LoggingInInterceptor()); + svrFactory.getOutInterceptors().add(new LoggingOutInterceptor()); + server = svrFactory.create(); + server.start();*/ + Endpoint.publish(WEBSERVICE_URL, leaveWebService); + System.out.println("请假Webservice已发布:" + WEBSERVICE_URL + "?wsdl"); + } + + /** + * 停止Webservice服务 + */ + public static void stopServer() { + if (server != null) { + server.destroy(); + } + } + + public static void main(String[] args) { + startServer(); + } + +} diff --git a/src/main/java/me/kafeitu/modules/test/data/DataFixtures.java b/src/main/java/me/kafeitu/modules/test/data/DataFixtures.java index 29318fd4ec..205a830ad0 100644 --- a/src/main/java/me/kafeitu/modules/test/data/DataFixtures.java +++ b/src/main/java/me/kafeitu/modules/test/data/DataFixtures.java @@ -5,13 +5,6 @@ */ package me.kafeitu.modules.test.data; -import java.io.IOException; -import java.io.InputStream; -import java.sql.Connection; -import java.sql.SQLException; - -import javax.sql.DataSource; - import org.apache.commons.lang3.StringUtils; import org.dbunit.DatabaseUnitException; import org.dbunit.database.DatabaseConnection; @@ -27,81 +20,87 @@ import org.springframework.core.io.DefaultResourceLoader; import org.springframework.core.io.ResourceLoader; +import javax.sql.DataSource; +import java.io.IOException; +import java.io.InputStream; +import java.sql.Connection; +import java.sql.SQLException; + /** * 基于DBUnit初始化数据到数据库的工具类. */ public class DataFixtures { - private static Logger logger = LoggerFactory.getLogger(DataFixtures.class); - private static ResourceLoader resourceLoader = new DefaultResourceLoader(); + private static Logger logger = LoggerFactory.getLogger(DataFixtures.class); + private static ResourceLoader resourceLoader = new DefaultResourceLoader(); - /** - * 先删除数据库中所有表的数据, 再插入XML文件中的数据到数据库. - * - * @param xmlFilePaths 符合Spring Resource路径格式的文件路径列表. - */ - public static void reloadData(DataSource dataSource, String... xmlFilePaths) throws Exception { - execute(DatabaseOperation.CLEAN_INSERT, dataSource, xmlFilePaths); - } + /** + * 先删除数据库中所有表的数据, 再插入XML文件中的数据到数据库. + * + * @param xmlFilePaths 符合Spring Resource路径格式的文件路径列表. + */ + public static void reloadData(DataSource dataSource, String... xmlFilePaths) throws Exception { + execute(DatabaseOperation.CLEAN_INSERT, dataSource, xmlFilePaths); + } - /** - * 插入XML文件中的数据到数据库. - * - * @param xmlFilePaths 符合Spring Resource路径格式的文件路径列表. - */ - public static void loadData(DataSource dataSource, String... xmlFilePaths) throws Exception { - execute(DatabaseOperation.INSERT, dataSource, xmlFilePaths); - } + /** + * 插入XML文件中的数据到数据库. + * + * @param xmlFilePaths 符合Spring Resource路径格式的文件路径列表. + */ + public static void loadData(DataSource dataSource, String... xmlFilePaths) throws Exception { + execute(DatabaseOperation.INSERT, dataSource, xmlFilePaths); + } - /** - * 在数据库中删除XML文件中涉及的表的数据. - * - * @param xmlFilePaths 符合Spring Resource路径格式的文件路径列表. - */ - public static void deleteData(DataSource dataSource, String... xmlFilePaths) throws Exception { - execute(DatabaseOperation.DELETE_ALL, dataSource, xmlFilePaths); - } + /** + * 在数据库中删除XML文件中涉及的表的数据. + * + * @param xmlFilePaths 符合Spring Resource路径格式的文件路径列表. + */ + public static void deleteData(DataSource dataSource, String... xmlFilePaths) throws Exception { + execute(DatabaseOperation.DELETE_ALL, dataSource, xmlFilePaths); + } - /** - * 对XML文件中的数据在数据库中执行Operation. - * - * @param xmlFilePaths 符合Spring Resource路径格式的文件列表. - */ - private static void execute(DatabaseOperation operation, DataSource dataSource, String... xmlFilePaths) - throws DatabaseUnitException, SQLException { - IDatabaseConnection connection = getConnection(dataSource); - try { - for (String xmlPath : xmlFilePaths) { - try { - InputStream input = resourceLoader.getResource(xmlPath).getInputStream(); - IDataSet dataSet = new FlatXmlDataSetBuilder().setColumnSensing(true).build(input); - operation.execute(connection, dataSet); - } catch (IOException e) { - logger.warn(xmlPath + " file not found", e); - } - } - } finally { - if (connection != null) { - connection.close(); - } - } - } + /** + * 对XML文件中的数据在数据库中执行Operation. + * + * @param xmlFilePaths 符合Spring Resource路径格式的文件列表. + */ + private static void execute(DatabaseOperation operation, DataSource dataSource, String... xmlFilePaths) + throws DatabaseUnitException, SQLException { + IDatabaseConnection connection = getConnection(dataSource); + try { + for (String xmlPath : xmlFilePaths) { + try { + InputStream input = resourceLoader.getResource(xmlPath).getInputStream(); + IDataSet dataSet = new FlatXmlDataSetBuilder().setColumnSensing(true).build(input); + operation.execute(connection, dataSet); + } catch (IOException e) { + logger.warn(xmlPath + " file not found", e); + } + } + } finally { + if (connection != null) { + connection.close(); + } + } + } - /** - * 从DataSource中取得新的Connection(不会参与原有事务),并根据url转换为相应数据库的Connection. - */ - protected static IDatabaseConnection getConnection(DataSource dataSource) throws DatabaseUnitException, - SQLException { - Connection connection = dataSource.getConnection(); - String jdbcUrl = connection.getMetaData().getURL(); - if (StringUtils.contains(jdbcUrl, ":h2:")) { - return new H2Connection(connection, null); - } else if (StringUtils.contains(jdbcUrl, ":mysql:")) { - return new MySqlConnection(connection, null); - } else if (StringUtils.contains(jdbcUrl, ":oracle:")) { - return new OracleConnection(connection, null); - } else { - return new DatabaseConnection(connection); - } - } + /** + * 从DataSource中取得新的Connection(不会参与原有事务),并根据url转换为相应数据库的Connection. + */ + protected static IDatabaseConnection getConnection(DataSource dataSource) throws DatabaseUnitException, + SQLException { + Connection connection = dataSource.getConnection(); + String jdbcUrl = connection.getMetaData().getURL(); + if (StringUtils.contains(jdbcUrl, ":h2:")) { + return new H2Connection(connection, null); + } else if (StringUtils.contains(jdbcUrl, ":mysql:")) { + return new MySqlConnection(connection, null); + } else if (StringUtils.contains(jdbcUrl, ":oracle:")) { + return new OracleConnection(connection, null); + } else { + return new DatabaseConnection(connection); + } + } } diff --git a/src/main/java/me/kafeitu/modules/test/data/DataInitializer.java b/src/main/java/me/kafeitu/modules/test/data/DataInitializer.java index 5d896aaa41..0264a817f4 100644 --- a/src/main/java/me/kafeitu/modules/test/data/DataInitializer.java +++ b/src/main/java/me/kafeitu/modules/test/data/DataInitializer.java @@ -1,30 +1,30 @@ package me.kafeitu.modules.test.data; -import javax.sql.DataSource; - import org.springframework.beans.factory.InitializingBean; +import javax.sql.DataSource; + /** * 测试数据初始化工具 - * + * * @author calvin */ public class DataInitializer implements InitializingBean { - private DataSource dataSource; + private DataSource dataSource; - private String dataFile; + private String dataFile; - public void setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - } + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } - public void setDataFile(String dataFile) { - this.dataFile = dataFile; - } + public void setDataFile(String dataFile) { + this.dataFile = dataFile; + } - @Override - public void afterPropertiesSet() throws Exception { - DataFixtures.reloadData(dataSource, dataFile); - } + @Override + public void afterPropertiesSet() throws Exception { + DataFixtures.reloadData(dataSource, dataFile); + } } diff --git a/src/main/java/me/kafeitu/modules/test/spring/SpringTransactionalTestCase.java b/src/main/java/me/kafeitu/modules/test/spring/SpringTransactionalTestCase.java index e8ad6016c3..843e5493c4 100644 --- a/src/main/java/me/kafeitu/modules/test/spring/SpringTransactionalTestCase.java +++ b/src/main/java/me/kafeitu/modules/test/spring/SpringTransactionalTestCase.java @@ -5,30 +5,30 @@ */ package me.kafeitu.modules.test.spring; -import javax.sql.DataSource; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests; +import javax.sql.DataSource; + /** * Spring的支持数据库访问, 事务控制和依赖注入的JUnit4 集成测试基类. * 相比Spring原基类名字更短并保存了dataSource变量. - * + *

* 子类需要定义applicationContext文件的位置, 如: - * @ContextConfiguration(locations = { "/applicationContext-test.xml" }) - * + * * @author calvin + * @ContextConfiguration(locations = { "/applicationContext-test.xml" }) */ @ActiveProfiles("test") public abstract class SpringTransactionalTestCase extends AbstractTransactionalJUnit4SpringContextTests { - protected DataSource dataSource; + protected DataSource dataSource; - @Override - @Autowired - public void setDataSource(DataSource dataSource) { - super.setDataSource(dataSource); - this.dataSource = dataSource; - } + @Override + @Autowired + public void setDataSource(DataSource dataSource) { + super.setDataSource(dataSource); + this.dataSource = dataSource; + } } diff --git a/src/main/java/me/kafeitu/modules/utils/PropertiesLoader.java b/src/main/java/me/kafeitu/modules/utils/PropertiesLoader.java index 2d18fd1396..8f89967002 100644 --- a/src/main/java/me/kafeitu/modules/utils/PropertiesLoader.java +++ b/src/main/java/me/kafeitu/modules/utils/PropertiesLoader.java @@ -2,16 +2,11 @@ * Copyright (c) 2005-2011 springside.org.cn * * Licensed under the Apache License, Version 2.0 (the "License"); - * + * * $Id: PropertiesLoader.java 1690 2012-02-22 13:42:00Z calvinxiu $ */ package me.kafeitu.modules.utils; -import java.io.IOException; -import java.io.InputStream; -import java.util.NoSuchElementException; -import java.util.Properties; - import org.apache.commons.io.IOUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -19,138 +14,143 @@ import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import java.io.IOException; +import java.io.InputStream; +import java.util.NoSuchElementException; +import java.util.Properties; + /** * Properties文件载入工具类. 可载入多个properties文件, 相同的属性在最后载入的文件中的值将会覆盖之前的值. - * + *

* 本类有两种使用方法: - * 1. - * + * 1. + * * @author calvin */ public class PropertiesLoader { - private static Logger logger = LoggerFactory.getLogger(PropertiesLoader.class); - - private static ResourceLoader resourceLoader = new DefaultResourceLoader(); - - private final Properties properties; - - public PropertiesLoader(String... resourcesPaths) { - properties = loadProperties(resourcesPaths); - } - - public Properties getProperties() { - return properties; - } - - /** - * 取出Property,但以System的Property优先. - */ - private String getValue(String key) { - String systemProperty = System.getProperty(key); - if (systemProperty != null) { - return systemProperty; - } - return properties.getProperty(key); - } - - /** - * 取出String类型的Property,但以System的Property优先,如果都為Null则抛出异常. - */ - public String getProperty(String key) { - String value = getValue(key); - if (value == null) { - throw new NoSuchElementException(); - } - return value; - } - - /** - * 取出String类型的Property,但以System的Property优先.如果都為Null則返回Default值. - */ - public String getProperty(String key, String defaultValue) { - String value = getValue(key); - return value != null ? value : defaultValue; - } - - /** - * 取出Integer类型的Property,但以System的Property优先.如果都為Null或内容错误则抛出异常. - */ - public Integer getInteger(String key) { - String value = getValue(key); - if (value == null) { - throw new NoSuchElementException(); - } - return Integer.valueOf(value); - } - - /** - * 取出Integer类型的Property,但以System的Property优先.如果都為Null則返回Default值,如果内容错误则抛出异常 - */ - public Integer getInteger(String key, Integer defaultValue) { - String value = getValue(key); - return value != null ? Integer.valueOf(value) : defaultValue; - } - - /** - * 取出Double类型的Property,但以System的Property优先.如果都為Null或内容错误则抛出异常. - */ - public Double getDouble(String key) { - String value = getValue(key); - if (value == null) { - throw new NoSuchElementException(); - } - return Double.valueOf(value); - } - - /** - * 取出Double类型的Property,但以System的Property优先.如果都為Null則返回Default值,如果内容错误则抛出异常 - */ - public Double getDouble(String key, Integer defaultValue) { - String value = getValue(key); - return value != null ? Double.valueOf(value) : defaultValue; - } - - /** - * 取出Boolean类型的Property,但以System的Property优先.如果都為Null抛出异常,如果内容不是true/false则返回false. - */ - public Boolean getBoolean(String key) { - String value = getValue(key); - if (value == null) { - throw new NoSuchElementException(); - } - return Boolean.valueOf(value); - } - - /** - * 取出Boolean类型的Property,但以System的Property优先.如果都為Null則返回Default值,如果内容不为true/false则返回false. - */ - public Boolean getBoolean(String key, boolean defaultValue) { - String value = getValue(key); - return value != null ? Boolean.valueOf(value) : defaultValue; - } - - /** - * 载入多个文件, 文件路径使用Spring Resource格式. - */ - private Properties loadProperties(String... resourcesPaths) { - Properties props = new Properties(); - - for (String location : resourcesPaths) { - - logger.debug("Loading properties file from:" + location); - - InputStream is = null; - try { - Resource resource = resourceLoader.getResource(location); - is = resource.getInputStream(); - props.load(is); - } catch (IOException ex) { - logger.info("Could not load properties from path:" + location + ", " + ex.getMessage()); - } finally { - IOUtils.closeQuietly(is); - } - } - return props; - } + private static Logger logger = LoggerFactory.getLogger(PropertiesLoader.class); + + private static ResourceLoader resourceLoader = new DefaultResourceLoader(); + + private final Properties properties; + + public PropertiesLoader(String... resourcesPaths) { + properties = loadProperties(resourcesPaths); + } + + public Properties getProperties() { + return properties; + } + + /** + * 取出Property,但以System的Property优先. + */ + private String getValue(String key) { + String systemProperty = System.getProperty(key); + if (systemProperty != null) { + return systemProperty; + } + return properties.getProperty(key); + } + + /** + * 取出String类型的Property,但以System的Property优先,如果都為Null则抛出异常. + */ + public String getProperty(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return value; + } + + /** + * 取出String类型的Property,但以System的Property优先.如果都為Null則返回Default值. + */ + public String getProperty(String key, String defaultValue) { + String value = getValue(key); + return value != null ? value : defaultValue; + } + + /** + * 取出Integer类型的Property,但以System的Property优先.如果都為Null或内容错误则抛出异常. + */ + public Integer getInteger(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return Integer.valueOf(value); + } + + /** + * 取出Integer类型的Property,但以System的Property优先.如果都為Null則返回Default值,如果内容错误则抛出异常 + */ + public Integer getInteger(String key, Integer defaultValue) { + String value = getValue(key); + return value != null ? Integer.valueOf(value) : defaultValue; + } + + /** + * 取出Double类型的Property,但以System的Property优先.如果都為Null或内容错误则抛出异常. + */ + public Double getDouble(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return Double.valueOf(value); + } + + /** + * 取出Double类型的Property,但以System的Property优先.如果都為Null則返回Default值,如果内容错误则抛出异常 + */ + public Double getDouble(String key, Integer defaultValue) { + String value = getValue(key); + return value != null ? Double.valueOf(value) : defaultValue; + } + + /** + * 取出Boolean类型的Property,但以System的Property优先.如果都為Null抛出异常,如果内容不是true/false则返回false. + */ + public Boolean getBoolean(String key) { + String value = getValue(key); + if (value == null) { + throw new NoSuchElementException(); + } + return Boolean.valueOf(value); + } + + /** + * 取出Boolean类型的Property,但以System的Property优先.如果都為Null則返回Default值,如果内容不为true/false则返回false. + */ + public Boolean getBoolean(String key, boolean defaultValue) { + String value = getValue(key); + return value != null ? Boolean.valueOf(value) : defaultValue; + } + + /** + * 载入多个文件, 文件路径使用Spring Resource格式. + */ + private Properties loadProperties(String... resourcesPaths) { + Properties props = new Properties(); + + for (String location : resourcesPaths) { + + logger.debug("Loading properties file from:" + location); + + InputStream is = null; + try { + Resource resource = resourceLoader.getResource(location); + is = resource.getInputStream(); + props.load(is); + } catch (IOException ex) { + logger.info("Could not load properties from path:" + location + ", " + ex.getMessage()); + } finally { + IOUtils.closeQuietly(is); + } + } + return props; + } } diff --git a/src/main/java/me/kafeitu/modules/web/servlet/PropertiesServlet.java b/src/main/java/me/kafeitu/modules/web/servlet/PropertiesServlet.java index 4028a32761..b0a5373efb 100644 --- a/src/main/java/me/kafeitu/modules/web/servlet/PropertiesServlet.java +++ b/src/main/java/me/kafeitu/modules/web/servlet/PropertiesServlet.java @@ -1,17 +1,26 @@ package me.kafeitu.modules.web.servlet; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.util.Enumeration; +import java.util.Properties; import java.util.Set; - import javax.servlet.Servlet; import javax.servlet.ServletConfig; +import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import me.kafeitu.demo.activiti.util.LinkedProperties; import me.kafeitu.demo.activiti.util.PropertyFileUtil; - +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,68 +30,301 @@ */ public class PropertiesServlet extends HttpServlet { - private static final long serialVersionUID = 1L; - - protected Logger logger = LoggerFactory.getLogger(getClass()); - - /** - * @see HttpServlet#HttpServlet() - */ - public PropertiesServlet() { - super(); - } - - /** - * @see Servlet#init(ServletConfig) - */ - public void init(ServletConfig config) throws ServletException { - try { - PropertyFileUtil.init(); - logger.info("++++ 初始化[classpath下面的属性配置文件]完成 ++++"); - } catch (IOException e) { - logger.error("初始化classpath下的属性文件失败", e); - } - } - - @Override - protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - doPost(req, resp); - } - - @Override - protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - String action = StringUtils.defaultString(req.getParameter("action")); - resp.setContentType("text/plain;charset=UTF-8"); - if ("reload".equals(action)) { // 重载 - try { - PropertyFileUtil.init(); - logger.info("++++ 重新初始化[classpath下面的属性配置文件]完成 ++++,{IP={}}", req.getRemoteAddr()); - resp.getWriter().print("属性文件重载成功!
"); - writeProperties(resp); - } catch (IOException e) { - logger.error("重新初始化classpath下的属性文件失败", e); - } - } else if ("getprop".equals(action)) { // 获取属性 - String key = StringUtils.defaultString(req.getParameter("key")); - resp.getWriter().print(key + "=" + PropertyFileUtil.get(key)); - } else if ("list".equals(action)) { // 获取属性 - writeProperties(resp); - } - } - - /** - * 输出属性以及值列表到页面 - * @param resp - * @throws IOException - */ - protected void writeProperties(HttpServletResponse resp) throws IOException { - Set keys = PropertyFileUtil.getKeys(); - StringBuilder sb = new StringBuilder(); - for (Object key : keys) { - sb.append(key + "=" + PropertyFileUtil.get(key.toString()) + "
"); - } - resp.setContentType("text/html"); - resp.getWriter().print("" + sb.toString() + ""); - } - -} + private static final long serialVersionUID = 1L; + protected Logger logger = LoggerFactory.getLogger(getClass()); + + /** + * @see HttpServlet#HttpServlet() + */ + public PropertiesServlet() { + super(); + } + + /** + * @see Servlet#init(ServletConfig) + */ + public void init(ServletConfig config) throws ServletException { + try { + String profile = config.getInitParameter("profile"); + if (StringUtils.isNotBlank(profile)) { + logger.info("启用特定Profile=" + profile); + PropertyFileUtil.init(profile); + } else { + PropertyFileUtil.init(); + logger.info("启用默认Profile"); + } + setParameterToServerContext(config.getServletContext()); + logger.info("++++ 初始化[classpath下面的属性配置文件]完成 ++++"); + } catch (IOException e) { + logger.error("初始化classpath下的属性文件失败", e); + } + } + + /** + * 绑定参数到ServletContext + * + * @param servletContext + */ + private void setParameterToServerContext(ServletContext servletContext) { + servletContext.setAttribute("prop", PropertyFileUtil.getKeyValueMap()); + } + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + doPost(req, resp); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + String action = StringUtils.defaultString(req.getParameter("action")); + resp.setContentType("text/plain;charset=UTF-8"); + if ("reload".equals(action)) { // 重载 + try { + String profile = StringUtils.defaultString(req.getParameter("profile"), PropertyFileUtil.getProfile()); + if (StringUtils.isNotBlank(profile)) { + logger.info("重载配置,使用特定Profile=" + profile); + } + PropertyFileUtil.init(profile); + + setParameterToServerContext(req.getSession().getServletContext()); + logger.info("++++ 已完成属性配置文件重载任务 ++++,{IP={}}", req.getRemoteAddr()); + resp.getWriter().print("属性文件重载成功!
"); + writeProperties(resp); + } catch (IOException e) { + logger.error("重载属性文件失败", e); + } + } else if ("getprop".equals(action)) { // 获取属性 + String key = StringUtils.defaultString(req.getParameter("key")); + resp.getWriter().print(ObjectUtils.toString(PropertyFileUtil.get(key))); + } else if ("list-all".equals(action)) { // 获取全部属性 + writeProperties(resp); + } else if ("list-split".equals(action)) { // 分文件获取全部属性 + writePropertiesBySplit(resp); + } else if ("files".equals(action)) { + writeActiveFiles(resp); + } else if ("save".equals(action)) { + String parameterName = StringUtils.defaultString(req.getParameter("parameterName")); + String parameterValue = StringUtils.defaultString(req.getParameter("parameterValue")); + saveParameter(parameterName, parameterValue, resp); + } else if ("delete".equals(action)) { + String parameterKey = StringUtils.defaultString(req.getParameter("parameterKey")); + deleteParameter(parameterKey, resp); + } else { + writeNav(req, resp); + } + } + + /** + * 新增/修改本地配置文件的属性 + * + * @param parameterName + * @param parameterValue + * @param resp + * @throws ServletException + * @throws IOException + */ + public void saveParameter(String parameterName, String parameterValue, HttpServletResponse resp) throws ServletException, IOException { + InputStream inputStream = null; + InputStream cInputStream = null; + OutputStream out = null; + try { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + inputStream = loader.getResourceAsStream("application-files.properties"); + Properties props = new Properties(); + props.load(inputStream); + String cFilePath = props.getProperty("C").split(":")[1]; + + File file = new File(cFilePath); + if (file.getParentFile() != null && !file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + if (!file.exists()) { + file.createNewFile(); + } + Properties cProps = new Properties(); + cInputStream = new FileInputStream(file); + cProps.load(cInputStream); + out = new FileOutputStream(cFilePath); + cProps.setProperty(parameterName, parameterValue); + cProps.store(out, "Update:'" + parameterName + "' value:" + parameterValue); + out.flush(); + out.close(); + cInputStream.close(); + inputStream.close(); + PropertyFileUtil.init(); + resp.getWriter().print("success"); + } catch (Exception e) { + logger.error("新增/修改属性:", e); + resp.getWriter().print("error:" + e.getMessage()); + } finally { + if (null != inputStream) { + inputStream.close(); + } + if (null != cInputStream) { + cInputStream.close(); + } + if (null != out) { + out.close(); + } + } + } + + /** + * 删除本地配置文件的属性 + * + * @param parameterKey + * @param resp + * @throws ServletException + * @throws IOException + */ + public void deleteParameter(String parameterKey, HttpServletResponse resp) throws ServletException, IOException { + InputStream inputStream = null; + InputStream cInputStream = null; + OutputStream out = null; + try { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + inputStream = loader.getResourceAsStream("application-files.properties"); + Properties props = new Properties(); + props.load(inputStream); + String cFilePath = props.getProperty("C").split(":")[1]; + + File file = new File(cFilePath); + if (file.getParentFile() != null && !file.getParentFile().exists()) { + file.getParentFile().mkdirs(); + } + if (!file.exists()) { + file.createNewFile(); + } + Properties cProps = new Properties(); + cInputStream = new FileInputStream(file); + cProps.load(cInputStream); + cProps.remove(parameterKey); + out = new FileOutputStream(cFilePath); + cProps.store(out, "delete:'" + parameterKey); + out.flush(); + out.close(); + cInputStream.close(); + inputStream.close(); + PropertyFileUtil.init(); + resp.getWriter().print("success"); + } catch (Exception e) { + logger.error("删除本地配置文件的属性:", e); + resp.getWriter().print("error:" + e.getMessage()); + } finally { + if (null != inputStream) { + inputStream.close(); + } + if (null != cInputStream) { + cInputStream.close(); + } + if (null != out) { + out.close(); + } + } + } + + /** + * 输出属性以及值列表到页面 + * + * @param resp + * @throws IOException + */ + protected void writeProperties(HttpServletResponse resp) throws IOException { + Set keys = PropertyFileUtil.getKeys(); + StringBuilder sb = new StringBuilder(); + for (String key : keys) { + sb.append(key + "=" + PropertyFileUtil.get(key) + "
"); + } + resp.setContentType("text/html"); + resp.getWriter().print("" + sb.toString() + ""); + } + + /** + * 分文件获取全部属性 + * + * @param resp + * @throws ServletException + * @throws IOException + */ + protected void writePropertiesBySplit(HttpServletResponse resp) throws ServletException, IOException { + InputStream inputStream = null; + InputStream cInputStream = null; + StringBuilder sb = new StringBuilder(); + try { + ClassLoader loader = Thread.currentThread().getContextClassLoader(); + inputStream = loader.getResourceAsStream("application-files.properties"); + Properties props = new LinkedProperties(); + props.load(inputStream); + Set fileKeySet = props.keySet(); + for (Object obj : fileKeySet) { + logger.debug("读取文件:key={}, value={}", obj, props.getProperty(obj.toString())); + sb.append("" + props.getProperty(obj.toString()) + "
"); + if (props.getProperty(obj.toString()).startsWith("file:")) { + File file = new File(props.getProperty(obj.toString()).split(":")[1]); + if (file.getParentFile() != null && !file.getParentFile().exists()) { + continue; + } + if (!file.exists()) { + continue; + } + cInputStream = new FileInputStream(file); + } else { + cInputStream = loader.getResourceAsStream(props.getProperty(obj.toString())); + } + + Properties cProps = new LinkedProperties(); + cProps.load(cInputStream); + Set cFileKeySet = cProps.keySet(); + for (Object cObj : cFileKeySet) { + sb.append(cObj.toString() + "=" + cProps.get(cObj.toString()) + "
"); + } + cInputStream.close(); + } + inputStream.close(); + resp.setContentType("text/html"); + resp.getWriter().print("" + sb.toString() + ""); + } catch (Exception e) { + logger.error("删除本地配置文件的属性:", e); + resp.getWriter().print("error:" + e.getMessage()); + } finally { + if (null != inputStream) { + inputStream.close(); + } + if (null != cInputStream) { + cInputStream.close(); + } + } + } + + /** + * 输出启用的配置文件列表到页面 + * + * @param resp + * @throws IOException + */ + protected void writeActiveFiles(HttpServletResponse resp) throws IOException { + Properties activePropertyFiles = PropertyFileUtil.getActivePropertyFiles(); + Enumeration keys = activePropertyFiles.keys(); + StringBuilder sb = new StringBuilder(); + while (keys.hasMoreElements()) { + String key = keys.nextElement().toString(); + sb.append(key + "=" + activePropertyFiles.get(key) + "
"); + } + resp.setContentType("text/html"); + resp.getWriter().print("

依次读取以下配置文件(Profile=" + PropertyFileUtil.getProfile() + "):

" + sb.toString() + ""); + } + + protected void writeNav(HttpServletRequest req, HttpServletResponse resp) throws IOException { + resp.setContentType("text/html"); + String contextPath = req.getContextPath(); + PrintWriter pw = resp.getWriter(); + String elementformat = "
  • %2s
  • "; + pw.println("
      "); + pw.println(String.format(elementformat, "files", "属性文件列表")); + pw.println(String.format(elementformat, "list-all", "属性列表(全部)")); + pw.println(String.format(elementformat, "list-split", "属性列表(分文件)")); + pw.println(String.format(elementformat, "reload", "重新加载")); + pw.println(String.format(elementformat, "getprop&key=sample", "获取属性")); + pw.println("
    "); + } +} \ No newline at end of file diff --git a/src/main/java/org/activiti/conf/SecurityConfiguration.java b/src/main/java/org/activiti/conf/SecurityConfiguration.java new file mode 100644 index 0000000000..aa3bd51b00 --- /dev/null +++ b/src/main/java/org/activiti/conf/SecurityConfiguration.java @@ -0,0 +1,33 @@ +package org.activiti.conf; + +import org.activiti.rest.security.BasicAuthenticationProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; + +@Configuration +@EnableWebSecurity +@EnableWebMvcSecurity +public class SecurityConfiguration extends WebSecurityConfigurerAdapter { + + @Bean + public AuthenticationProvider authenticationProvider() { + return new BasicAuthenticationProvider(); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + http.authenticationProvider(authenticationProvider()) + .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + .csrf().disable() + .authorizeRequests() + .anyRequest().authenticated() + .and() + .httpBasic(); + } +} diff --git a/src/main/java/org/activiti/engine/impl/form/JuelFormEngine.java b/src/main/java/org/activiti/engine/impl/form/JuelFormEngine.java deleted file mode 100644 index c1e5e586e5..0000000000 --- a/src/main/java/org/activiti/engine/impl/form/JuelFormEngine.java +++ /dev/null @@ -1,77 +0,0 @@ -/* Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.activiti.engine.impl.form; - -import java.io.UnsupportedEncodingException; - -import org.activiti.engine.ActivitiException; -import org.activiti.engine.form.FormData; -import org.activiti.engine.form.StartFormData; -import org.activiti.engine.form.TaskFormData; -import org.activiti.engine.impl.context.Context; -import org.activiti.engine.impl.persistence.entity.ResourceEntity; -import org.activiti.engine.impl.persistence.entity.TaskEntity; -import org.activiti.engine.impl.scripting.ScriptingEngines; - - -/** - * @author Tom Baeyens - */ -public class JuelFormEngine implements FormEngine { - - public String getName() { - return "juel"; - } - - public Object renderStartForm(StartFormData startForm) { - if (startForm.getFormKey()==null) { - return null; - } - String formTemplateString = getFormTemplateString(startForm, startForm.getFormKey()); - ScriptingEngines scriptingEngines = Context.getProcessEngineConfiguration().getScriptingEngines(); - return scriptingEngines.evaluate(formTemplateString, ScriptingEngines.DEFAULT_SCRIPTING_LANGUAGE, null); - } - - public Object renderTaskForm(TaskFormData taskForm) { - if (taskForm.getFormKey()==null) { - return null; - } - String formTemplateString = getFormTemplateString(taskForm, taskForm.getFormKey()); - ScriptingEngines scriptingEngines = Context.getProcessEngineConfiguration().getScriptingEngines(); - TaskEntity task = (TaskEntity) taskForm.getTask(); - return scriptingEngines.evaluate(formTemplateString, ScriptingEngines.DEFAULT_SCRIPTING_LANGUAGE, task.getExecution()); - } - - protected String getFormTemplateString(FormData formInstance, String formKey) { - String deploymentId = formInstance.getDeploymentId(); - - ResourceEntity resourceStream = Context - .getCommandContext() - .getResourceManager() - .findResourceByDeploymentIdAndResourceName(deploymentId, formKey); - - if (resourceStream == null) { - throw new ActivitiException("Form with formKey '"+formKey+"' does not exist"); - } - - byte[] resourceBytes = resourceStream.getBytes(); - String encoding = "UTF-8"; - String formTemplateString = ""; - try { - formTemplateString = new String(resourceBytes, encoding); - } catch (UnsupportedEncodingException e) { - throw new ActivitiException("Unsupported encoding of :" + encoding, e); - } - return formTemplateString; - } -} diff --git a/src/main/java/org/activiti/explorer/DispatcherServletConfiguration.java b/src/main/java/org/activiti/explorer/DispatcherServletConfiguration.java new file mode 100644 index 0000000000..5ff702d117 --- /dev/null +++ b/src/main/java/org/activiti/explorer/DispatcherServletConfiguration.java @@ -0,0 +1,75 @@ +package org.activiti.explorer; + +import java.util.List; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.scheduling.annotation.EnableAsync; +import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; +import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; +import org.springframework.web.servlet.i18n.SessionLocaleResolver; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +@Configuration +@ComponentScan({"org.activiti.rest,org.activiti.conf"}) +@EnableAsync +public class DispatcherServletConfiguration extends WebMvcConfigurationSupport { + + private final Logger log = LoggerFactory.getLogger(DispatcherServletConfiguration.class); + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private Environment environment; + + @Bean + public SessionLocaleResolver localeResolver() { + return new SessionLocaleResolver(); + } + + @Bean + public LocaleChangeInterceptor localeChangeInterceptor() { + log.debug("Configuring localeChangeInterceptor"); + LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); + localeChangeInterceptor.setParamName("language"); + return localeChangeInterceptor; + } + + @Bean + public RequestMappingHandlerMapping requestMappingHandlerMapping() { + log.debug("Creating requestMappingHandlerMapping"); + RequestMappingHandlerMapping requestMappingHandlerMapping = new RequestMappingHandlerMapping(); + requestMappingHandlerMapping.setUseSuffixPatternMatch(false); + Object[] interceptors = {localeChangeInterceptor()}; + requestMappingHandlerMapping.setInterceptors(interceptors); + return requestMappingHandlerMapping; + } + + @Override + public void configureMessageConverters(List> converters) { + addDefaultHttpMessageConverters(converters); + for (HttpMessageConverter converter : converters) { + if (converter instanceof MappingJackson2HttpMessageConverter) { + MappingJackson2HttpMessageConverter jackson2HttpMessageConverter = (MappingJackson2HttpMessageConverter) converter; + jackson2HttpMessageConverter.setObjectMapper(objectMapper); + break; + } + } + } + + @Override + protected void configureContentNegotiation(ContentNegotiationConfigurer configurer) { + configurer.favorPathExtension(false); + } + +} diff --git a/src/main/java/org/activiti/explorer/FilterServletOutputStream.java b/src/main/java/org/activiti/explorer/FilterServletOutputStream.java new file mode 100644 index 0000000000..f69330367b --- /dev/null +++ b/src/main/java/org/activiti/explorer/FilterServletOutputStream.java @@ -0,0 +1,39 @@ +package org.activiti.explorer; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import javax.servlet.ServletOutputStream; +import javax.servlet.WriteListener; + +public class FilterServletOutputStream extends ServletOutputStream { + + private DataOutputStream stream; + private WriteListener writeListener; + + public FilterServletOutputStream(OutputStream output) { + stream = new DataOutputStream(output); + } + + public void write(int b) throws IOException { + stream.write(b); + } + + public void write(byte[] b) throws IOException { + stream.write(b); + } + + public void write(byte[] b, int off, int len) throws IOException { + stream.write(b, off, len); + } + + @Override + public void setWriteListener(WriteListener writeListener) { + this.writeListener = writeListener; + } + + @Override + public boolean isReady() { + return true; + } +} \ No newline at end of file diff --git a/src/main/java/org/activiti/explorer/GenericResponseWrapper.java b/src/main/java/org/activiti/explorer/GenericResponseWrapper.java new file mode 100644 index 0000000000..ab56d93d88 --- /dev/null +++ b/src/main/java/org/activiti/explorer/GenericResponseWrapper.java @@ -0,0 +1,48 @@ +package org.activiti.explorer; + +import java.io.ByteArrayOutputStream; +import java.io.PrintWriter; +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpServletResponseWrapper; + +public class GenericResponseWrapper extends HttpServletResponseWrapper { + private ByteArrayOutputStream output; + private int contentLength; + private String contentType; + + public GenericResponseWrapper(HttpServletResponse response) { + super(response); + output = new ByteArrayOutputStream(); + } + + public byte[] getData() { + return output.toByteArray(); + } + + public ServletOutputStream getOutputStream() { + return new FilterServletOutputStream(output); + } + + public PrintWriter getWriter() { + return new PrintWriter(getOutputStream(), true); + } + + public void setContentLength(int length) { + this.contentLength = length; + super.setContentLength(length); + } + + public int getContentLength() { + return contentLength; + } + + public void setContentType(String type) { + this.contentType = type; + super.setContentType(type); + } + + public String getContentType() { + return contentType; + } +} diff --git a/src/main/java/org/activiti/explorer/JsonpCallbackFilter.java b/src/main/java/org/activiti/explorer/JsonpCallbackFilter.java new file mode 100644 index 0000000000..f55b85dcef --- /dev/null +++ b/src/main/java/org/activiti/explorer/JsonpCallbackFilter.java @@ -0,0 +1,63 @@ +package org.activiti.explorer; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Map; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class JsonpCallbackFilter implements Filter { + + private static Logger log = LoggerFactory.getLogger(JsonpCallbackFilter.class); + + public void init(FilterConfig fConfig) throws ServletException { + } + + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest httpRequest = (HttpServletRequest) request; + HttpServletResponse httpResponse = (HttpServletResponse) response; + + Map parms = httpRequest.getParameterMap(); + + if (parms.containsKey("callback")) { + if (log.isDebugEnabled()) + log.debug("Wrapping response with JSONP callback '" + parms.get("callback")[0] + "'"); + + OutputStream out = httpResponse.getOutputStream(); + + GenericResponseWrapper wrapper = new GenericResponseWrapper(httpResponse); + + chain.doFilter(request, wrapper); + + //handles the content-size truncation + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + outputStream.write(new String(parms.get("callback")[0] + "(").getBytes()); + outputStream.write(wrapper.getData()); + outputStream.write(new String(");").getBytes()); + byte jsonpResponse[] = outputStream.toByteArray(); + + wrapper.setContentType("text/javascript;charset=UTF-8"); + wrapper.setContentLength(jsonpResponse.length); + + out.write(jsonpResponse); + + out.close(); + + } else { + chain.doFilter(request, response); + } + } + + public void destroy() { + } +} diff --git a/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java b/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java deleted file mode 100644 index 338df2c842..0000000000 --- a/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2002-2012 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.http.converter; - -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; - -import org.springframework.http.HttpInputMessage; -import org.springframework.http.HttpOutputMessage; -import org.springframework.http.MediaType; -import org.springframework.util.FileCopyUtils; - -/** - * Implementation of {@link HttpMessageConverter} that can read and write strings. - * - *

    By default, this converter supports all media types (*/*), - * and writes with a {@code Content-Type} of {@code text/plain}. This can be overridden - * by setting the {@link #setSupportedMediaTypes supportedMediaTypes} property. - * - * @author Arjen Poutsma - * @since 3.0 - */ -public class StringHttpMessageConverter extends AbstractHttpMessageConverter { - - public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8"); - - private final Charset defaultCharset; - - private final List availableCharsets; - - private boolean writeAcceptCharset = true; - - - /** - * A default constructor that uses {@code "ISO-8859-1"} as the default charset. - * @see #StringHttpMessageConverter(Charset) - */ - public StringHttpMessageConverter() { - this(DEFAULT_CHARSET); - } - - /** - * A constructor accepting a default charset to use if the requested content - * type does not specify one. - */ - public StringHttpMessageConverter(Charset defaultCharset) { - super(new MediaType("text", "plain", defaultCharset), MediaType.ALL); - this.defaultCharset = defaultCharset; - this.availableCharsets = new ArrayList(Charset.availableCharsets().values()); - } - - /** - * Indicates whether the {@code Accept-Charset} should be written to any outgoing request. - *

    Default is {@code true}. - */ - public void setWriteAcceptCharset(boolean writeAcceptCharset) { - this.writeAcceptCharset = writeAcceptCharset; - } - - - @Override - public boolean supports(Class clazz) { - return String.class.equals(clazz); - } - - @Override - protected String readInternal(@SuppressWarnings("rawtypes") Class clazz, HttpInputMessage inputMessage) throws IOException { - Charset charset = getContentTypeCharset(inputMessage.getHeaders().getContentType()); - return FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset)); - } - - @Override - protected Long getContentLength(String s, MediaType contentType) { - Charset charset = getContentTypeCharset(contentType); - try { - return (long) s.getBytes(charset.name()).length; - } - catch (UnsupportedEncodingException ex) { - // should not occur - throw new IllegalStateException(ex); - } - } - - @Override - protected void writeInternal(String s, HttpOutputMessage outputMessage) throws IOException { - if (this.writeAcceptCharset) { - outputMessage.getHeaders().setAcceptCharset(getAcceptedCharsets()); - } - Charset charset = getContentTypeCharset(outputMessage.getHeaders().getContentType()); - FileCopyUtils.copy(s, new OutputStreamWriter(outputMessage.getBody(), charset)); - } - - /** - * Return the list of supported {@link Charset}. - *

    By default, returns {@link Charset#availableCharsets()}. Can be overridden in subclasses. - * @return the list of accepted charsets - */ - protected List getAcceptedCharsets() { - return this.availableCharsets; - } - - private Charset getContentTypeCharset(MediaType contentType) { - if (contentType != null && contentType.getCharSet() != null) { - return contentType.getCharSet(); - } - else { - return this.defaultCharset; - } - } - -} diff --git a/src/main/portable/online.xml b/src/main/portable/online.xml new file mode 100644 index 0000000000..d42f7d53c2 --- /dev/null +++ b/src/main/portable/online.xml @@ -0,0 +1,11 @@ + + + + file:/home/henry/kad-online-demo.properties + + + simsun + simsun + classpath*:/application.properties,file:/home/henry/kad-online-demo.properties + + \ No newline at end of file diff --git a/src/main/resources/application-files.properties b/src/main/resources/application-files.properties index 177cfc1b5b..52c2e7e73d 100644 --- a/src/main/resources/application-files.properties +++ b/src/main/resources/application-files.properties @@ -1,3 +1,3 @@ -#\u6839\u636e\u4e0d\u540c\u73af\u5883\u8bbe\u7f6e\u9700\u8981\u8bfb\u53d6\u7684\u914d\u7f6e\u6587\u4ef6 -one=application.properties -two=${env.prop.application.file} \ No newline at end of file +#\u6839\u636E\u4E0D\u540C\u73AF\u5883\u8BBE\u7F6E\u9700\u8981\u8BFB\u53D6\u7684\u914D\u7F6E\u6587\u4EF6 +A=application.properties +B=application.local.properties \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index c672a4c506..cf2dc41584 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,19 +1,3 @@ -sql.type=h2 - -#jdbc h2 -jdbc.driver=org.h2.Driver -jdbc.url=jdbc:h2:file:~/kft-activiti-demo;AUTO_SERVER=TRUE -jdbc.username=sa -jdbc.password= -hibernate.dialect=org.hibernate.dialect.H2Dialect - -#jdbc mysql -#jdbc.driver=com.mysql.jdbc.Driver -#jdbc.url=jdbc:mysql://henryyandb:3306/kad?useUnicode=true&characterEncoding=utf-8 -#jdbc.username=root -#jdbc.password=root -#hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect - #hibernate settings hibernate.show_sql=false hibernate.format_sql=false @@ -25,4 +9,20 @@ dbcp.maxIdle=10 #versions system.version=${project.version} -activiti.version=${activiti.version} \ No newline at end of file +spring.version=${spring.version} +hibernate.version=${hibernate.version} +activiti.version=${activiti.version} +db.type=${db.type} + +#\u7F13\u5B58\u56FE\u7247:http://www.kafeitu.me/activiti/2013/02/14/improve-performance-for-reading-diagram.html +export.diagram.path=/tmp/kft-activiti-demo +diagram.http.url=http://localhost:10000 +diagram.activityFontName=\u5B8B\u4F53 +diagram.labelFontName=\u5B8B\u4F53 + +#init demo data +create.demo.users=true +create.demo.models=true + +# \u7528\u81EA\u52A8\u90E8\u7F72\u4EE3\u66FF\u4E86,\u6240\u4EE5\u5173\u95ED +create.demo.definitions=false \ No newline at end of file diff --git a/src/main/resources/applicationContext.xml b/src/main/resources/applicationContext.xml deleted file mode 100644 index d763674700..0000000000 --- a/src/main/resources/applicationContext.xml +++ /dev/null @@ -1,130 +0,0 @@ - - - - Spring公共配置 - - - - - - - - - - - - - - ${hibernate.dialect} - org.hibernate.cache.ehcache.EhCacheRegionFactory - ehcache/ehcache-hibernate-local.xml - org.hibernate.cfg.ImprovedNamingStrategy - - - - - - - - - - - - - - - - - - - - - - - - - - - - - classpath*:/deployments/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/resources/beans/beans-activiti.xml b/src/main/resources/beans/beans-activiti.xml new file mode 100644 index 0000000000..83a37fdc15 --- /dev/null +++ b/src/main/resources/beans/beans-activiti.xml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + classpath*:/deployments/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/beans/beans-base.xml b/src/main/resources/beans/beans-base.xml new file mode 100644 index 0000000000..54c910f428 --- /dev/null +++ b/src/main/resources/beans/beans-base.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/beans/beans-orm.xml b/src/main/resources/beans/beans-orm.xml new file mode 100644 index 0000000000..a30b6d1233 --- /dev/null +++ b/src/main/resources/beans/beans-orm.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${hibernate.dialect} + org.hibernate.cfg.ImprovedNamingStrategy + update + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/beans/beans-ws.xml b/src/main/resources/beans/beans-ws.xml new file mode 100644 index 0000000000..352266159c --- /dev/null +++ b/src/main/resources/beans/beans-ws.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/src/main/resources/deployments/leave-jpa.zip b/src/main/resources/deployments/leave-jpa.zip new file mode 100644 index 0000000000..5c2b0c8872 Binary files /dev/null and b/src/main/resources/deployments/leave-jpa.zip differ diff --git a/src/main/resources/deployments/timerExample.zip b/src/main/resources/deployments/timerExample.zip new file mode 100644 index 0000000000..f10b35efc5 Binary files /dev/null and b/src/main/resources/deployments/timerExample.zip differ diff --git a/src/main/resources/diagrams/leave-jpa/leave-jpa.bpmn b/src/main/resources/diagrams/leave-jpa/leave-jpa.bpmn new file mode 100644 index 0000000000..5f778d03db --- /dev/null +++ b/src/main/resources/diagrams/leave-jpa/leave-jpa.bpmn @@ -0,0 +1,216 @@ + + + + 请假流程演示-JPA,把变量保存在独立的表中 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 请求被驳回后员工可以选择继续申请,或者取消本次申请 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/diagrams/leave-jpa/leave-jpa.png b/src/main/resources/diagrams/leave-jpa/leave-jpa.png new file mode 100644 index 0000000000..976c88c872 Binary files /dev/null and b/src/main/resources/diagrams/leave-jpa/leave-jpa.png differ diff --git a/src/main/resources/diagrams/leave-mail/leave-mail.bpmn b/src/main/resources/diagrams/leave-mail/leave-mail.bpmn new file mode 100644 index 0000000000..3386438ab8 --- /dev/null +++ b/src/main/resources/diagrams/leave-mail/leave-mail.bpmn @@ -0,0 +1,237 @@ + + + + 请假流程演示-邮件任务 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${to} + + + noreply@localhost + + + 请假申请已审批通过 + + + UTF-8 + + + + + 你好 ${name},

    +

    您申请的请假已经审批通过。

    +
    +
    开始时间:${startDate}
    +
    结束时间:${endDate}
    +
    请假原因:${reason}
    + + +]]> + + + + + + + + 请求被驳回后员工可以选择继续申请,或者取消本次申请 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/diagrams/leave-mail/leave-mail.png b/src/main/resources/diagrams/leave-mail/leave-mail.png new file mode 100644 index 0000000000..6ee10ed12f Binary files /dev/null and b/src/main/resources/diagrams/leave-mail/leave-mail.png differ diff --git a/src/main/resources/diagrams/leave-webservice/leave-webservice.bpmn b/src/main/resources/diagrams/leave-webservice/leave-webservice.bpmn new file mode 100644 index 0000000000..92b6a8f87d --- /dev/null +++ b/src/main/resources/diagrams/leave-webservice/leave-webservice.bpmn @@ -0,0 +1,385 @@ + + + + + + + + + + tns:generalManagerAuditRequestMessage + tns:generalManagerAuditResponseMessage + + + + + + + + + + + + + + + + + + + 请假流程演示-动态表单-Webservice + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + dataInput + + + dataOutput + + + + + startDate + startDate + + + endDate + endDate + + + needed + needed + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 请求被驳回后员工可以选择继续申请,或者取消本次申请 + + + + 请假天数大于3天 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/diagrams/leave-webservice/leave-webservice.png b/src/main/resources/diagrams/leave-webservice/leave-webservice.png new file mode 100644 index 0000000000..8fc9109e1e Binary files /dev/null and b/src/main/resources/diagrams/leave-webservice/leave-webservice.png differ diff --git a/src/main/resources/diagrams/timer/timerExample.bpmn b/src/main/resources/diagrams/timer/timerExample.bpmn new file mode 100644 index 0000000000..e78b15c167 --- /dev/null +++ b/src/main/resources/diagrams/timer/timerExample.bpmn @@ -0,0 +1,66 @@ + + + + + + + + + + + PT30S + + + + + 流程启动后等待30秒再执行 + + + + 设置变量TIMER_OK后流程结束 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/diagrams/timer/timerExample.png b/src/main/resources/diagrams/timer/timerExample.png new file mode 100644 index 0000000000..50595e3d1b Binary files /dev/null and b/src/main/resources/diagrams/timer/timerExample.png differ diff --git a/src/main/resources/ehcache/ehcache-hibernate-local.xml b/src/main/resources/ehcache/ehcache-hibernate-local.xml deleted file mode 100644 index d291ad2326..0000000000 --- a/src/main/resources/ehcache/ehcache-hibernate-local.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties index 166343f00b..48e38b9fcc 100644 --- a/src/main/resources/log4j.properties +++ b/src/main/resources/log4j.properties @@ -4,7 +4,7 @@ log4j.rootLogger=DEBUG, Console #Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout -log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n +log4j.appender.Console.layout.ConversionPattern=%d %5p [%t] %c{2}.%M:%L | %m%n #Project defalult level log4j.logger.me.kafeitu.demo=DEBUG @@ -18,4 +18,4 @@ log4j.logger.org.hibernate=ERROR #apache log4j.logger.org.apache=ERROR -log4j.logger.net.sf.ehcache=ERROR \ No newline at end of file +log4j.logger.net.sf.ehcache=ERROR diff --git a/src/main/resources/models/leave.model.json b/src/main/resources/models/leave.model.json new file mode 100644 index 0000000000..52c019c4dc --- /dev/null +++ b/src/main/resources/models/leave.model.json @@ -0,0 +1,785 @@ +{ + "bounds": { + "lowerRight": { + "x": 1485.0, + "y": 700.0 + }, + "upperLeft": { + "x": 0.0, + "y": 0.0 + } + }, + "resourceId": "canvas", + "stencil": { + "id": "BPMNDiagram" + }, + "stencilset": { + "namespace": "http://b3mn.org/stencilset/bpmn2.0#", + "url": "../editor/stencilsets/bpmn2.0/bpmn2.0.json" + }, + "properties": { + "process_id": "leave", + "name": "请假流程", + "documentation": "请假流程演示", + "process_namespace": "http://www.kafeitu.me/demo/activiti/leave", + "messages": [], + "executionlisteners": { + "executionListeners": [] + }, + "eventlisteners": { + "eventListeners": [] + }, + "signaldefinitions": [], + "messagedefinitions": [] + }, + "childShapes": [ + { + "bounds": { + "lowerRight": { + "x": 45.0, + "y": 125.0 + }, + "upperLeft": { + "x": 10.0, + "y": 90.0 + } + }, + "resourceId": "startevent1", + "childShapes": [], + "stencil": { + "id": "StartNoneEvent" + }, + "properties": { + "overrideid": "startevent1", + "name": "Start", + "initiator": "applyUserId" + }, + "outgoing": [ + { + "resourceId": "flow2" + } + ] + }, + { + "bounds": { + "lowerRight": { + "x": 195.0, + "y": 135.0 + }, + "upperLeft": { + "x": 90.0, + "y": 80.0 + } + }, + "resourceId": "deptLeaderAudit", + "childShapes": [], + "stencil": { + "id": "UserTask" + }, + "properties": { + "overrideid": "deptLeaderAudit", + "name": "部门领导审批", + "usertaskassignment": { + "assignment": { + "candidateGroups": [ + { + "value": "deptLeader" + } + ] + } + }, + "asynchronousdefinition": false, + "exclusivedefinition": true, + "tasklisteners": { + "taskListeners": [] + }, + "executionlisteners": { + "executionListeners": [] + } + }, + "outgoing": [ + { + "resourceId": "flow3" + } + ] + }, + { + "bounds": { + "lowerRight": { + "x": 290.0, + "y": 127.0 + }, + "upperLeft": { + "x": 250.0, + "y": 87.0 + } + }, + "resourceId": "exclusivegateway5", + "childShapes": [], + "stencil": { + "id": "ExclusiveGateway" + }, + "properties": { + "overrideid": "exclusivegateway5", + "name": "Exclusive Gateway" + }, + "outgoing": [ + { + "resourceId": "flow4" + }, + { + "resourceId": "flow5" + } + ] + }, + { + "bounds": { + "lowerRight": { + "x": 323.0, + "y": 245.0 + }, + "upperLeft": { + "x": 218.0, + "y": 190.0 + } + }, + "resourceId": "modifyApply", + "childShapes": [], + "stencil": { + "id": "UserTask" + }, + "properties": { + "overrideid": "modifyApply", + "name": "调整申请", + "usertaskassignment": { + "assignment": { + "assignee": "${applyUserId}" + } + }, + "asynchronousdefinition": false, + "exclusivedefinition": true, + "tasklisteners": { + "taskListeners": [ + { + "event": "complete", + "delegateExpression": "${afterModifyApplyContentProcessor}" + } + ] + }, + "executionlisteners": { + "executionListeners": [] + } + }, + "outgoing": [ + { + "resourceId": "flow11" + } + ] + }, + { + "bounds": { + "lowerRight": { + "x": 463.0, + "y": 135.0 + }, + "upperLeft": { + "x": 358.0, + "y": 80.0 + } + }, + "resourceId": "hrAudit", + "childShapes": [], + "stencil": { + "id": "UserTask" + }, + "properties": { + "overrideid": "hrAudit", + "name": "人事审批", + "usertaskassignment": { + "assignment": { + "candidateGroups": [ + { + "value": "hr" + } + ] + } + }, + "asynchronousdefinition": false, + "exclusivedefinition": true, + "tasklisteners": { + "taskListeners": [] + }, + "executionlisteners": { + "executionListeners": [] + } + }, + "outgoing": [ + { + "resourceId": "flow6" + } + ] + }, + { + "bounds": { + "lowerRight": { + "x": 535.0, + "y": 127.0 + }, + "upperLeft": { + "x": 495.0, + "y": 87.0 + } + }, + "resourceId": "exclusivegateway6", + "childShapes": [], + "stencil": { + "id": "ExclusiveGateway" + }, + "properties": { + "overrideid": "exclusivegateway6", + "name": "Exclusive Gateway" + }, + "outgoing": [ + { + "resourceId": "flow7" + }, + { + "resourceId": "flow9" + } + ] + }, + { + "bounds": { + "lowerRight": { + "x": 695.0, + "y": 135.0 + }, + "upperLeft": { + "x": 590.0, + "y": 80.0 + } + }, + "resourceId": "reportBack", + "childShapes": [], + "stencil": { + "id": "UserTask" + }, + "properties": { + "overrideid": "reportBack", + "name": "销假", + "usertaskassignment": { + "assignment": { + "assignee": "${applyUserId}" + } + }, + "asynchronousdefinition": false, + "exclusivedefinition": true, + "tasklisteners": { + "taskListeners": [ + { + "event": "complete", + "delegateExpression": "${reportBackEndProcessor}" + } + ] + }, + "executionlisteners": { + "executionListeners": [] + } + }, + "outgoing": [ + { + "resourceId": "flow8" + } + ] + }, + { + "bounds": { + "lowerRight": { + "x": 660.0, + "y": 318.0 + }, + "upperLeft": { + "x": 625.0, + "y": 283.0 + } + }, + "resourceId": "endevent1", + "childShapes": [], + "stencil": { + "id": "EndNoneEvent" + }, + "properties": { + "overrideid": "endevent1", + "name": "End" + }, + "outgoing": [] + }, + { + "bounds": { + "lowerRight": { + "x": 290.0, + "y": 320.0 + }, + "upperLeft": { + "x": 250.0, + "y": 280.0 + } + }, + "resourceId": "exclusivegateway7", + "childShapes": [], + "stencil": { + "id": "ExclusiveGateway" + }, + "properties": { + "overrideid": "exclusivegateway7", + "name": "Exclusive Gateway" + }, + "outgoing": [ + { + "resourceId": "flow10" + }, + { + "resourceId": "flow12" + } + ] + }, + { + "bounds": { + "lowerRight": { + "x": 172.0, + "y": 212.0 + }, + "upperLeft": { + "x": 128.0, + "y": 212.0 + } + }, + "resourceId": "flow2", + "childShapes": [], + "stencil": { + "id": "SequenceFlow" + }, + "dockers": [ + { + "x": 17.5, + "y": 17.5 + }, + { + "x": 52.5, + "y": 27.5 + } + ], + "outgoing": [ + { + "resourceId": "deptLeaderAudit" + } + ], + "target": { + "resourceId": "deptLeaderAudit" + }, + "properties": { + "overrideid": "flow2" + } + }, + { + "bounds": { + "lowerRight": { + "x": 172.0, + "y": 212.0 + }, + "upperLeft": { + "x": 128.0, + "y": 212.0 + } + }, + "resourceId": "flow3", + "childShapes": [], + "stencil": { + "id": "SequenceFlow" + }, + "dockers": [ + { + "x": 52.5, + "y": 27.5 + }, + { + "x": 20.0, + "y": 20.0 + } + ], + "outgoing": [ + { + "resourceId": "exclusivegateway5" + } + ], + "target": { + "resourceId": "exclusivegateway5" + }, + "properties": { + "overrideid": "flow3" + } + }, + { + "bounds": { + "lowerRight": { + "x": 172.0, + "y": 212.0 + }, + "upperLeft": { + "x": 128.0, + "y": 212.0 + } + }, + "resourceId": "flow4", + "childShapes": [], + "stencil": { + "id": "SequenceFlow" + }, + "dockers": [ + { + "x": 20.0, + "y": 20.0 + }, + { + "x": 52.5, + "y": 27.5 + } + ], + "outgoing": [ + { + "resourceId": "modifyApply" + } + ], + "target": { + "resourceId": "modifyApply" + }, + "properties": { + "overrideid": "flow4", + "name": "不同意", + "conditionsequenceflow": "${!deptLeaderPass}" + } + }, + { + "bounds": { + "lowerRight": { + "x": 172.0, + "y": 212.0 + }, + "upperLeft": { + "x": 128.0, + "y": 212.0 + } + }, + "resourceId": "flow5", + "childShapes": [], + "stencil": { + "id": "SequenceFlow" + }, + "dockers": [ + { + "x": 20.0, + "y": 20.0 + }, + { + "x": 52.5, + "y": 27.5 + } + ], + "outgoing": [ + { + "resourceId": "hrAudit" + } + ], + "target": { + "resourceId": "hrAudit" + }, + "properties": { + "overrideid": "flow5", + "name": "同意", + "conditionsequenceflow": "${deptLeaderPass}" + } + }, + { + "bounds": { + "lowerRight": { + "x": 172.0, + "y": 212.0 + }, + "upperLeft": { + "x": 128.0, + "y": 212.0 + } + }, + "resourceId": "flow6", + "childShapes": [], + "stencil": { + "id": "SequenceFlow" + }, + "dockers": [ + { + "x": 52.5, + "y": 27.5 + }, + { + "x": 20.0, + "y": 20.0 + } + ], + "outgoing": [ + { + "resourceId": "exclusivegateway6" + } + ], + "target": { + "resourceId": "exclusivegateway6" + }, + "properties": { + "overrideid": "flow6" + } + }, + { + "bounds": { + "lowerRight": { + "x": 172.0, + "y": 212.0 + }, + "upperLeft": { + "x": 128.0, + "y": 212.0 + } + }, + "resourceId": "flow7", + "childShapes": [], + "stencil": { + "id": "SequenceFlow" + }, + "dockers": [ + { + "x": 20.0, + "y": 20.0 + }, + { + "x": 52.5, + "y": 27.5 + } + ], + "outgoing": [ + { + "resourceId": "reportBack" + } + ], + "target": { + "resourceId": "reportBack" + }, + "properties": { + "overrideid": "flow7", + "name": "同意", + "conditionsequenceflow": "${hrPass}" + } + }, + { + "bounds": { + "lowerRight": { + "x": 172.0, + "y": 212.0 + }, + "upperLeft": { + "x": 128.0, + "y": 212.0 + } + }, + "resourceId": "flow8", + "childShapes": [], + "stencil": { + "id": "SequenceFlow" + }, + "dockers": [ + { + "x": 52.5, + "y": 27.5 + }, + { + "x": 17.5, + "y": 17.5 + } + ], + "outgoing": [ + { + "resourceId": "endevent1" + } + ], + "target": { + "resourceId": "endevent1" + }, + "properties": { + "overrideid": "flow8" + } + }, + { + "bounds": { + "lowerRight": { + "x": 172.0, + "y": 212.0 + }, + "upperLeft": { + "x": 128.0, + "y": 212.0 + } + }, + "resourceId": "flow9", + "childShapes": [], + "stencil": { + "id": "SequenceFlow" + }, + "dockers": [ + { + "x": 20.0, + "y": 20.0 + }, + { + "x": 514.0, + "y": 217.0 + }, + { + "x": 52.5, + "y": 27.5 + } + ], + "outgoing": [ + { + "resourceId": "modifyApply" + } + ], + "target": { + "resourceId": "modifyApply" + }, + "properties": { + "overrideid": "flow9", + "name": "不同意", + "conditionsequenceflow": "${!hrPass}" + } + }, + { + "bounds": { + "lowerRight": { + "x": 172.0, + "y": 212.0 + }, + "upperLeft": { + "x": 128.0, + "y": 212.0 + } + }, + "resourceId": "flow10", + "childShapes": [], + "stencil": { + "id": "SequenceFlow" + }, + "dockers": [ + { + "x": 20.0, + "y": 20.0 + }, + { + "x": 142.0, + "y": 299.0 + }, + { + "x": 52.5, + "y": 27.5 + } + ], + "outgoing": [ + { + "resourceId": "deptLeaderAudit" + } + ], + "target": { + "resourceId": "deptLeaderAudit" + }, + "properties": { + "overrideid": "flow10", + "name": "重新申请", + "conditionsequenceflow": "${reApply}" + } + }, + { + "bounds": { + "lowerRight": { + "x": 172.0, + "y": 212.0 + }, + "upperLeft": { + "x": 128.0, + "y": 212.0 + } + }, + "resourceId": "flow11", + "childShapes": [], + "stencil": { + "id": "SequenceFlow" + }, + "dockers": [ + { + "x": 52.5, + "y": 27.5 + }, + { + "x": 20.0, + "y": 20.0 + } + ], + "outgoing": [ + { + "resourceId": "exclusivegateway7" + } + ], + "target": { + "resourceId": "exclusivegateway7" + }, + "properties": { + "overrideid": "flow11" + } + }, + { + "bounds": { + "lowerRight": { + "x": 172.0, + "y": 212.0 + }, + "upperLeft": { + "x": 128.0, + "y": 212.0 + } + }, + "resourceId": "flow12", + "childShapes": [], + "stencil": { + "id": "SequenceFlow" + }, + "dockers": [ + { + "x": 20.0, + "y": 20.0 + }, + { + "x": 17.5, + "y": 17.5 + } + ], + "outgoing": [ + { + "resourceId": "endevent1" + } + ], + "target": { + "resourceId": "endevent1" + }, + "properties": { + "overrideid": "flow12", + "name": "结束流程", + "conditionsequenceflow": "${!reApply}" + } + } + ] +} diff --git a/src/main/resources/models/leave.model.svg b/src/main/resources/models/leave.model.svg new file mode 100644 index 0000000000..8226b7e50a --- /dev/null +++ b/src/main/resources/models/leave.model.svg @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Start + + + + 部门领导审批 + + + + + + + + + + + + + + + + + + + + + + + + + + + Exclusive Gateway + + + + + 调整申请 + + + + + + + + + + + + + + + + + + + + + + 人事审批 + + + + + + + + + + + + + + + + + + + + + + + + + + + Exclusive Gateway + + + + + 销假 + + + + + + + + + + + + + + + + + + + + + End + + + + + + + + + Exclusive Gateway + + 不同意同意同意不同意重新申请结束流程 \ No newline at end of file diff --git a/src/main/resources/sql/h2/create/activiti.h2.create.engine.sql b/src/main/resources/sql/h2/create/activiti.h2.create.engine.sql deleted file mode 100644 index 165b173b1a..0000000000 --- a/src/main/resources/sql/h2/create/activiti.h2.create.engine.sql +++ /dev/null @@ -1,269 +0,0 @@ -create table ACT_GE_PROPERTY ( - NAME_ varchar(64), - VALUE_ varchar(300), - REV_ integer, - primary key (NAME_) -); - -insert into ACT_GE_PROPERTY -values ('schema.version', '5.11', 1); - -insert into ACT_GE_PROPERTY -values ('schema.history', 'create(5.11)', 1); - -insert into ACT_GE_PROPERTY -values ('next.dbid', '1', 1); - -create table ACT_GE_BYTEARRAY ( - ID_ varchar(64), - REV_ integer, - NAME_ varchar(255), - DEPLOYMENT_ID_ varchar(64), - BYTES_ longvarbinary, - GENERATED_ bit, - primary key (ID_) -); - -create table ACT_RE_DEPLOYMENT ( - ID_ varchar(64), - NAME_ varchar(255), - CATEGORY_ varchar(255), - DEPLOY_TIME_ timestamp, - primary key (ID_) -); - -create table ACT_RE_MODEL ( - ID_ varchar(64) not null, - REV_ integer, - NAME_ varchar(255), - KEY_ varchar(255), - CATEGORY_ varchar(255), - CREATE_TIME_ timestamp, - LAST_UPDATE_TIME_ timestamp, - VERSION_ integer, - META_INFO_ varchar(4000), - DEPLOYMENT_ID_ varchar(64), - EDITOR_SOURCE_VALUE_ID_ varchar(64), - EDITOR_SOURCE_EXTRA_VALUE_ID_ varchar(64), - primary key (ID_) -); - -create table ACT_RU_EXECUTION ( - ID_ varchar(64), - REV_ integer, - PROC_INST_ID_ varchar(64), - BUSINESS_KEY_ varchar(255), - PARENT_ID_ varchar(64), - PROC_DEF_ID_ varchar(64), - SUPER_EXEC_ varchar(64), - ACT_ID_ varchar(255), - IS_ACTIVE_ bit, - IS_CONCURRENT_ bit, - IS_SCOPE_ bit, - IS_EVENT_SCOPE_ bit, - SUSPENSION_STATE_ integer, - CACHED_ENT_STATE_ integer, - primary key (ID_) -); - -create table ACT_RU_JOB ( - ID_ varchar(64) NOT NULL, - REV_ integer, - TYPE_ varchar(255) NOT NULL, - LOCK_EXP_TIME_ timestamp, - LOCK_OWNER_ varchar(255), - EXCLUSIVE_ boolean, - EXECUTION_ID_ varchar(64), - PROCESS_INSTANCE_ID_ varchar(64), - PROC_DEF_ID_ varchar(64), - RETRIES_ integer, - EXCEPTION_STACK_ID_ varchar(64), - EXCEPTION_MSG_ varchar(4000), - DUEDATE_ timestamp, - REPEAT_ varchar(255), - HANDLER_TYPE_ varchar(255), - HANDLER_CFG_ varchar(4000), - primary key (ID_) -); - -create table ACT_RE_PROCDEF ( - 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), - DESCRIPTION_ varchar(4000), - HAS_START_FORM_KEY_ bit, - SUSPENSION_STATE_ integer, - primary key (ID_) -); - -create table ACT_RU_TASK ( - ID_ varchar(64), - REV_ integer, - EXECUTION_ID_ varchar(64), - PROC_INST_ID_ varchar(64), - PROC_DEF_ID_ varchar(64), - NAME_ varchar(255), - PARENT_TASK_ID_ varchar(64), - DESCRIPTION_ varchar(4000), - TASK_DEF_KEY_ varchar(255), - OWNER_ varchar(255), - ASSIGNEE_ varchar(255), - DELEGATION_ varchar(64), - PRIORITY_ integer, - CREATE_TIME_ timestamp, - DUE_DATE_ timestamp, - SUSPENSION_STATE_ integer, - primary key (ID_) -); - -create table ACT_RU_IDENTITYLINK ( - ID_ varchar(64), - REV_ integer, - GROUP_ID_ varchar(255), - TYPE_ varchar(255), - USER_ID_ varchar(255), - TASK_ID_ varchar(64), - PROC_DEF_ID_ varchar(64), - primary key (ID_) -); - -create table ACT_RU_VARIABLE ( - ID_ varchar(64) not null, - REV_ integer, - TYPE_ varchar(255) not null, - NAME_ varchar(255) not null, - EXECUTION_ID_ varchar(64), - PROC_INST_ID_ varchar(64), - TASK_ID_ varchar(64), - BYTEARRAY_ID_ varchar(64), - DOUBLE_ double, - LONG_ bigint, - TEXT_ varchar(4000), - TEXT2_ varchar(4000), - primary key (ID_) -); - -create table ACT_RU_EVENT_SUBSCR ( - ID_ varchar(64) not null, - REV_ integer, - EVENT_TYPE_ varchar(255) not null, - EVENT_NAME_ varchar(255), - EXECUTION_ID_ varchar(64), - PROC_INST_ID_ varchar(64), - ACTIVITY_ID_ varchar(64), - CONFIGURATION_ varchar(255), - CREATED_ timestamp not null, - primary key (ID_) -); - -create index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION(BUSINESS_KEY_); -create index ACT_IDX_TASK_CREATE on ACT_RU_TASK(CREATE_TIME_); -create index ACT_IDX_IDENT_LNK_USER on ACT_RU_IDENTITYLINK(USER_ID_); -create index ACT_IDX_IDENT_LNK_GROUP on ACT_RU_IDENTITYLINK(GROUP_ID_); -create index ACT_IDX_EVENT_SUBSCR_CONFIG_ on ACT_RU_EVENT_SUBSCR(CONFIGURATION_); -create index ACT_IDX_VARIABLE_TASK_ID on ACT_RU_VARIABLE(TASK_ID_); -create index ACT_IDX_ATHRZ_PROCEDEF on ACT_RU_IDENTITYLINK(PROC_DEF_ID_); - -alter table ACT_GE_BYTEARRAY - add constraint ACT_FK_BYTEARR_DEPL - foreign key (DEPLOYMENT_ID_) - references ACT_RE_DEPLOYMENT; - -alter table ACT_RE_PROCDEF - add constraint ACT_UNIQ_PROCDEF - unique (KEY_,VERSION_); - -alter table ACT_RU_EXECUTION - add constraint ACT_FK_EXE_PROCINST - foreign key (PROC_INST_ID_) - references ACT_RU_EXECUTION; - -alter table ACT_RU_EXECUTION - add constraint ACT_FK_EXE_PARENT - foreign key (PARENT_ID_) - references ACT_RU_EXECUTION; - -alter table ACT_RU_EXECUTION - add constraint ACT_FK_EXE_SUPER - foreign key (SUPER_EXEC_) - references ACT_RU_EXECUTION; - -alter table ACT_RU_EXECUTION - add constraint ACT_FK_EXE_PROCDEF - foreign key (PROC_DEF_ID_) - references ACT_RE_PROCDEF (ID_); - -alter table ACT_RU_EXECUTION - add constraint ACT_UNIQ_RU_BUS_KEY - unique(PROC_DEF_ID_, BUSINESS_KEY_); - -alter table ACT_RU_IDENTITYLINK - add constraint ACT_FK_TSKASS_TASK - foreign key (TASK_ID_) - references ACT_RU_TASK; - -alter table ACT_RU_IDENTITYLINK - add constraint ACT_FK_ATHRZ_PROCEDEF - foreign key (PROC_DEF_ID_) - references ACT_RE_PROCDEF; - -alter table ACT_RU_TASK - add constraint ACT_FK_TASK_EXE - foreign key (EXECUTION_ID_) - references ACT_RU_EXECUTION; - -alter table ACT_RU_TASK - add constraint ACT_FK_TASK_PROCINST - foreign key (PROC_INST_ID_) - references ACT_RU_EXECUTION; - -alter table ACT_RU_TASK - add constraint ACT_FK_TASK_PROCDEF - foreign key (PROC_DEF_ID_) - references ACT_RE_PROCDEF; - -alter table ACT_RU_VARIABLE - add constraint ACT_FK_VAR_EXE - foreign key (EXECUTION_ID_) - references ACT_RU_EXECUTION; - -alter table ACT_RU_VARIABLE - add constraint ACT_FK_VAR_PROCINST - foreign key (PROC_INST_ID_) - references ACT_RU_EXECUTION; - -alter table ACT_RU_VARIABLE - add constraint ACT_FK_VAR_BYTEARRAY - foreign key (BYTEARRAY_ID_) - references ACT_GE_BYTEARRAY; - -alter table ACT_RU_JOB - add constraint ACT_FK_JOB_EXCEPTION - foreign key (EXCEPTION_STACK_ID_) - references ACT_GE_BYTEARRAY; - -alter table ACT_RU_EVENT_SUBSCR - add constraint ACT_FK_EVENT_EXEC - foreign key (EXECUTION_ID_) - references ACT_RU_EXECUTION; - -alter table ACT_RE_MODEL - add constraint ACT_FK_MODEL_SOURCE - foreign key (EDITOR_SOURCE_VALUE_ID_) - references ACT_GE_BYTEARRAY (ID_); - -alter table ACT_RE_MODEL - add constraint ACT_FK_MODEL_SOURCE_EXTRA - foreign key (EDITOR_SOURCE_EXTRA_VALUE_ID_) - references ACT_GE_BYTEARRAY (ID_); - -alter table ACT_RE_MODEL - add constraint ACT_FK_MODEL_DEPLOYMENT - foreign key (DEPLOYMENT_ID_) - references ACT_RE_DEPLOYMENT (ID_); diff --git a/src/main/resources/sql/h2/create/activiti.h2.create.history.sql b/src/main/resources/sql/h2/create/activiti.h2.create.history.sql deleted file mode 100644 index 7fbdf40fab..0000000000 --- a/src/main/resources/sql/h2/create/activiti.h2.create.history.sql +++ /dev/null @@ -1,132 +0,0 @@ -create table ACT_HI_PROCINST ( - ID_ varchar(64) not null, - PROC_INST_ID_ varchar(64) not null, - BUSINESS_KEY_ varchar(255), - PROC_DEF_ID_ varchar(64) not null, - START_TIME_ timestamp not null, - END_TIME_ timestamp, - DURATION_ bigint, - START_USER_ID_ varchar(255), - START_ACT_ID_ varchar(255), - END_ACT_ID_ varchar(255), - SUPER_PROCESS_INSTANCE_ID_ varchar(64), - DELETE_REASON_ varchar(4000), - primary key (ID_), - unique (PROC_INST_ID_) -); - -create table ACT_HI_ACTINST ( - ID_ varchar(64) not null, - PROC_DEF_ID_ varchar(64) not null, - PROC_INST_ID_ varchar(64) not null, - EXECUTION_ID_ varchar(64) not null, - ACT_ID_ varchar(255) not null, - TASK_ID_ varchar(64), - CALL_PROC_INST_ID_ varchar(64), - ACT_NAME_ varchar(255), - ACT_TYPE_ varchar(255) not null, - ASSIGNEE_ varchar(64), - START_TIME_ timestamp not null, - END_TIME_ timestamp, - DURATION_ bigint, - primary key (ID_) -); - -create table ACT_HI_TASKINST ( - ID_ varchar(64) not null, - PROC_DEF_ID_ varchar(64), - TASK_DEF_KEY_ varchar(255), - PROC_INST_ID_ varchar(64), - EXECUTION_ID_ varchar(64), - NAME_ varchar(255), - PARENT_TASK_ID_ varchar(64), - DESCRIPTION_ varchar(4000), - OWNER_ varchar(255), - ASSIGNEE_ varchar(255), - START_TIME_ timestamp not null, - END_TIME_ timestamp, - DURATION_ bigint, - DELETE_REASON_ varchar(4000), - PRIORITY_ integer, - DUE_DATE_ timestamp, - primary key (ID_) -); - -create table ACT_HI_VARINST ( - ID_ varchar(64) not null, - PROC_INST_ID_ varchar(64), - EXECUTION_ID_ varchar(64), - TASK_ID_ varchar(64), - NAME_ varchar(255) not null, - VAR_TYPE_ varchar(100), - REV_ integer, - BYTEARRAY_ID_ varchar(64), - DOUBLE_ double, - LONG_ bigint, - TEXT_ varchar(4000), - TEXT2_ varchar(4000), - primary key (ID_) -); - -create table ACT_HI_DETAIL ( - ID_ varchar(64) not null, - TYPE_ varchar(255) not null, - TIME_ timestamp not null, - NAME_ varchar(255), - PROC_INST_ID_ varchar(64), - EXECUTION_ID_ varchar(64), - TASK_ID_ varchar(64), - ACT_INST_ID_ varchar(64), - VAR_TYPE_ varchar(255), - REV_ integer, - BYTEARRAY_ID_ varchar(64), - DOUBLE_ double, - LONG_ bigint, - TEXT_ varchar(4000), - TEXT2_ varchar(4000), - primary key (ID_) -); - -create table ACT_HI_COMMENT ( - ID_ varchar(64) not null, - TYPE_ varchar(255), - TIME_ timestamp not null, - USER_ID_ varchar(255), - TASK_ID_ varchar(64), - PROC_INST_ID_ varchar(64), - ACTION_ varchar(255), - MESSAGE_ varchar(4000), - FULL_MSG_ longvarbinary, - primary key (ID_) -); - -create table ACT_HI_ATTACHMENT ( - ID_ varchar(64) not null, - REV_ integer, - USER_ID_ varchar(255), - NAME_ varchar(255), - DESCRIPTION_ varchar(4000), - TYPE_ varchar(255), - TASK_ID_ varchar(64), - PROC_INST_ID_ varchar(64), - URL_ varchar(4000), - CONTENT_ID_ varchar(64), - primary key (ID_) -); - -create index ACT_IDX_HI_PRO_INST_END on ACT_HI_PROCINST(END_TIME_); -create index ACT_IDX_HI_PRO_I_BUSKEY on ACT_HI_PROCINST(BUSINESS_KEY_); -create index ACT_IDX_HI_ACT_INST_START on ACT_HI_ACTINST(START_TIME_); -create index ACT_IDX_HI_ACT_INST_END on ACT_HI_ACTINST(END_TIME_); -create index ACT_IDX_HI_DETAIL_PROC_INST on ACT_HI_DETAIL(PROC_INST_ID_); -create index ACT_IDX_HI_DETAIL_ACT_INST on ACT_HI_DETAIL(ACT_INST_ID_); -create index ACT_IDX_HI_DETAIL_TIME on ACT_HI_DETAIL(TIME_); -create index ACT_IDX_HI_DETAIL_NAME on ACT_HI_DETAIL(NAME_); -create index ACT_IDX_HI_DETAIL_TASK_ID on ACT_HI_DETAIL(TASK_ID_); -create index ACT_IDX_HI_PROCVAR_PROC_INST on ACT_HI_VARINST(PROC_INST_ID_); -create index ACT_IDX_HI_PROCVAR_NAME_TYPE on ACT_HI_VARINST(NAME_, VAR_TYPE_); -create index ACT_IDX_HI_ACT_INST_PROCINST on ACT_HI_ACTINST(PROC_INST_ID_, ACT_ID_); - -alter table ACT_HI_PROCINST - add constraint ACT_UNIQ_HI_BUS_KEY - unique(PROC_DEF_ID_, BUSINESS_KEY_); diff --git a/src/main/resources/sql/h2/create/activiti.h2.create.identity.sql b/src/main/resources/sql/h2/create/activiti.h2.create.identity.sql deleted file mode 100644 index 80c03fbe7d..0000000000 --- a/src/main/resources/sql/h2/create/activiti.h2.create.identity.sql +++ /dev/null @@ -1,46 +0,0 @@ -create table ACT_ID_GROUP ( - ID_ varchar(64), - REV_ integer, - NAME_ varchar(255), - TYPE_ varchar(255), - primary key (ID_) -); - -create table ACT_ID_MEMBERSHIP ( - USER_ID_ varchar(64), - GROUP_ID_ varchar(64), - primary key (USER_ID_, GROUP_ID_) -); - -create table ACT_ID_USER ( - ID_ varchar(64), - REV_ integer, - FIRST_ varchar(255), - LAST_ varchar(255), - EMAIL_ varchar(255), - PWD_ varchar(255), - PICTURE_ID_ varchar(64), - primary key (ID_) -); - -create table ACT_ID_INFO ( - ID_ varchar(64), - REV_ integer, - USER_ID_ varchar(64), - TYPE_ varchar(64), - KEY_ varchar(255), - VALUE_ varchar(255), - PASSWORD_ longvarbinary, - PARENT_ID_ varchar(255), - primary key (ID_) -); - -alter table ACT_ID_MEMBERSHIP - add constraint ACT_FK_MEMB_GROUP - foreign key (GROUP_ID_) - references ACT_ID_GROUP; - -alter table ACT_ID_MEMBERSHIP - add constraint ACT_FK_MEMB_USER - foreign key (USER_ID_) - references ACT_ID_USER; diff --git a/src/main/resources/sql/h2/data.sql b/src/main/resources/sql/h2/data.sql deleted file mode 100644 index 887416c688..0000000000 --- a/src/main/resources/sql/h2/data.sql +++ /dev/null @@ -1,23 +0,0 @@ -insert into ACT_ID_GROUP values ('admin', 1, '管理员', 'security-role'); -insert into ACT_ID_GROUP values ('user', 1, '用户', 'security-role'); -insert into ACT_ID_GROUP values ('deptLeader', 1, '部门领导', 'assignment'); -insert into ACT_ID_GROUP values ('hr', 1, '人事', 'assignment'); - -insert into ACT_ID_USER values ('admin', 1, 'Admin', 'Kad', 'admin@kad.com', '000000', ''); -insert into ACT_ID_MEMBERSHIP values ('admin', 'user'); -insert into ACT_ID_MEMBERSHIP values ('admin', 'admin'); - -insert into ACT_ID_USER values ('kafeitu', 1, 'Henry', 'Yan', 'yanhonglei@gmail.com', '000000', ''); -insert into ACT_ID_MEMBERSHIP values ('kafeitu', 'admin'); - -insert into ACT_ID_USER values ('hruser', 1, 'Lili', 'Zhang', 'hr@gmail.com', '000000', ''); -insert into ACT_ID_MEMBERSHIP values ('hruser', 'user'); -insert into ACT_ID_MEMBERSHIP values ('hruser', 'hr'); - -insert into ACT_ID_USER values ('leaderuser', 1, 'Jhon', 'Li', 'leader@gmail.com', '000000', ''); -insert into ACT_ID_MEMBERSHIP values ('leaderuser', 'user'); -insert into ACT_ID_MEMBERSHIP values ('leaderuser', 'deptLeader'); - -update ACT_GE_PROPERTY -set VALUE_ = '10' -where NAME_ = 'next.dbid'; \ No newline at end of file diff --git a/src/main/resources/sql/h2/drop/activiti.h2.drop.engine.sql b/src/main/resources/sql/h2/drop/activiti.h2.drop.engine.sql deleted file mode 100644 index 98e70d9328..0000000000 --- a/src/main/resources/sql/h2/drop/activiti.h2.drop.engine.sql +++ /dev/null @@ -1,80 +0,0 @@ -drop index ACT_IDX_EXEC_BUSKEY; -drop index ACT_IDX_TASK_CREATE; -drop index ACT_IDX_IDENT_LNK_USER; -drop index ACT_IDX_IDENT_LNK_GROUP; -drop index ACT_IDX_VARIABLE_TASK_ID; - -alter table ACT_GE_BYTEARRAY - drop constraint ACT_FK_BYTEARR_DEPL; - -alter table ACT_RU_EXECUTION - drop constraint ACT_FK_EXE_PROCINST; - -alter table ACT_RU_EXECUTION - drop constraint ACT_FK_EXE_PARENT; - -alter table ACT_RU_EXECUTION - drop constraint ACT_FK_EXE_SUPER; - -alter table ACT_RU_EXECUTION - drop constraint ACT_FK_EXE_PROCDEF; - -alter table ACT_RU_EXECUTION - drop constraint ACT_UNIQ_RU_BUS_KEY; - -alter table ACT_RU_IDENTITYLINK - drop constraint ACT_FK_TSKASS_TASK; - -alter table ACT_RU_IDENTITYLINK - drop constraint ACT_FK_ATHRZ_PROCEDEF; - -alter table ACT_RU_TASK - drop constraint ACT_FK_TASK_EXE; - -alter table ACT_RU_TASK - drop constraint ACT_FK_TASK_PROCINST; - -alter table ACT_RU_TASK - drop constraint ACT_FK_TASK_PROCDEF; - -alter table ACT_RU_VARIABLE - drop constraint ACT_FK_VAR_EXE; - -alter table ACT_RU_VARIABLE - drop constraint ACT_FK_VAR_PROCINST; - -alter table ACT_RU_VARIABLE - drop constraint ACT_FK_VAR_BYTEARRAY; - -alter table ACT_RU_JOB - drop constraint ACT_FK_JOB_EXCEPTION; - -alter table ACT_RU_EVENT_SUBSCR - drop constraint ACT_FK_EVENT_EXEC; - -alter table ACT_RE_PROCDEF - drop constraint ACT_UNIQ_PROCDEF; - -alter table ACT_RE_MODEL - drop constraint ACT_FK_MODEL_SOURCE; - -alter table ACT_RE_MODEL - drop constraint ACT_FK_MODEL_SOURCE_EXTRA; - -alter table ACT_RE_MODEL - drop constraint ACT_FK_MODEL_DEPLOYMENT; - -drop index ACT_IDX_EVENT_SUBSCR_CONFIG_; -drop index ACT_IDX_ATHRZ_PROCEDEF; - -drop table ACT_GE_PROPERTY if exists; -drop table ACT_GE_BYTEARRAY if exists; -drop table ACT_RE_DEPLOYMENT if exists; -drop table ACT_RE_MODEL if exists; -drop table ACT_RU_EXECUTION if exists; -drop table ACT_RU_JOB if exists; -drop table ACT_RE_PROCDEF if exists; -drop table ACT_RU_TASK if exists; -drop table ACT_RU_IDENTITYLINK if exists; -drop table ACT_RU_VARIABLE if exists; -drop table ACT_RU_EVENT_SUBSCR if exists; diff --git a/src/main/resources/sql/h2/drop/activiti.h2.drop.history.sql b/src/main/resources/sql/h2/drop/activiti.h2.drop.history.sql deleted file mode 100644 index 936591335e..0000000000 --- a/src/main/resources/sql/h2/drop/activiti.h2.drop.history.sql +++ /dev/null @@ -1,23 +0,0 @@ -drop index ACT_IDX_HI_PRO_INST_END; -drop index ACT_IDX_HI_PRO_I_BUSKEY; -drop index ACT_IDX_HI_ACT_INST_START; -drop index ACT_IDX_HI_ACT_INST_END; -drop index ACT_IDX_HI_DETAIL_PROC_INST; -drop index ACT_IDX_HI_DETAIL_ACT_INST; -drop index ACT_IDX_HI_DETAIL_TIME; -drop index ACT_IDX_HI_DETAIL_NAME; -drop index ACT_IDX_HI_DETAIL_TASK_ID; -drop index ACT_IDX_HI_PROCVAR_PROC_INST; -drop index ACT_IDX_HI_PROCVAR_NAME_TYPE; -drop index ACT_IDX_HI_ACT_INST_PROCINST; - -alter table ACT_HI_PROCINST - drop constraint ACT_UNIQ_HI_BUS_KEY; - -drop table ACT_HI_PROCINST if exists; -drop table ACT_HI_ACTINST if exists; -drop table ACT_HI_VARINST if exists; -drop table ACT_HI_TASKINST if exists; -drop table ACT_HI_DETAIL if exists; -drop table ACT_HI_COMMENT if exists; -drop table ACT_HI_ATTACHMENT if exists; diff --git a/src/main/resources/sql/h2/drop/activiti.h2.drop.identity.sql b/src/main/resources/sql/h2/drop/activiti.h2.drop.identity.sql deleted file mode 100644 index 8290d1d168..0000000000 --- a/src/main/resources/sql/h2/drop/activiti.h2.drop.identity.sql +++ /dev/null @@ -1,10 +0,0 @@ -alter table ACT_ID_MEMBERSHIP - drop constraint ACT_FK_MEMB_GROUP; - -alter table ACT_ID_MEMBERSHIP - drop constraint ACT_FK_MEMB_USER; - -drop table ACT_ID_INFO if exists; -drop table ACT_ID_GROUP if exists; -drop table ACT_ID_MEMBERSHIP if exists; -drop table ACT_ID_USER if exists; diff --git a/src/main/resources/sql/h2/schema.sql b/src/main/resources/sql/h2/schema.sql deleted file mode 100644 index 980adad505..0000000000 --- a/src/main/resources/sql/h2/schema.sql +++ /dev/null @@ -1,48 +0,0 @@ -drop table OA_LEAVE if exists; -create table OA_LEAVE -( - ID bigint generated by default as identity not null, - PROCESS_INSTANCE_ID VARCHAR2(64), - USER_ID VARCHAR2(20) not null, - START_TIME TIMESTAMP not null, - END_TIME TIMESTAMP not null, - LEAVE_TYPE VARCHAR2(20), - REASON VARCHAR2(2000), - APPLY_TIME TIMESTAMP not null, - REALITY_START_TIME TIMESTAMP, - REALITY_END_TIME TIMESTAMP, - constraint PK_OA_LEAVE primary key (ID) -); - -comment on table OA_LEAVE is -'请假'; - -comment on column OA_LEAVE.ID is -'ID'; - -comment on column OA_LEAVE.PROCESS_INSTANCE_ID is -'流程ID'; - -comment on column OA_LEAVE.USER_ID is -'工号'; - -comment on column OA_LEAVE.START_TIME is -'开始时间'; - -comment on column OA_LEAVE.END_TIME is -'结束时间'; - -comment on column OA_LEAVE.LEAVE_TYPE is -'假种'; - -comment on column OA_LEAVE.REASON is -'请假事由'; - -comment on column OA_LEAVE.APPLY_TIME is -'申请时间'; - -comment on column OA_LEAVE.REALITY_START_TIME is -'实际开始时间'; - -comment on column OA_LEAVE.REALITY_END_TIME is -'实际结束时间'; \ No newline at end of file diff --git a/src/main/resources/sql/mysql/create/activiti.mysql.create.engine.sql b/src/main/resources/sql/mysql/create/activiti.mysql.create.engine.sql deleted file mode 100644 index 30cfcc7398..0000000000 --- a/src/main/resources/sql/mysql/create/activiti.mysql.create.engine.sql +++ /dev/null @@ -1,266 +0,0 @@ -create table ACT_GE_PROPERTY ( - NAME_ varchar(64), - VALUE_ varchar(300), - REV_ integer, - primary key (NAME_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -insert into ACT_GE_PROPERTY -values ('schema.version', '5.11', 1); - -insert into ACT_GE_PROPERTY -values ('schema.history', 'create(5.11)', 1); - -insert into ACT_GE_PROPERTY -values ('next.dbid', '1', 1); - -create table ACT_GE_BYTEARRAY ( - ID_ varchar(64), - REV_ integer, - NAME_ varchar(255), - DEPLOYMENT_ID_ varchar(64), - BYTES_ LONGBLOB, - GENERATED_ TINYINT, - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_RE_DEPLOYMENT ( - ID_ varchar(64), - NAME_ varchar(255), - CATEGORY_ varchar(255), - DEPLOY_TIME_ timestamp, - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_RE_MODEL ( - ID_ varchar(64) not null, - REV_ integer, - NAME_ varchar(255), - KEY_ varchar(255), - CATEGORY_ varchar(255), - CREATE_TIME_ timestamp, - LAST_UPDATE_TIME_ timestamp, - VERSION_ integer, - META_INFO_ varchar(4000), - DEPLOYMENT_ID_ varchar(64), - EDITOR_SOURCE_VALUE_ID_ varchar(64), - EDITOR_SOURCE_EXTRA_VALUE_ID_ varchar(64), - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_RU_EXECUTION ( - ID_ varchar(64), - REV_ integer, - PROC_INST_ID_ varchar(64), - BUSINESS_KEY_ varchar(255), - PARENT_ID_ varchar(64), - PROC_DEF_ID_ varchar(64), - SUPER_EXEC_ varchar(64), - ACT_ID_ varchar(255), - IS_ACTIVE_ TINYINT, - IS_CONCURRENT_ TINYINT, - IS_SCOPE_ TINYINT, - IS_EVENT_SCOPE_ TINYINT, - SUSPENSION_STATE_ integer, - CACHED_ENT_STATE_ integer, - primary key (ID_), - unique ACT_UNIQ_RU_BUS_KEY (PROC_DEF_ID_, BUSINESS_KEY_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_RU_JOB ( - ID_ varchar(64) NOT NULL, - REV_ integer, - TYPE_ varchar(255) NOT NULL, - LOCK_EXP_TIME_ timestamp NULL, - LOCK_OWNER_ varchar(255), - EXCLUSIVE_ boolean, - EXECUTION_ID_ varchar(64), - PROCESS_INSTANCE_ID_ varchar(64), - PROC_DEF_ID_ varchar(64), - RETRIES_ integer, - EXCEPTION_STACK_ID_ varchar(64), - EXCEPTION_MSG_ varchar(4000), - DUEDATE_ timestamp NULL, - REPEAT_ varchar(255), - HANDLER_TYPE_ varchar(255), - HANDLER_CFG_ varchar(4000), - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_RE_PROCDEF ( - 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), - DESCRIPTION_ varchar(4000), - HAS_START_FORM_KEY_ TINYINT, - SUSPENSION_STATE_ integer, - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_RU_TASK ( - ID_ varchar(64), - REV_ integer, - EXECUTION_ID_ varchar(64), - PROC_INST_ID_ varchar(64), - PROC_DEF_ID_ varchar(64), - NAME_ varchar(255), - PARENT_TASK_ID_ varchar(64), - DESCRIPTION_ varchar(4000), - TASK_DEF_KEY_ varchar(255), - OWNER_ varchar(255), - ASSIGNEE_ varchar(255), - DELEGATION_ varchar(64), - PRIORITY_ integer, - CREATE_TIME_ timestamp, - DUE_DATE_ datetime, - SUSPENSION_STATE_ integer, - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_RU_IDENTITYLINK ( - ID_ varchar(64), - REV_ integer, - GROUP_ID_ varchar(255), - TYPE_ varchar(255), - USER_ID_ varchar(255), - TASK_ID_ varchar(64), - PROC_DEF_ID_ varchar(64), - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_RU_VARIABLE ( - ID_ varchar(64) not null, - REV_ integer, - TYPE_ varchar(255) not null, - NAME_ varchar(255) not null, - EXECUTION_ID_ varchar(64), - PROC_INST_ID_ varchar(64), - TASK_ID_ varchar(64), - 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 table ACT_RU_EVENT_SUBSCR ( - ID_ varchar(64) not null, - REV_ integer, - EVENT_TYPE_ varchar(255) not null, - EVENT_NAME_ varchar(255), - EXECUTION_ID_ varchar(64), - PROC_INST_ID_ varchar(64), - ACTIVITY_ID_ varchar(64), - CONFIGURATION_ varchar(255), - CREATED_ timestamp not null, - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION(BUSINESS_KEY_); -create index ACT_IDX_TASK_CREATE on ACT_RU_TASK(CREATE_TIME_); -create index ACT_IDX_IDENT_LNK_USER on ACT_RU_IDENTITYLINK(USER_ID_); -create index ACT_IDX_IDENT_LNK_GROUP on ACT_RU_IDENTITYLINK(GROUP_ID_); -create index ACT_IDX_EVENT_SUBSCR_CONFIG_ on ACT_RU_EVENT_SUBSCR(CONFIGURATION_); -create index ACT_IDX_VARIABLE_TASK_ID on ACT_RU_VARIABLE(TASK_ID_); -create index ACT_IDX_ATHRZ_PROCEDEF on ACT_RU_IDENTITYLINK(PROC_DEF_ID_); - -alter table ACT_GE_BYTEARRAY - add constraint ACT_FK_BYTEARR_DEPL - foreign key (DEPLOYMENT_ID_) - references ACT_RE_DEPLOYMENT (ID_); - -alter table ACT_RE_PROCDEF - add constraint ACT_UNIQ_PROCDEF - unique (KEY_,VERSION_); - -alter table ACT_RU_EXECUTION - add constraint ACT_FK_EXE_PROCINST - foreign key (PROC_INST_ID_) - references ACT_RU_EXECUTION (ID_) on delete cascade on update cascade; - -alter table ACT_RU_EXECUTION - add constraint ACT_FK_EXE_PARENT - foreign key (PARENT_ID_) - references ACT_RU_EXECUTION (ID_); - -alter table ACT_RU_EXECUTION - add constraint ACT_FK_EXE_SUPER - foreign key (SUPER_EXEC_) - references ACT_RU_EXECUTION (ID_); - -alter table ACT_RU_EXECUTION - add constraint ACT_FK_EXE_PROCDEF - foreign key (PROC_DEF_ID_) - references ACT_RE_PROCDEF (ID_); - -alter table ACT_RU_IDENTITYLINK - add constraint ACT_FK_TSKASS_TASK - foreign key (TASK_ID_) - references ACT_RU_TASK (ID_); - -alter table ACT_RU_IDENTITYLINK - add constraint ACT_FK_ATHRZ_PROCEDEF - foreign key (PROC_DEF_ID_) - references ACT_RE_PROCDEF(ID_); - -alter table ACT_RU_TASK - add constraint ACT_FK_TASK_EXE - foreign key (EXECUTION_ID_) - references ACT_RU_EXECUTION (ID_); - -alter table ACT_RU_TASK - add constraint ACT_FK_TASK_PROCINST - foreign key (PROC_INST_ID_) - references ACT_RU_EXECUTION (ID_); - -alter table ACT_RU_TASK - add constraint ACT_FK_TASK_PROCDEF - foreign key (PROC_DEF_ID_) - references ACT_RE_PROCDEF (ID_); - -alter table ACT_RU_VARIABLE - add constraint ACT_FK_VAR_EXE - foreign key (EXECUTION_ID_) - references ACT_RU_EXECUTION (ID_); - -alter table ACT_RU_VARIABLE - add constraint ACT_FK_VAR_PROCINST - foreign key (PROC_INST_ID_) - references ACT_RU_EXECUTION(ID_); - -alter table ACT_RU_VARIABLE - add constraint ACT_FK_VAR_BYTEARRAY - foreign key (BYTEARRAY_ID_) - references ACT_GE_BYTEARRAY (ID_); - -alter table ACT_RU_JOB - add constraint ACT_FK_JOB_EXCEPTION - foreign key (EXCEPTION_STACK_ID_) - references ACT_GE_BYTEARRAY (ID_); - -alter table ACT_RU_EVENT_SUBSCR - add constraint ACT_FK_EVENT_EXEC - foreign key (EXECUTION_ID_) - references ACT_RU_EXECUTION(ID_); - -alter table ACT_RE_MODEL - add constraint ACT_FK_MODEL_SOURCE - foreign key (EDITOR_SOURCE_VALUE_ID_) - references ACT_GE_BYTEARRAY (ID_); - -alter table ACT_RE_MODEL - add constraint ACT_FK_MODEL_SOURCE_EXTRA - foreign key (EDITOR_SOURCE_EXTRA_VALUE_ID_) - references ACT_GE_BYTEARRAY (ID_); - -alter table ACT_RE_MODEL - add constraint ACT_FK_MODEL_DEPLOYMENT - foreign key (DEPLOYMENT_ID_) - references ACT_RE_DEPLOYMENT (ID_); diff --git a/src/main/resources/sql/mysql/create/activiti.mysql.create.history.sql b/src/main/resources/sql/mysql/create/activiti.mysql.create.history.sql deleted file mode 100644 index 327be5d385..0000000000 --- a/src/main/resources/sql/mysql/create/activiti.mysql.create.history.sql +++ /dev/null @@ -1,129 +0,0 @@ -create table ACT_HI_PROCINST ( - ID_ varchar(64) not null, - PROC_INST_ID_ varchar(64) not null, - BUSINESS_KEY_ varchar(255), - PROC_DEF_ID_ varchar(64) not null, - START_TIME_ datetime not null, - END_TIME_ datetime, - DURATION_ bigint, - START_USER_ID_ varchar(255), - START_ACT_ID_ varchar(255), - END_ACT_ID_ varchar(255), - SUPER_PROCESS_INSTANCE_ID_ varchar(64), - DELETE_REASON_ varchar(4000), - primary key (ID_), - unique (PROC_INST_ID_), - unique ACT_UNIQ_HI_BUS_KEY (PROC_DEF_ID_, BUSINESS_KEY_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_HI_ACTINST ( - ID_ varchar(64) not null, - PROC_DEF_ID_ varchar(64) not null, - PROC_INST_ID_ varchar(64) not null, - EXECUTION_ID_ varchar(64) not null, - ACT_ID_ varchar(255) not null, - TASK_ID_ varchar(64), - CALL_PROC_INST_ID_ varchar(64), - ACT_NAME_ varchar(255), - ACT_TYPE_ varchar(255) not null, - ASSIGNEE_ varchar(64), - START_TIME_ datetime not null, - END_TIME_ datetime, - DURATION_ bigint, - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_HI_TASKINST ( - ID_ varchar(64) not null, - PROC_DEF_ID_ varchar(64), - TASK_DEF_KEY_ varchar(255), - PROC_INST_ID_ varchar(64), - EXECUTION_ID_ varchar(64), - NAME_ varchar(255), - PARENT_TASK_ID_ varchar(64), - DESCRIPTION_ varchar(4000), - OWNER_ varchar(255), - ASSIGNEE_ varchar(255), - START_TIME_ datetime not null, - END_TIME_ datetime, - DURATION_ bigint, - DELETE_REASON_ varchar(4000), - PRIORITY_ integer, - DUE_DATE_ datetime, - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_HI_VARINST ( - ID_ varchar(64) not null, - PROC_INST_ID_ varchar(64), - EXECUTION_ID_ varchar(64), - TASK_ID_ varchar(64), - NAME_ varchar(255) not null, - VAR_TYPE_ varchar(100), - REV_ integer, - 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 table ACT_HI_DETAIL ( - ID_ varchar(64) not null, - TYPE_ varchar(255) not null, - PROC_INST_ID_ varchar(64), - EXECUTION_ID_ varchar(64), - TASK_ID_ varchar(64), - ACT_INST_ID_ varchar(64), - NAME_ varchar(255) not null, - VAR_TYPE_ varchar(255), - REV_ integer, - TIME_ datetime not null, - 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 table ACT_HI_COMMENT ( - ID_ varchar(64) not null, - TYPE_ varchar(255), - TIME_ datetime not null, - USER_ID_ varchar(255), - TASK_ID_ varchar(64), - PROC_INST_ID_ varchar(64), - ACTION_ varchar(255), - MESSAGE_ varchar(4000), - FULL_MSG_ LONGBLOB, - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_HI_ATTACHMENT ( - ID_ varchar(64) not null, - REV_ integer, - USER_ID_ varchar(255), - NAME_ varchar(255), - DESCRIPTION_ varchar(4000), - TYPE_ varchar(255), - TASK_ID_ varchar(64), - PROC_INST_ID_ varchar(64), - URL_ varchar(4000), - CONTENT_ID_ varchar(64), - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create index ACT_IDX_HI_PRO_INST_END on ACT_HI_PROCINST(END_TIME_); -create index ACT_IDX_HI_PRO_I_BUSKEY on ACT_HI_PROCINST(BUSINESS_KEY_); -create index ACT_IDX_HI_ACT_INST_START on ACT_HI_ACTINST(START_TIME_); -create index ACT_IDX_HI_ACT_INST_END on ACT_HI_ACTINST(END_TIME_); -create index ACT_IDX_HI_DETAIL_PROC_INST on ACT_HI_DETAIL(PROC_INST_ID_); -create index ACT_IDX_HI_DETAIL_ACT_INST on ACT_HI_DETAIL(ACT_INST_ID_); -create index ACT_IDX_HI_DETAIL_TIME on ACT_HI_DETAIL(TIME_); -create index ACT_IDX_HI_DETAIL_NAME on ACT_HI_DETAIL(NAME_); -create index ACT_IDX_HI_DETAIL_TASK_ID on ACT_HI_DETAIL(TASK_ID_); -create index ACT_IDX_HI_PROCVAR_PROC_INST on ACT_HI_VARINST(PROC_INST_ID_); -create index ACT_IDX_HI_PROCVAR_NAME_TYPE on ACT_HI_VARINST(NAME_, VAR_TYPE_); -create index ACT_IDX_HI_ACT_INST_PROCINST on ACT_HI_ACTINST(PROC_INST_ID_, ACT_ID_); \ No newline at end of file diff --git a/src/main/resources/sql/mysql/create/activiti.mysql.create.identity.sql b/src/main/resources/sql/mysql/create/activiti.mysql.create.identity.sql deleted file mode 100644 index b65e5abfc5..0000000000 --- a/src/main/resources/sql/mysql/create/activiti.mysql.create.identity.sql +++ /dev/null @@ -1,46 +0,0 @@ -create table ACT_ID_GROUP ( - ID_ varchar(64), - REV_ integer, - NAME_ varchar(255), - TYPE_ varchar(255), - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_ID_MEMBERSHIP ( - USER_ID_ varchar(64), - GROUP_ID_ varchar(64), - primary key (USER_ID_, GROUP_ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_ID_USER ( - ID_ varchar(64), - REV_ integer, - FIRST_ varchar(255), - LAST_ varchar(255), - EMAIL_ varchar(255), - PWD_ varchar(255), - PICTURE_ID_ varchar(64), - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -create table ACT_ID_INFO ( - ID_ varchar(64), - REV_ integer, - USER_ID_ varchar(64), - TYPE_ varchar(64), - KEY_ varchar(255), - VALUE_ varchar(255), - PASSWORD_ LONGBLOB, - PARENT_ID_ varchar(255), - primary key (ID_) -) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin; - -alter table ACT_ID_MEMBERSHIP - add constraint ACT_FK_MEMB_GROUP - foreign key (GROUP_ID_) - references ACT_ID_GROUP (ID_); - -alter table ACT_ID_MEMBERSHIP - add constraint ACT_FK_MEMB_USER - foreign key (USER_ID_) - references ACT_ID_USER (ID_); diff --git a/src/main/resources/sql/mysql/data.sql b/src/main/resources/sql/mysql/data.sql deleted file mode 100644 index 887416c688..0000000000 --- a/src/main/resources/sql/mysql/data.sql +++ /dev/null @@ -1,23 +0,0 @@ -insert into ACT_ID_GROUP values ('admin', 1, '管理员', 'security-role'); -insert into ACT_ID_GROUP values ('user', 1, '用户', 'security-role'); -insert into ACT_ID_GROUP values ('deptLeader', 1, '部门领导', 'assignment'); -insert into ACT_ID_GROUP values ('hr', 1, '人事', 'assignment'); - -insert into ACT_ID_USER values ('admin', 1, 'Admin', 'Kad', 'admin@kad.com', '000000', ''); -insert into ACT_ID_MEMBERSHIP values ('admin', 'user'); -insert into ACT_ID_MEMBERSHIP values ('admin', 'admin'); - -insert into ACT_ID_USER values ('kafeitu', 1, 'Henry', 'Yan', 'yanhonglei@gmail.com', '000000', ''); -insert into ACT_ID_MEMBERSHIP values ('kafeitu', 'admin'); - -insert into ACT_ID_USER values ('hruser', 1, 'Lili', 'Zhang', 'hr@gmail.com', '000000', ''); -insert into ACT_ID_MEMBERSHIP values ('hruser', 'user'); -insert into ACT_ID_MEMBERSHIP values ('hruser', 'hr'); - -insert into ACT_ID_USER values ('leaderuser', 1, 'Jhon', 'Li', 'leader@gmail.com', '000000', ''); -insert into ACT_ID_MEMBERSHIP values ('leaderuser', 'user'); -insert into ACT_ID_MEMBERSHIP values ('leaderuser', 'deptLeader'); - -update ACT_GE_PROPERTY -set VALUE_ = '10' -where NAME_ = 'next.dbid'; \ No newline at end of file diff --git a/src/main/resources/sql/mysql/drop/activiti.mysql.drop.engine.sql b/src/main/resources/sql/mysql/drop/activiti.mysql.drop.engine.sql deleted file mode 100644 index 0a162e3b1e..0000000000 --- a/src/main/resources/sql/mysql/drop/activiti.mysql.drop.engine.sql +++ /dev/null @@ -1,74 +0,0 @@ -drop index ACT_IDX_EXEC_BUSKEY on ACT_RU_EXECUTION; -drop index ACT_IDX_TASK_CREATE on ACT_RU_TASK; -drop index ACT_IDX_IDENT_LNK_USER on ACT_RU_IDENTITYLINK; -drop index ACT_IDX_IDENT_LNK_GROUP on ACT_RU_IDENTITYLINK; -drop index ACT_IDX_VARIABLE_TASK_ID on ACT_RU_VARIABLE; - -alter table ACT_GE_BYTEARRAY - drop FOREIGN KEY ACT_FK_BYTEARR_DEPL; - -alter table ACT_RU_EXECUTION - drop FOREIGN KEY ACT_FK_EXE_PROCINST; - -alter table ACT_RU_EXECUTION - drop FOREIGN KEY ACT_FK_EXE_PARENT; - -alter table ACT_RU_EXECUTION - drop FOREIGN KEY ACT_FK_EXE_SUPER; - -alter table ACT_RU_EXECUTION - drop FOREIGN KEY ACT_FK_EXE_PROCDEF; - -alter table ACT_RU_IDENTITYLINK - drop FOREIGN KEY ACT_FK_TSKASS_TASK; - -alter table ACT_RU_IDENTITYLINK - drop FOREIGN KEY ACT_FK_ATHRZ_PROCEDEF; - -alter table ACT_RU_TASK - drop FOREIGN KEY ACT_FK_TASK_EXE; - -alter table ACT_RU_TASK - drop FOREIGN KEY ACT_FK_TASK_PROCINST; - -alter table ACT_RU_TASK - drop FOREIGN KEY ACT_FK_TASK_PROCDEF; - -alter table ACT_RU_VARIABLE - drop FOREIGN KEY ACT_FK_VAR_EXE; - -alter table ACT_RU_VARIABLE - drop FOREIGN KEY ACT_FK_VAR_PROCINST; - -alter table ACT_RU_VARIABLE - drop FOREIGN KEY ACT_FK_VAR_BYTEARRAY; - -alter table ACT_RU_JOB - drop FOREIGN KEY ACT_FK_JOB_EXCEPTION; - -alter table ACT_RU_EVENT_SUBSCR - drop FOREIGN KEY ACT_FK_EVENT_EXEC; - -alter table ACT_RE_MODEL - drop FOREIGN KEY ACT_FK_MODEL_SOURCE; - -alter table ACT_RE_MODEL - drop FOREIGN KEY ACT_FK_MODEL_SOURCE_EXTRA; - -alter table ACT_RE_MODEL - drop FOREIGN KEY ACT_FK_MODEL_DEPLOYMENT; - -drop index ACT_IDX_ATHRZ_PROCEDEF on ACT_RU_IDENTITYLINK; -drop index ACT_IDX_EVENT_SUBSCR_CONFIG_ on ACT_RU_EVENT_SUBSCR; - -drop table if exists ACT_GE_PROPERTY; -drop table if exists ACT_RU_VARIABLE; -drop table if exists ACT_GE_BYTEARRAY; -drop table if exists ACT_RE_DEPLOYMENT; -drop table if exists ACT_RE_MODEL; -drop table if exists ACT_RU_IDENTITYLINK; -drop table if exists ACT_RU_TASK; -drop table if exists ACT_RE_PROCDEF; -drop table if exists ACT_RU_EXECUTION; -drop table if exists ACT_RU_JOB; -drop table if exists ACT_RU_EVENT_SUBSCR; \ No newline at end of file diff --git a/src/main/resources/sql/mysql/drop/activiti.mysql.drop.history.sql b/src/main/resources/sql/mysql/drop/activiti.mysql.drop.history.sql deleted file mode 100644 index 4acf18eaac..0000000000 --- a/src/main/resources/sql/mysql/drop/activiti.mysql.drop.history.sql +++ /dev/null @@ -1,21 +0,0 @@ -drop index ACT_IDX_HI_PRO_INST_END on ACT_HI_PROCINST; -drop index ACT_IDX_HI_PRO_I_BUSKEY on ACT_HI_PROCINST; -drop index ACT_IDX_HI_ACT_INST_START on ACT_HI_ACTINST; -drop index ACT_IDX_HI_ACT_INST_END on ACT_HI_ACTINST; -drop index ACT_IDX_HI_DETAIL_PROC_INST on ACT_HI_DETAIL; -drop index ACT_IDX_HI_DETAIL_ACT_INST on ACT_HI_DETAIL; -drop index ACT_IDX_HI_DETAIL_TIME on ACT_HI_DETAIL; -drop index ACT_IDX_HI_DETAIL_NAME on ACT_HI_DETAIL; -drop index ACT_IDX_HI_DETAIL_TASK_ID on ACT_HI_DETAIL; -drop index ACT_IDX_HI_PROCVAR_PROC_INST on ACT_HI_VARINST; -drop index ACT_IDX_HI_PROCVAR_NAME_TYPE on ACT_HI_VARINST; -drop index ACT_IDX_HI_ACT_INST_PROCINST on ACT_HI_ACTINST; - -drop table if exists ACT_HI_PROCINST; -drop table if exists ACT_HI_ACTINST; -drop table if exists ACT_HI_VARINST; -drop table if exists ACT_HI_TASKINST; -drop table if exists ACT_HI_DETAIL; -drop table if exists ACT_HI_COMMENT; -drop table if exists ACT_HI_ATTACHMENT; - \ No newline at end of file diff --git a/src/main/resources/sql/mysql/drop/activiti.mysql.drop.identity.sql b/src/main/resources/sql/mysql/drop/activiti.mysql.drop.identity.sql deleted file mode 100644 index 3b404c4db4..0000000000 --- a/src/main/resources/sql/mysql/drop/activiti.mysql.drop.identity.sql +++ /dev/null @@ -1,10 +0,0 @@ -alter table ACT_ID_MEMBERSHIP - drop FOREIGN KEY ACT_FK_MEMB_GROUP; - -alter table ACT_ID_MEMBERSHIP - drop FOREIGN KEY ACT_FK_MEMB_USER; - -drop table if exists ACT_ID_INFO; -drop table if exists ACT_ID_MEMBERSHIP; -drop table if exists ACT_ID_GROUP; -drop table if exists ACT_ID_USER; diff --git a/src/main/resources/sql/mysql/schema.sql b/src/main/resources/sql/mysql/schema.sql deleted file mode 100644 index 980adad505..0000000000 --- a/src/main/resources/sql/mysql/schema.sql +++ /dev/null @@ -1,48 +0,0 @@ -drop table OA_LEAVE if exists; -create table OA_LEAVE -( - ID bigint generated by default as identity not null, - PROCESS_INSTANCE_ID VARCHAR2(64), - USER_ID VARCHAR2(20) not null, - START_TIME TIMESTAMP not null, - END_TIME TIMESTAMP not null, - LEAVE_TYPE VARCHAR2(20), - REASON VARCHAR2(2000), - APPLY_TIME TIMESTAMP not null, - REALITY_START_TIME TIMESTAMP, - REALITY_END_TIME TIMESTAMP, - constraint PK_OA_LEAVE primary key (ID) -); - -comment on table OA_LEAVE is -'请假'; - -comment on column OA_LEAVE.ID is -'ID'; - -comment on column OA_LEAVE.PROCESS_INSTANCE_ID is -'流程ID'; - -comment on column OA_LEAVE.USER_ID is -'工号'; - -comment on column OA_LEAVE.START_TIME is -'开始时间'; - -comment on column OA_LEAVE.END_TIME is -'结束时间'; - -comment on column OA_LEAVE.LEAVE_TYPE is -'假种'; - -comment on column OA_LEAVE.REASON is -'请假事由'; - -comment on column OA_LEAVE.APPLY_TIME is -'申请时间'; - -comment on column OA_LEAVE.REALITY_START_TIME is -'实际开始时间'; - -comment on column OA_LEAVE.REALITY_END_TIME is -'实际结束时间'; \ No newline at end of file diff --git a/src/main/resources/stencilset.json b/src/main/resources/stencilset.json new file mode 100644 index 0000000000..c15c6a6ecf --- /dev/null +++ b/src/main/resources/stencilset.json @@ -0,0 +1,1339 @@ +{ + "title" : "Process editor", + "namespace" : "http://b3mn.org/stencilset/bpmn2.0#", + "description" : "BPMN process editor", + "propertyPackages" : [ { + "name" : "process_idpackage", + "properties" : [ { + "id" : "process_id", + "type" : "String", + "title" : "Process identifier", + "value" : "process", + "description" : "Unique identifier of the process definition.", + "popular" : true + } ] + }, { + "name" : "overrideidpackage", + "properties" : [ { + "id" : "overrideid", + "type" : "String", + "title" : "Id", + "value" : "", + "description" : "Unique identifier of the element.", + "popular" : true + } ] + }, { + "name" : "namepackage", + "properties" : [ { + "id" : "name", + "type" : "String", + "title" : "Name", + "value" : "", + "description" : "The descriptive name of the BPMN element.", + "popular" : true, + "refToView" : "text_name" + } ] + }, { + "name" : "documentationpackage", + "properties" : [ { + "id" : "documentation", + "type" : "Text", + "title" : "Documentation", + "value" : "", + "description" : "The descriptive name of the BPMN element.", + "popular" : true + } ] + }, { + "name" : "process_authorpackage", + "properties" : [ { + "id" : "process_author", + "type" : "String", + "title" : "Process author", + "value" : "", + "description" : "Author of the process definition.", + "popular" : true + } ] + }, { + "name" : "process_versionpackage", + "properties" : [ { + "id" : "process_version", + "type" : "String", + "title" : "Process version string (documentation only)", + "value" : "", + "description" : "Version identifier for documentation purpose.", + "popular" : true + } ] + }, { + "name" : "process_namespacepackage", + "properties" : [ { + "id" : "process_namespace", + "type" : "String", + "title" : "Target namespace", + "value" : "http://www.activiti.org/processdef", + "description" : "Target namespace for the process definition.", + "popular" : true + } ] + }, { + "name" : "asynchronousdefinitionpackage", + "properties" : [ { + "id" : "asynchronousdefinition", + "type" : "Boolean", + "title" : "Asynchronous", + "value" : "false", + "description" : "Define the activity as asynchronous.", + "popular" : true + } ] + }, { + "name" : "exclusivedefinitionpackage", + "properties" : [ { + "id" : "exclusivedefinition", + "type" : "Boolean", + "title" : "Exclusive", + "value" : "false", + "description" : "Define the activity as exclusive.", + "popular" : true + } ] + }, { + "name" : "executionlistenerspackage", + "properties" : [ { + "id" : "executionlisteners", + "type" : "multiplecomplex", + "title" : "Execution listeners", + "value" : "", + "description" : "Listeners for an activity, process, sequence flow, start and end event.", + "popular" : true + } ] + }, { + "name" : "tasklistenerspackage", + "properties" : [ { + "id" : "tasklisteners", + "type" : "multiplecomplex", + "title" : "Task listeners", + "value" : "", + "description" : "Listeners for a user task", + "popular" : true + } ] + }, { + "name" : "eventlistenerspackage", + "properties" : [ { + "id" : "eventlisteners", + "type" : "multiplecomplex", + "title" : "Event listeners", + "value" : "", + "description" : "Listeners for any event happening in the Activiti Engine. It's also possible to rethrow the event as a signal, message or error event", + "popular" : true + } ] + }, { + "name" : "usertaskassignmentpackage", + "properties" : [ { + "id" : "usertaskassignment", + "type" : "Complex", + "title" : "Assignments", + "value" : "", + "description" : "Assignment definition for the user task", + "popular" : true + } ] + }, { + "name" : "formpropertiespackage", + "properties" : [ { + "id" : "formproperties", + "type" : "Complex", + "title" : "Form properties", + "value" : "", + "description" : "Definition of the form with a list of form properties", + "popular" : true + } ] + }, { + "name" : "formkeydefinitionpackage", + "properties" : [ { + "id" : "formkeydefinition", + "type" : "String", + "title" : "Form key", + "value" : "", + "description" : "Form key that provides a reference to a form.", + "popular" : true + } ] + }, { + "name" : "duedatedefinitionpackage", + "properties" : [ { + "id" : "duedatedefinition", + "type" : "String", + "title" : "Due date", + "value" : "", + "description" : "Due date of the user task.", + "popular" : true + } ] + }, { + "name" : "prioritydefinitionpackage", + "properties" : [ { + "id" : "prioritydefinition", + "type" : "String", + "title" : "Priority", + "value" : "", + "description" : "Priority of the user task.", + "popular" : true + } ] + }, { + "name" : "duedatedefinitionpackage", + "properties" : [ { + "id" : "duedatedefinition", + "type" : "String", + "title" : "Due date", + "value" : "", + "description" : "Due date of the user task.", + "popular" : true + } ] + }, { + "name" : "servicetaskclasspackage", + "properties" : [ { + "id" : "servicetaskclass", + "type" : "String", + "title" : "Class", + "value" : "", + "description" : "Class that implements the service task logic.", + "popular" : true + } ] + }, { + "name" : "servicetaskexpressionpackage", + "properties" : [ { + "id" : "servicetaskexpression", + "type" : "String", + "title" : "Expression", + "value" : "", + "description" : "Service task logic defined with an expression.", + "popular" : true + } ] + }, { + "name" : "servicetaskdelegateexpressionpackage", + "properties" : [ { + "id" : "servicetaskdelegateexpression", + "type" : "String", + "title" : "Delegate expression", + "value" : "", + "description" : "Service task logic defined with a delegate expression.", + "popular" : true + } ] + }, { + "name" : "servicetaskfieldspackage", + "properties" : [ { + "id" : "servicetaskfields", + "type" : "Complex", + "title" : "Class fields", + "value" : "", + "description" : "Field extensions", + "popular" : true + } ] + }, { + "name" : "servicetaskresultvariablepackage", + "properties" : [ { + "id" : "servicetaskresultvariable", + "type" : "String", + "title" : "Result variable name", + "value" : "", + "description" : "Process variable name to store the service task result.", + "popular" : true + } ] + }, { + "name" : "scriptformatpackage", + "properties" : [ { + "id" : "scriptformat", + "type" : "String", + "title" : "Script format", + "value" : "", + "description" : "Script format of the script task.", + "popular" : true + } ] + }, { + "name" : "scripttextpackage", + "properties" : [ { + "id" : "scripttext", + "type" : "Text", + "title" : "Script", + "value" : "", + "description" : "Script text of the script task.", + "popular" : true + } ] + }, { + "name" : "ruletask_rulespackage", + "properties" : [ { + "id" : "ruletask_rules", + "type" : "String", + "title" : "Rules", + "value" : "", + "description" : "Rules of the rule task.", + "popular" : true + } ] + }, { + "name" : "ruletask_variables_inputpackage", + "properties" : [ { + "id" : "ruletask_variables_input", + "type" : "String", + "title" : "Input variables", + "value" : "", + "description" : "Input variables of the rule task.", + "popular" : true + } ] + }, { + "name" : "ruletask_excludepackage", + "properties" : [ { + "id" : "ruletask_exclude", + "type" : "Boolean", + "title" : "Exclude", + "value" : "false", + "description" : "Use the rules property as exclusion.", + "popular" : true + } ] + }, { + "name" : "ruletask_resultpackage", + "properties" : [ { + "id" : "ruletask_result", + "type" : "String", + "title" : "Result variable", + "value" : "", + "description" : "Result variable of the rule task.", + "popular" : true + } ] + }, { + "name" : "mailtasktopackage", + "properties" : [ { + "id" : "mailtaskto", + "type" : "Text", + "title" : "To", + "value" : "", + "description" : "The recipients if the e-mail. Multiple recipients are defined in a comma-separated list.", + "popular" : true + } ] + }, { + "name" : "mailtaskfrompackage", + "properties" : [ { + "id" : "mailtaskfrom", + "type" : "Text", + "title" : "From", + "value" : "", + "description" : "The sender e-mail address. If not provided, the default configured from address is used.", + "popular" : true + } ] + }, { + "name" : "mailtasksubjectpackage", + "properties" : [ { + "id" : "mailtasksubject", + "type" : "Text", + "title" : "Subject", + "value" : "", + "description" : "The subject of the e-mail.", + "popular" : true + } ] + }, { + "name" : "mailtaskccpackage", + "properties" : [ { + "id" : "mailtaskcc", + "type" : "Text", + "title" : "Cc", + "value" : "", + "description" : "The cc's of the e-mail. Multiple recipients are defined in a comma-separated list", + "popular" : true + } ] + }, { + "name" : "mailtaskbccpackage", + "properties" : [ { + "id" : "mailtaskbcc", + "type" : "Text", + "title" : "Bcc", + "value" : "", + "description" : "The bcc's of the e-mail. Multiple recipients are defined in a comma-separated list", + "popular" : true + } ] + }, { + "name" : "mailtasktextpackage", + "properties" : [ { + "id" : "mailtasktext", + "type" : "Text", + "title" : "Text", + "value" : "", + "description" : "The content of the e-mail, in case one needs to send plain none-rich e-mails. Can be used in combination with html, for e-mail clients that don't support rich content. The client will then fall back to this text-only alternative.", + "popular" : true + } ] + }, { + "name" : "mailtaskhtmlpackage", + "properties" : [ { + "id" : "mailtaskhtml", + "type" : "Text", + "title" : "Html", + "value" : "", + "description" : "A piece of HTML that is the content of the e-mail.", + "popular" : true + } ] + }, { + "name" : "mailtaskcharsetpackage", + "properties" : [ { + "id" : "mailtaskcharset", + "type" : "String", + "title" : "Charset", + "value" : "", + "description" : "Allows to change the charset of the email, which is necessary for many non-English languages. ", + "popular" : true + } ] + }, { + "name" : "callactivitycalledelementpackage", + "properties" : [ { + "id" : "callactivitycalledelement", + "type" : "String", + "title" : "Called element", + "value" : "", + "description" : "Process reference.", + "popular" : true + } ] + }, { + "name" : "callactivityinparameterspackage", + "properties" : [ { + "id" : "callactivityinparameters", + "type" : "Complex", + "title" : "In parameters", + "value" : "", + "description" : "Definition of the input parameters", + "popular" : true + } ] + }, { + "name" : "callactivityoutparameterspackage", + "properties" : [ { + "id" : "callactivityoutparameters", + "type" : "Complex", + "title" : "Out parameters", + "value" : "", + "description" : "Definition of the output parameters", + "popular" : true + } ] + }, { + "name" : "cameltaskcamelcontextpackage", + "properties" : [ { + "id" : "cameltaskcamelcontext", + "type" : "String", + "title" : "Camel context", + "value" : "", + "description" : "An optional camel context definition, if left empty the default is used.", + "popular" : true + } ] + }, { + "name" : "muletaskendpointurlpackage", + "properties" : [ { + "id" : "muletaskendpointurl", + "type" : "String", + "title" : "Endpoint url", + "value" : "", + "description" : "A required endpoint url to sent the message to Mule.", + "popular" : true + } ] + }, { + "name" : "muletasklanguagepackage", + "properties" : [ { + "id" : "muletasklanguage", + "type" : "String", + "title" : "Language", + "value" : "", + "description" : "A required definition for the language to resolve the payload expression, like juel.", + "popular" : true + } ] + }, { + "name" : "muletaskpayloadexpressionpackage", + "properties" : [ { + "id" : "muletaskpayloadexpression", + "type" : "String", + "title" : "Payload expression", + "value" : "", + "description" : "A required definition for the payload of the message sent to Mule.", + "popular" : true + } ] + }, { + "name" : "muletaskresultvariablepackage", + "properties" : [ { + "id" : "muletaskresultvariable", + "type" : "String", + "title" : "Result variable", + "value" : "", + "description" : "An optional result variable for the payload returned.", + "popular" : true + } ] + }, { + "name" : "conditionsequenceflowpackage", + "properties" : [ { + "id" : "conditionsequenceflow", + "type" : "Complex", + "title" : "Flow condition", + "value" : "", + "description" : "The condition of the sequence flow", + "popular" : true + } ] + }, { + "name" : "defaultflowpackage", + "properties" : [ { + "id" : "defaultflow", + "type" : "Boolean", + "title" : "Default flow", + "value" : "false", + "description" : "Define the sequence flow as default", + "popular" : true, + "refToView" : "default" + } ] + }, { + "name" : "conditionalflowpackage", + "properties" : [ { + "id" : "conditionalflow", + "type" : "Boolean", + "title" : "Conditional flow", + "value" : "false", + "description" : "Define the sequence flow with a condition", + "popular" : true + } ] + }, { + "name" : "timercycledefinitionpackage", + "properties" : [ { + "id" : "timercycledefinition", + "type" : "String", + "title" : "Time cycle (e.g. R3/PT10H)", + "value" : "", + "description" : "Define the timer with a ISO-8601 cycle.", + "popular" : true + } ] + }, { + "name" : "timerdatedefinitionpackage", + "properties" : [ { + "id" : "timerdatedefinition", + "type" : "String", + "title" : "Time date in ISO-8601", + "value" : "", + "description" : "Define the timer with a ISO-8601 date definition.", + "popular" : true + } ] + }, { + "name" : "timerdurationdefinitionpackage", + "properties" : [ { + "id" : "timerdurationdefinition", + "type" : "String", + "title" : "Time duration (e.g. PT5M)", + "value" : "", + "description" : "Define the timer with a ISO-8601 duration.", + "popular" : true + } ] + }, { + "name" : "timerenddatedefinitionpackage", + "properties" : [ { + "id" : "timerenddatedefinition", + "type" : "String", + "title" : "Time End Date in ISO-8601", + "value" : "", + "description" : "Define the timer with a ISO-8601 duration.", + "popular" : true + } ] + }, { + "name" : "messagerefpackage", + "properties" : [ { + "id" : "messageref", + "type" : "String", + "title" : "Message reference", + "value" : "", + "description" : "Define the message name.", + "popular" : true + } ] + }, { + "name" : "signalrefpackage", + "properties" : [ { + "id" : "signalref", + "type" : "String", + "title" : "Signal reference", + "value" : "", + "description" : "Define the signal name.", + "popular" : true + } ] + }, { + "name" : "errorrefpackage", + "properties" : [ { + "id" : "errorref", + "type" : "String", + "title" : "Error reference", + "value" : "", + "description" : "Define the error name.", + "popular" : true + } ] + }, { + "name" : "cancelactivitypackage", + "properties" : [ { + "id" : "cancelactivity", + "type" : "Boolean", + "title" : "Cancel activity", + "value" : "true", + "description" : "Should the activity be cancelled", + "popular" : true, + "refToView" : [ "frame", "frame2" ] + } ] + }, { + "name" : "initiatorpackage", + "properties" : [ { + "id" : "initiator", + "type" : "String", + "title" : "Initiator", + "value" : "", + "description" : "Initiator of the process.", + "popular" : true + } ] + }, { + "name" : "textpackage", + "properties" : [ { + "id" : "text", + "type" : "String", + "title" : "Text", + "value" : "", + "description" : "The text of the text annotation.", + "popular" : true, + "refToView" : "text" + } ] + }, { + "name" : "multiinstance_typepackage", + "properties" : [ { + "id" : "multiinstance_type", + "type" : "kisbpm-multiinstance", + "title" : "Multi-instance type", + "value" : "None", + "description" : "Repeated activity execution (parallel or sequential) can be displayed through different loop types", + "popular" : true, + "refToView" : "multiinstance" + } ] + }, { + "name" : "multiinstance_cardinalitypackage", + "properties" : [ { + "id" : "multiinstance_cardinality", + "type" : "String", + "title" : "Cardinality (Multi-instance)", + "value" : "", + "description" : "Define the cardinality of multi instance.", + "popular" : true + } ] + }, { + "name" : "multiinstance_collectionpackage", + "properties" : [ { + "id" : "multiinstance_collection", + "type" : "String", + "title" : "Collection (Multi-instance)", + "value" : "", + "description" : "Define the collection for the multi instance.", + "popular" : true + } ] + }, { + "name" : "multiinstance_variablepackage", + "properties" : [ { + "id" : "multiinstance_variable", + "type" : "String", + "title" : "Element variable (Multi-instance)", + "value" : "", + "description" : "Define the element variable for the multi instance.", + "popular" : true + } ] + }, { + "name" : "multiinstance_conditionpackage", + "properties" : [ { + "id" : "multiinstance_condition", + "type" : "String", + "title" : "Completion condition (Multi-instance)", + "value" : "", + "description" : "Define the completion condition for the multi instance.", + "popular" : true + } ] + }, { + "name" : "isforcompensationpackage", + "properties" : [ { + "id" : "isforcompensation", + "type" : "Boolean", + "title" : "Is for compensation", + "value" : "false", + "description" : "A flag that identifies whether this activity is intended for the purposes of compensation.", + "popular" : true, + "refToView" : "compensation" + } ] + }, { + "name" : "sequencefloworderpackage", + "properties" : [ { + "id" : "sequencefloworder", + "type" : "Complex", + "title" : "Flow order", + "value" : "", + "description" : "Order outgoing sequence flows.", + "popular" : true + } ] + }, { + "name" : "signaldefinitionspackage", + "properties" : [ { + "id" : "signaldefinitions", + "type" : "multiplecomplex", + "title" : "Signal definitions", + "value" : "", + "description" : "Signal definitions", + "popular" : true + } ] + }, { + "name" : "messagedefinitionspackage", + "properties" : [ { + "id" : "messagedefinitions", + "type" : "multiplecomplex", + "title" : "Message definitions", + "value" : "", + "description" : "Message definitions", + "popular" : true + } ] + }, { + "name" : "istransactionpackage", + "properties" : [ { + "id" : "istransaction", + "type" : "Boolean", + "title" : "Is a transaction sub process", + "value" : "false", + "description" : "A flag that identifies whether this sub process is of type transaction.", + "popular" : true, + "refToView" : "border" + } ] + }, { + "name" : "terminateAllpackage", + "properties" : [ { + "id" : "terminateAll", + "type" : "Boolean", + "title" : "Terminate all", + "value" : "false", + "description" : "Enable to terminate the process instance", + "popular" : true + } ] + } ], + "stencils" : [ { + "type" : "node", + "id" : "BPMNDiagram", + "title" : "BPMN-Diagram", + "description" : "A BPMN 2.0 diagram.", + "view" : "\n\n \n \n \n \n \t\n \n", + "icon" : "diagram.png", + "groups" : [ "Diagram" ], + "mayBeRoot" : true, + "hide" : true, + "propertyPackages" : [ "process_idpackage", "namepackage", "documentationpackage", "process_authorpackage", "process_versionpackage", "process_namespacepackage", "executionlistenerspackage", "eventlistenerspackage", "signaldefinitionspackage", "messagedefinitionspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ ] + }, { + "type" : "node", + "id" : "StartNoneEvent", + "title" : "Start event", + "description" : "A start event without a specific trigger", + "view" : "\n\n \n \n \t\n \n \n \n\t\n \n", + "icon" : "startevent/none.png", + "groups" : [ "Start Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "initiatorpackage", "formkeydefinitionpackage", "formpropertiespackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "StartTimerEvent", + "title" : "Start timer event", + "description" : "A start event with a timer trigger", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n\t\n \n", + "icon" : "startevent/timer.png", + "groups" : [ "Start Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "timercycledefinitionpackage", "timerdatedefinitionpackage", "timerdurationdefinitionpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "StartSignalEvent", + "title" : "Start signal event", + "description" : "A start event with a signal trigger", + "view" : "\n\n \n \n \t\n \n \n\n \n \n \n\t\n \n", + "icon" : "startevent/signal.png", + "groups" : [ "Start Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "signalrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "StartMessageEvent", + "title" : "Start message event", + "description" : "A start event with a message trigger", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n\t\n \n", + "icon" : "startevent/message.png", + "groups" : [ "Start Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "messagerefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "StartErrorEvent", + "title" : "Start error event", + "description" : "A start event that catches a thrown BPMN error", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", + "icon" : "startevent/error.png", + "groups" : [ "Start Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "errorrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "Startevents_all", "StartEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "UserTask", + "title" : "User task", + "description" : "A manual task assigned to a specific person", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.user.png", + "groups" : [ "Activities" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "usertaskassignmentpackage", "formkeydefinitionpackage", "duedatedefinitionpackage", "prioritydefinitionpackage", "formpropertiespackage", "tasklistenerspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "ServiceTask", + "title" : "Service task", + "description" : "An automatic task with service logic", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.service.png", + "groups" : [ "Activities" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "servicetaskclasspackage", "servicetaskexpressionpackage", "servicetaskdelegateexpressionpackage", "servicetaskfieldspackage", "servicetaskresultvariablepackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "ScriptTask", + "title" : "Script task", + "description" : "An automatic task with script logic", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.script.png", + "groups" : [ "Activities" ], + "propertyPackages" : [ "scriptformatpackage", "scripttextpackage", "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "BusinessRule", + "title" : "Business rule task", + "description" : "An automatic task with rule logic", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n \t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.business.rule.png", + "groups" : [ "Activities" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "ruletask_rulespackage", "ruletask_variables_inputpackage", "ruletask_excludepackage", "ruletask_resultpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "ReceiveTask", + "title" : "Receive task", + "description" : "An task that waits for a signal", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.receive.png", + "groups" : [ "Activities" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "ManualTask", + "title" : "Manual task", + "description" : "An automatic task with no logic", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n \t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.manual.png", + "groups" : [ "Activities" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "MailTask", + "title" : "Mail task", + "description" : "An mail task", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.send.png", + "groups" : [ "Activities" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "mailtasktopackage", "mailtaskfrompackage", "mailtasksubjectpackage", "mailtaskccpackage", "mailtaskbccpackage", "mailtasktextpackage", "mailtaskhtmlpackage", "mailtaskcharsetpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "CamelTask", + "title" : "Camel task", + "description" : "An task that sends a message to Camel", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.camel.png", + "groups" : [ "Activities" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "cameltaskcamelcontextpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "MuleTask", + "title" : "Mule task", + "description" : "An task that sends a message to Mule", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n\t\n\t\t\n\t\n\t\n\t\t\n\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.mule.png", + "groups" : [ "Activities" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage", "muletaskendpointurlpackage", "muletasklanguagepackage", "muletaskpayloadexpressionpackage", "muletaskresultvariablepackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "SendTask", + "title" : "Send task", + "description" : "An task that sends a message", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n\t\t\n\t\t\n \n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/list/type.send.png", + "groups" : [ "Activities" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "ActivitiesMorph", "all" ] + }, { + "type" : "node", + "id" : "SubProcess", + "title" : "Sub process", + "description" : "A sub process scope", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n \n\t\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\n\t\n\t\t\n\t\n \n", + "icon" : "activity/expanded.subprocess.png", + "groups" : [ "Structural" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "istransactionpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EventSubProcess", + "title" : "Event sub process", + "description" : "A event sub process scope", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \n \n\t\n\t\n \t\n\t\t\n \t\n\t\n\t\n \n", + "icon" : "activity/event.subprocess.png", + "groups" : [ "Structural" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "all" ] + }, { + "type" : "node", + "id" : "CallActivity", + "title" : "Call activity", + "description" : "A call activity", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \t\n \n \n\t\n \n\t\n\t\t\n\t\t\n \n\t\n\t\t\n\t\n\t\n\t\n\t\t\n\t\n\n\t\n\t\t\n\t\n \n", + "icon" : "activity/task.png", + "groups" : [ "Structural" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "executionlistenerspackage", "callactivitycalledelementpackage", "callactivityinparameterspackage", "callactivityoutparameterspackage", "multiinstance_typepackage", "multiinstance_cardinalitypackage", "multiinstance_collectionpackage", "multiinstance_variablepackage", "multiinstance_conditionpackage", "isforcompensationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "Activity", "sequence_start", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "ExclusiveGateway", + "title" : "Exclusive gateway", + "description" : "A choice gateway", + "view" : "\n\n \n \n \n \t\t\t\t\t\n \n \n \n \n \n \n \n\t\n\t\n\t\n \n\n", + "icon" : "gateway/exclusive.databased.png", + "groups" : [ "Gateways" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "ParallelGateway", + "title" : "Parallel gateway", + "description" : "A parallel gateway", + "view" : "\n\n \n \n \n \n \n \n \n \n\t\n\t\n \n\n", + "icon" : "gateway/parallel.png", + "groups" : [ "Gateways" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "InclusiveGateway", + "title" : "Inclusive gateway", + "description" : "An inclusive gateway", + "view" : "\n\n \n \n \n \n\n \n \n \n\t\n\t\n \n\n", + "icon" : "gateway/inclusive.png", + "groups" : [ "Gateways" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EventGateway", + "title" : "Event gateway", + "description" : "An event gateway", + "view" : "\n\n \n \n \n \n \n \t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\t\n\t\t\n\t\t\n\t\n\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\n\t\n\t\n\t\n\t\n\t\n \t\n\t\n\n", + "icon" : "gateway/eventbased.png", + "groups" : [ "Gateways" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "asynchronousdefinitionpackage", "exclusivedefinitionpackage", "sequencefloworderpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "GatewaysMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "BoundaryErrorEvent", + "title" : "Boundary error event", + "description" : "A boundary event that catches a BPMN error", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n\t\n \n", + "icon" : "catching/error.png", + "groups" : [ "Boundary Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "errorrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] + }, { + "type" : "node", + "id" : "BoundaryTimerEvent", + "title" : "Boundary timer event", + "description" : "A boundary event with a timer trigger", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n \n \n \t\n\t\n \n", + "icon" : "catching/timer.png", + "groups" : [ "Boundary Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "timercycledefinitionpackage", "timerdatedefinitionpackage", "timerdurationdefinitionpackage", "timerenddatedefinitionpackage", "cancelactivitypackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] + }, { + "type" : "node", + "id" : "BoundarySignalEvent", + "title" : "Boundary signal event", + "description" : "A boundary event with a signal trigger", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n\t\n\t\n \n", + "icon" : "catching/signal.png", + "groups" : [ "Boundary Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "signalrefpackage", "cancelactivitypackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] + }, { + "type" : "node", + "id" : "BoundaryMessageEvent", + "title" : "Boundary message event", + "description" : "A boundary event with a message trigger", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \t\n \n \n \n\t\n\t\t\n\t\n\t\n\t\n \n", + "icon" : "catching/message.png", + "groups" : [ "Boundary Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "messagerefpackage", "cancelactivitypackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] + }, { + "type" : "node", + "id" : "BoundaryCancelEvent", + "title" : "Boundary cancel event", + "description" : "A boundary cancel event", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n \n \n\t\n \n", + "icon" : "catching/cancel.png", + "groups" : [ "Boundary Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary" ] + }, { + "type" : "node", + "id" : "BoundaryCompensationEvent", + "title" : "Boundary compensation event", + "description" : "A boundary compensation event", + "view" : "\n\n \n \n \t\n \n \n \n\t\n \n \n \n \n \n\t\n \n", + "icon" : "catching/compensation.png", + "groups" : [ "Boundary Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "BoundaryEventsMorph", "IntermediateEventOnActivityBoundary", "all" ] + }, { + "type" : "node", + "id" : "CatchTimerEvent", + "title" : "Intermediate timer catching event", + "description" : "An intermediate catching event with a timer trigger", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n \n \n \t\n\t\n \n", + "icon" : "catching/timer.png", + "groups" : [ "Intermediate Catching Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "timercycledefinitionpackage", "timerdatedefinitionpackage", "timerdurationdefinitionpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "sequence_end", "CatchEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "CatchSignalEvent", + "title" : "Intermediate signal catching event", + "description" : "An intermediate catching event with a signal trigger", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \n \n \n\t\n\t\n \n", + "icon" : "catching/signal.png", + "groups" : [ "Intermediate Catching Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "signalrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "sequence_end", "CatchEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "CatchMessageEvent", + "title" : "Intermediate message catching event", + "description" : "An intermediate catching event with a message trigger", + "view" : "\n\n \n \n \t\n \n \n \n \n \t\n \n \t\n \n \n \n\t\n\t\t\n\t\n\t\n\t\n \n", + "icon" : "catching/message.png", + "groups" : [ "Intermediate Catching Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "messagerefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "sequence_start", "sequence_end", "CatchEventsMorph", "all" ] + }, { + "type" : "node", + "id" : "ThrowNoneEvent", + "title" : "Intermediate none throwing event", + "description" : "An intermediate event without a specific trigger", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", + "icon" : "throwing/none.png", + "groups" : [ "Intermediate Throwing Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ThrowEventsMorph", "sequence_start", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "ThrowSignalEvent", + "title" : "Intermediate signal throwing event", + "description" : "An intermediate event with a signal trigger", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", + "icon" : "throwing/signal.png", + "groups" : [ "Intermediate Throwing Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "signalrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ThrowEventsMorph", "sequence_start", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EndNoneEvent", + "title" : "End event", + "description" : "An end event without a specific trigger", + "view" : "\n\n \n \n \t\n \n \n \n\t\n \n", + "icon" : "endevent/none.png", + "groups" : [ "End Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "EndEventsMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EndErrorEvent", + "title" : "End error event", + "description" : "An end event that throws an error event", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", + "icon" : "endevent/error.png", + "groups" : [ "End Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "errorrefpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "EndEventsMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EndCancelEvent", + "title" : "End cancel event", + "description" : "A cancel end event", + "view" : "\n\n \n \n \t\n \n \n \n \n \n\t\n \n", + "icon" : "endevent/cancel.png", + "groups" : [ "End Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "EndEventsMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "EndTerminateEvent", + "title" : "End terminate event", + "description" : "A terminate end event", + "view" : "\n\n \n \n \t\n \n \n \n \n \n\t\n \n", + "icon" : "endevent/terminate.png", + "groups" : [ "End Events" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "executionlistenerspackage", "terminateAllpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "EndEventsMorph", "sequence_end", "all" ] + }, { + "type" : "node", + "id" : "Pool", + "title" : "Pool", + "description" : "A pool to stucture the process definition", + "view" : "\n\n \n \n \t\n \t\n \t\n \t\n \t\n \n \n \n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t \t\n \t\n \n \n\t\n\t\n\t\n\t\n \n \n \n", + "icon" : "swimlane/pool.png", + "groups" : [ "Swimlanes" ], + "layout" : [ { + "type" : "layout.bpmn2_0.pool" + } ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "process_idpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "canContainArtifacts", "all" ] + }, { + "type" : "node", + "id" : "Lane", + "title" : "Lane", + "description" : "A lane to stucture the process definition", + "view" : "\n\n \n \n \n \n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\n\t\n \t\t\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n\t\n \n\t\n \n", + "icon" : "swimlane/lane.png", + "groups" : [ "Swimlanes" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "PoolChild", "canContainArtifacts", "all" ] + }, { + "type" : "edge", + "id" : "SequenceFlow", + "title" : "Sequence flow", + "description" : "Sequence flow defines the execution order of activities.", + "view" : "\r\n\r\n\t\r\n\t \t\r\n\t \t\t\r\n\t\t\t\r\n\t \t\r\n\t \t\r\n\t \t\t\r\n\t \t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\r\n", + "icon" : "connector/sequenceflow.png", + "groups" : [ "Connecting Objects" ], + "layout" : [ { + "type" : "layout.bpmn2_0.sequenceflow" + } ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "conditionsequenceflowpackage", "executionlistenerspackage", "defaultflowpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ConnectingObjectsMorph", "all" ] + }, { + "type" : "edge", + "id" : "MessageFlow", + "title" : "Message flow", + "description" : "Message flow to connect elements in different pools.", + "view" : "\r\n\r\n\t\r\n\t\t\r\n\t \t\t\r\n\t \t\t\r\n\t \t\r\n\r\n\t \t\r\n\t \t\t\r\n\t \t\r\n\t\r\n\t\r\n\t \r\n\t\t\r\n\t\r\n", + "icon" : "connector/messageflow.png", + "groups" : [ "Connecting Objects" ], + "layout" : [ { + "type" : "layout.bpmn2_0.sequenceflow" + } ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ConnectingObjectsMorph", "all" ] + }, { + "type" : "edge", + "id" : "Association", + "title" : "Association", + "description" : "Associates a text annotation with an element.", + "view" : "\r\n\r\n\t\r\n\t \r\n\t\t\r\n\t\r\n", + "icon" : "connector/association.undirected.png", + "groups" : [ "Connecting Objects" ], + "layout" : [ { + "type" : "layout.bpmn2_0.sequenceflow" + } ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ConnectingObjectsMorph", "all" ] + }, { + "type" : "edge", + "id" : "DataAssociation", + "title" : "DataAssociation", + "description" : "Associates a data element with an activity.", + "view" : "\r\n\r\n\t\r\n\t \t\r\n\t \t\t\r\n\t \t\r\n\t\r\n\t\r\n\t \r\n\t\t\r\n\t\r\n", + "icon" : "connector/association.unidirectional.png", + "groups" : [ "Connecting Objects" ], + "layout" : [ { + "type" : "layout.bpmn2_0.sequenceflow" + } ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "ConnectingObjectsMorph", "all" ] + }, { + "type" : "node", + "id" : "TextAnnotation", + "title" : "Text annotation", + "description" : "Annotates elements with description text.", + "view" : "\n\n \n \n \t\n \n \n \n \n \n \n\t\n \n", + "icon" : "artifact/text.annotation.png", + "groups" : [ "Artifacts" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage", "textpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "all" ] + }, { + "type" : "node", + "id" : "DataStore", + "title" : "Data store", + "description" : "Reference to a data store.", + "view" : "\r\n\r\n\t\r\n\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\r\n\t\r\n\t\r\n\t\t\r\n\t\t\t\r\n\t\t\t\t\r\n\t\t\t\t\r\n\t\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\r\n\t\t\t \t\r\n\t\t\r\n\t\t\t \r\n\t\r\n\r\n", + "icon" : "dataobject/data.store.png", + "groups" : [ "Artifacts" ], + "propertyPackages" : [ "overrideidpackage", "namepackage", "documentationpackage" ], + "hiddenPropertyPackages" : [ ], + "roles" : [ "all" ] + } ], + "rules" : { + "cardinalityRules" : [ { + "role" : "Startevents_all", + "incomingEdges" : [ { + "role" : "SequenceFlow", + "maximum" : 0 + } ] + }, { + "role" : "Endevents_all", + "outgoingEdges" : [ { + "role" : "SequenceFlow", + "maximum" : 0 + } ] + } ], + "connectionRules" : [ { + "role" : "SequenceFlow", + "connects" : [ { + "from" : "sequence_start", + "to" : [ "sequence_end" ] + } ] + }, { + "role" : "Association", + "connects" : [ { + "from" : "sequence_start", + "to" : [ "TextAnnotation" ] + }, { + "from" : "sequence_end", + "to" : [ "TextAnnotation" ] + }, { + "from" : "TextAnnotation", + "to" : [ "sequence_end" ] + }, { + "from" : "BoundaryCompensationEvent", + "to" : [ "sequence_end" ] + }, { + "from" : "TextAnnotation", + "to" : [ "sequence_start" ] + }, { + "from" : "BoundaryCompensationEvent", + "to" : [ "sequence_start" ] + } ] + }, { + "role" : "DataAssociation", + "connects" : [ { + "from" : "sequence_start", + "to" : [ "DataStore" ] + }, { + "from" : "sequence_end", + "to" : [ "DataStore" ] + }, { + "from" : "DataStore", + "to" : [ "sequence_end" ] + }, { + "from" : "DataStore", + "to" : [ "sequence_start" ] + } ] + }, { + "role" : "IntermediateEventOnActivityBoundary", + "connects" : [ { + "from" : "Activity", + "to" : [ "IntermediateEventOnActivityBoundary" ] + } ] + } ], + "containmentRules" : [ { + "role" : "BPMNDiagram", + "contains" : [ "all" ] + }, { + "role" : "SubProcess", + "contains" : [ "sequence_start", "sequence_end", "from_task_event", "to_task_event", "EventSubProcess", "TextAnnotation", "DataStore" ] + }, { + "role" : "EventSubProcess", + "contains" : [ "sequence_start", "sequence_end", "from_task_event", "to_task_event", "TextAnnotation", "DataStore" ] + }, { + "role" : "Pool", + "contains" : [ "Lane" ] + }, { + "role" : "Lane", + "contains" : [ "sequence_start", "sequence_end", "EventSubProcess", "TextAnnotation", "DataStore" ] + } ], + "morphingRules" : [ { + "role" : "ActivitiesMorph", + "baseMorphs" : [ "UserTask" ], + "preserveBounds" : true + }, { + "role" : "GatewaysMorph", + "baseMorphs" : [ "ExclusiveGateway" ] + }, { + "role" : "StartEventsMorph", + "baseMorphs" : [ "StartNoneEvent" ] + }, { + "role" : "EndEventsMorph", + "baseMorphs" : [ "StartNoneEvent" ] + }, { + "role" : "CatchEventsMorph", + "baseMorphs" : [ "CatchTimerEvent" ] + }, { + "role" : "ThrowEventsMorph", + "baseMorphs" : [ "ThrowNoneEvent" ] + }, { + "role" : "BoundaryEventsMorph", + "baseMorphs" : [ "ThrowNoneEvent" ] + }, { + "role" : "BoundaryCompensationEvent", + "baseMorphs" : [ "BoundaryCompensationEvent" ] + }, { + "role" : "TextAnnotation", + "baseMorphs" : [ "TextAnnotation" ] + }, { + "role" : "DataStore", + "baseMorphs" : [ "DataStore" ] + } ] + } +} diff --git a/src/main/webapp/WEB-INF/decorators.xml b/src/main/webapp/WEB-INF/decorators.xml deleted file mode 100644 index d20814eb6b..0000000000 --- a/src/main/webapp/WEB-INF/decorators.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - /static/* - - - - /* - - diff --git a/src/main/webapp/WEB-INF/spring-mvc-modeler.xml b/src/main/webapp/WEB-INF/spring-mvc-modeler.xml new file mode 100644 index 0000000000..8959fd2359 --- /dev/null +++ b/src/main/webapp/WEB-INF/spring-mvc-modeler.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/spring-mvc-rest.xml b/src/main/webapp/WEB-INF/spring-mvc-rest.xml new file mode 100644 index 0000000000..a6d3f05b9c --- /dev/null +++ b/src/main/webapp/WEB-INF/spring-mvc-rest.xml @@ -0,0 +1,15 @@ + + + + + + + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/spring-mvc.xml b/src/main/webapp/WEB-INF/spring-mvc.xml index 131b6ae7c8..c1e3913d0b 100644 --- a/src/main/webapp/WEB-INF/spring-mvc.xml +++ b/src/main/webapp/WEB-INF/spring-mvc.xml @@ -1,10 +1,9 @@ @@ -25,16 +24,6 @@ - - - - - - - - - - + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/tags/pagination.tag b/src/main/webapp/WEB-INF/tags/pagination.tag new file mode 100644 index 0000000000..1dadc3de23 --- /dev/null +++ b/src/main/webapp/WEB-INF/tags/pagination.tag @@ -0,0 +1,43 @@ +<%@tag pageEncoding="UTF-8"%> +<%@ attribute name="page" type="me.kafeitu.demo.activiti.util.Page" required="true"%> +<%@ attribute name="paginationSize" type="java.lang.Integer" required="true"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<% + int current = page.getPageNo(); + long begin = Math.max(1, current - paginationSize/2); + long end = Math.min(begin + (paginationSize - 1), page.getTotalPages()); + request.setAttribute("current", current); + request.setAttribute("begin", begin); + request.setAttribute("end", end); +%> + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-process-list.jsp b/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-process-list.jsp index c9c447eaf9..ef00524b22 100644 --- a/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-process-list.jsp +++ b/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-process-list.jsp @@ -10,6 +10,7 @@ <%@ include file="/common/include-jquery-ui-theme.jsp" %> + <%@ include file="/common/include-custom-styles.jsp" %> @@ -18,6 +19,10 @@ + @@ -45,19 +50,20 @@ - + ${process.id } ${process.deploymentId } ${process.name } ${process.key } ${process.version } - ${process.resourceName } - ${process.diagramResourceName } + ${process.resourceName } + ${process.diagramResourceName } 启动 + diff --git a/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-task-list.jsp b/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-task-list.jsp index 4353c055c8..07b2ea381c 100644 --- a/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-task-list.jsp +++ b/src/main/webapp/WEB-INF/views/form/dynamic/dynamic-form-task-list.jsp @@ -22,6 +22,9 @@ + @@ -65,7 +68,7 @@ ${task.owner } - 签收 + 签收 <%-- 此处用tkey记录当前节点的名称 --%> diff --git a/src/main/webapp/WEB-INF/views/form/finished-list.jsp b/src/main/webapp/WEB-INF/views/form/finished-list.jsp index c021516127..3967d10f24 100644 --- a/src/main/webapp/WEB-INF/views/form/finished-list.jsp +++ b/src/main/webapp/WEB-INF/views/form/finished-list.jsp @@ -23,17 +23,17 @@ 流程结束原因 - + ${hpi.id } ${hpi.processDefinitionId } ${hpi.startTime } ${hpi.endTime } - ${hpi.deleteReason } + ${empty hpi.deleteReason ? "正常结束" : hpi.deleteReason} - +
    diff --git a/src/main/webapp/WEB-INF/views/form/formkey/formkey-process-list.jsp b/src/main/webapp/WEB-INF/views/form/formkey/formkey-process-list.jsp index e4cf82fb95..cdff76d0e4 100644 --- a/src/main/webapp/WEB-INF/views/form/formkey/formkey-process-list.jsp +++ b/src/main/webapp/WEB-INF/views/form/formkey/formkey-process-list.jsp @@ -10,6 +10,7 @@ <%@ include file="/common/include-jquery-ui-theme.jsp" %> + <%@ include file="/common/include-custom-styles.jsp" %> @@ -46,19 +47,20 @@ - + ${process.id } ${process.deploymentId } ${process.name } ${process.key } ${process.version } - ${process.resourceName } - ${process.diagramResourceName } + ${process.resourceName } + ${process.diagramResourceName } 启动 + diff --git a/src/main/webapp/WEB-INF/views/form/formkey/formkey-task-list.jsp b/src/main/webapp/WEB-INF/views/form/formkey/formkey-task-list.jsp index c1137acb01..549ffc3040 100644 --- a/src/main/webapp/WEB-INF/views/form/formkey/formkey-task-list.jsp +++ b/src/main/webapp/WEB-INF/views/form/formkey/formkey-task-list.jsp @@ -51,7 +51,7 @@ 操作 - + ${task.id } ${task.taskDefinitionKey } @@ -75,7 +75,7 @@ - +
    diff --git a/src/main/webapp/WEB-INF/views/form/running-list.jsp b/src/main/webapp/WEB-INF/views/form/running-list.jsp index 8c8b759853..36163a65d3 100644 --- a/src/main/webapp/WEB-INF/views/form/running-list.jsp +++ b/src/main/webapp/WEB-INF/views/form/running-list.jsp @@ -43,19 +43,19 @@ 是否挂起 - + ${p.id } ${p.processInstanceId } ${p.processDefinitionId } - <%=ProcessDefinitionCache.getActivityName(pageContext.getAttribute("pdid").toString(), ObjectUtils.toString(pageContext.getAttribute("activityId"))) %> + <%=ProcessDefinitionCache.getActivityName(pageContext.getAttribute("pdid").toString(), ObjectUtils.toString(pageContext.getAttribute("activityId"))) %> ${p.suspended } - +
    diff --git a/src/main/webapp/WEB-INF/views/login.jsp b/src/main/webapp/WEB-INF/views/login.jsp index c6ae2bcad8..868a24ab1f 100644 --- a/src/main/webapp/WEB-INF/views/login.jsp +++ b/src/main/webapp/WEB-INF/views/login.jsp @@ -4,7 +4,7 @@ <%@ include file="/common/global.jsp"%> - 登录页 + KAD登录页 - 咖啡兔(闫洪磊) @@ -28,73 +43,109 @@ - -
    - -

    用户名或密码错误!!!

    -
    - -

    未登陆或超时!!!

    -
    -
    -

    工作流引擎Activiti演示

    + + -
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + +
    用户列表(密码:000000)
    用户名角色
    admin管理员、用户
    kafeitu用户
    hruser人事、用户
    leaderuser部门经理、用户
    +
    + +
    +
    +
    +
    +
    组件版本信息
    +
      +
    • Activiti版本:${prop['activiti.version']}
    • +
    • Spring版本:${prop['spring.version']}
    • +
    • Database:${prop['db.type']}
    • +
    • 使用Maven管理依赖
    • +
    +
    +
    +
    QQ交流群
    +
      +
    • Activiti中文群1(欢迎):236540304
    • +
    • Activiti中文群2(已满):23539326
    • +
    • Activiti中文群3(已满):139983080
    • +
    • Activiti中文群4(已满):327913744
    • +
    +
    +
    +
    +
    + +
    + diff --git a/src/main/webapp/WEB-INF/views/main/index.jsp b/src/main/webapp/WEB-INF/views/main/index.jsp index 83d554cac5..96b4a1ebe5 100644 --- a/src/main/webapp/WEB-INF/views/main/index.jsp +++ b/src/main/webapp/WEB-INF/views/main/index.jsp @@ -15,7 +15,7 @@ PropertyFileUtil.init(); } <%@ include file="/common/meta.jsp" %> - Activiti-演示系统 + Activiti-演示系统-咖啡兔(闫洪磊) <%@ include file="/common/include-base-styles.jsp" %> <%@ include file="/common/include-jquery-ui-theme.jsp" %> @@ -78,9 +78,9 @@ PropertyFileUtil.init();
    <%@ include file="menu.jsp" %> diff --git a/src/main/webapp/WEB-INF/views/main/menu.jsp b/src/main/webapp/WEB-INF/views/main/menu.jsp index 7767a40b87..6e22512839 100644 --- a/src/main/webapp/WEB-INF/views/main/menu.jsp +++ b/src/main/webapp/WEB-INF/views/main/menu.jsp @@ -28,11 +28,41 @@
  • 已结束流程(外置)
  • +
  • + 综合流程 + +
  • - 流程管理 + 管理模块 +
  • +
  • + Rest示例 +
  • \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/main/welcome.jsp b/src/main/webapp/WEB-INF/views/main/welcome.jsp index a6fb346d1a..1b3e3aba3e 100644 --- a/src/main/webapp/WEB-INF/views/main/welcome.jsp +++ b/src/main/webapp/WEB-INF/views/main/welcome.jsp @@ -10,11 +10,17 @@ <%@ include file="/common/include-base-styles.jsp" %> <%@ include file="/common/include-jquery-ui-theme.jsp" %> + <%@ include file="/common/include-custom-styles.jsp" %> @@ -26,85 +32,125 @@ -

    欢迎访问Activiti Demo,专为优秀的BPMN2.0规范的轻量级工作流引擎Activiti服务

    -
    +
    +
    +

    欢迎访问Activiti Demo,专为优秀的BPMN2.0规范的轻量级工作流引擎Activiti服务

    +
    +
    +
    + +
    +
      +
    • + 普通表单:每个节点的表单内容都写死在JSP或者HTML中。 +
    • +
    • + 动态表单:表单内容存放在流程定义文件中(包含在启动事件以及每个用户任务中)。 +
    • +
    • + 外置表单:每个用户任务对应一个单独的.form文件,和流程定义文件同时部署(打包为zip/bar文件)。 +
    • +
    • + 综合流程:可以查询到所有的流程(普通、动态、外置固定查询某些流程的表单,为了演示所以单独分开);综合流程的目的 + 在于可以启动用户上传或者设计后部署的流程定义。 +
    • +
    +
    +
    + 在填写会签参与人字段时使用用户的ID作为值,例如:kafeitu,admin表示两个用户,即两个任务实例被创建。 +
    +
    + +
    - -
    -
      -
    • - 普通表单:每个节点的表单内容都写死在JSP或者HTML中。 -
    • -
    • - 动态表单:表单内容存放在流程定义文件中(包含在启动事件以及每个用户任务中)。 -
    • -
    • - 外置表单:每个用户任务对应一个单独的.form文件,和流程定义文件同时部署(打包为zip/bar文件)。 -
    • -
    -
    -
    - 在填写会签参与人字段时使用用户的ID作为值,例如:kafeitu,admin表示两个用户,即两个任务实例被创建。 -
    -
    - -
    +
    +
      +
    • Activiti版本:${prop['activiti.version']}
    • +
    • Spring版本:${prop['spring.version']}
    • +
    • Hibernate:${prop['hibernate.version']}
    • +
    • 使用Maven管理依赖
    • +
    +
    -
    -
      -
    • Activiti版本:<%=PropertyFileUtil.get("activiti.version") %>
    • -
    • Spring版本:3.1
    • -
    • 使用Maven管理依赖
    • -
    -
    +
    +
      +
    • 部署流程
    • +
    • 启动流程
    • +
    • 任务签收
    • +
    • 任务办理
    • +
    • 驳回请求
    • +
    • 查询运行中流程
    • +
    • 查询历史流程
    • +
    • 任务监听
    • +
    • 自定义表单
    • +
    • 动态表单
    • +
    • 外置表单
    • +
    • 个人待办任务汇总
    • +
    • 分页查询
    • +
    • 流程定义缓存
    • +
    • 集成Activiti Modeler[5.17+](New)
    • +
    • 引擎参数(New)
    • +
    • 引擎数据库查看(New)
    • +
    • 引擎内置用户与组(New)
    • +
    • 定时作业管理(启动timerExample流程)(New)
    • +
    +
    -
    -
      -
    • 部署流程
    • -
    • 启动流程
    • -
    • 任务签收
    • -
    • 任务办理
    • -
    • 驳回请求
    • -
    • 查询运行中流程
    • -
    • 查询历史流程
    • -
    • 任务监听
    • -
    • 自定义表单
    • -
    • 动态表单
    • -
    • 外置表单
    • -
    • 个人待办任务汇总
    • -
    -
    + - +
    +
      +
    • + 作者:咖啡兔(闫洪磊) +
    • +
    • + QQ:576525789 +
    • +
    • + Weibo:@kafeituzi +
    • +
    • + QQ群: +
        +
      • Activiti中文群1(欢迎):236540304
      • +
      • Activiti中文群2(已满):23539326
      • +
      • Activiti中文群3(已满):139983080
      • +
      • Activiti中文群4(已满):327913744
      • +
      +
    • +
    +
    -
    -
      -
    • - 作者:咖啡兔 -
    • -
    • - QQ:576525789 -
    • -
    • - QQ群:236540304 -
    • -
    • - Weibo:@kafeituzi -
    • -
    -
    +
    +

    在web.xml中映射了两个两个Servlet

    +
    +
    ModelRestServlet
    +
    +

    针对Activiti Modeler的Rest接口,映射路径:/service/*

    +
    +
    RestServlet
    +
    +

    官方提供的完整Rest接口

    +

    访问路径:http://localhost/yourappname/<用户手册提供的Rest地址>

    +

    映射路径:/rest/*

    +
    +
    +
    - \ No newline at end of file + diff --git a/src/main/webapp/WEB-INF/views/management/database.jsp b/src/main/webapp/WEB-INF/views/management/database.jsp new file mode 100644 index 0000000000..9cfa26a603 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/management/database.jsp @@ -0,0 +1,62 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + <%@ include file="/common/global.jsp"%> + <%@ include file="/common/meta.jsp" %> + + + + + + + + +
    引擎数据库
    +
    +
    +
    表名
    + +
    +
    + +
    记录(${tableMetaData.tableName})
    + + + + + + + + + + + + + + + + + + + + + +
    ${data}
    ${counter}${data[column]}
    + + + + +
    + + +

    单击左边的表名可以查看记录!

    +
    +
    +
    + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/management/engine-info.jsp b/src/main/webapp/WEB-INF/views/management/engine-info.jsp new file mode 100644 index 0000000000..39989f8955 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/management/engine-info.jsp @@ -0,0 +1,42 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + <%@ include file="/common/global.jsp"%> + <%@ include file="/common/meta.jsp" %> + + + + + + + +
    引擎配置
    + + + + + + + + + + + +
    属性名称属性值
    ${prop.key}${prop.value}
    + +
    系统参数
    + + + + + + + + + + + +
    属性名称属性值
    ${prop.key}${prop.value}
    + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/management/group-list.jsp b/src/main/webapp/WEB-INF/views/management/group-list.jsp new file mode 100644 index 0000000000..6f61458173 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/management/group-list.jsp @@ -0,0 +1,115 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + <%@ include file="/common/global.jsp"%> + <%@ include file="/common/meta.jsp" %> + + + + + + + 组列表--management + + + + +
    + +
    ${message}
    + + +
    + +
    ${errorMsg}
    + + +
    +
    +
    +
    + 组列表 + + + + + + + + + + + + + + + + + + + +
    组ID组名称类型操作
    ${group.id}${group.name}${group.type} + 删除 + 编辑 +
    + +
    +
    +
    +
    + +
    + 新增/编辑组 + +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + + +
    +
    +
    +
    +
    + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/management/job-list.jsp b/src/main/webapp/WEB-INF/views/management/job-list.jsp new file mode 100644 index 0000000000..9afb7544ef --- /dev/null +++ b/src/main/webapp/WEB-INF/views/management/job-list.jsp @@ -0,0 +1,85 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + <%@ include file="/common/global.jsp"%> + <%@ include file="/common/meta.jsp" %> + + + + + + + + Job列表 + + + + +
    作业管理列表
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    作业ID作业类型预定时间可重试次数流程定义ID流程实例ID执行ID异常消息作业配置信息操作
    ${job.id}${JOB_TYPES[job.jobHandlerType]}${job.retries}${job.processDefinitionId}${job.processInstanceId}${job.executionId}${job.exceptionMessage} + <%-- 特殊处理异步的job --%> + + 到期时间: +
    + 锁标示(UUID):${job.lockOwner} +
    + ${job.jobHandlerConfiguration} +
    + +
    + + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/management/user-list.jsp b/src/main/webapp/WEB-INF/views/management/user-list.jsp new file mode 100644 index 0000000000..43932c912e --- /dev/null +++ b/src/main/webapp/WEB-INF/views/management/user-list.jsp @@ -0,0 +1,184 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + <%@ include file="/common/global.jsp"%> + <%@ include file="/common/meta.jsp" %> + + + + + + + 用户列表--management + + + + +
    + +
    ${message}
    + + +
    + +
    ${errorMsg}
    + + +
    +
    +
    +
    + 用户列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    用户ID姓名Email所属组操作
    ${user.id} + ${user.firstName} ${user.lastName} + + + ${user.email} + 共${fn:length(groupOfUserMap[user.id])}个组
    +
    + 删除 + 编辑 +
    + +
    +
    + + +
    +
    +
    + 新增/编辑用户 + +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + + +
    +
    +
    +
    + + +
    + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/oa/leave/finished.jsp b/src/main/webapp/WEB-INF/views/oa/leave/finished.jsp index 7a4ad8126f..a6399ff497 100644 --- a/src/main/webapp/WEB-INF/views/oa/leave/finished.jsp +++ b/src/main/webapp/WEB-INF/views/oa/leave/finished.jsp @@ -39,7 +39,7 @@ - + ${leave.leaveType } @@ -57,5 +57,6 @@ + diff --git a/src/main/webapp/WEB-INF/views/oa/leave/leaveApply.jsp b/src/main/webapp/WEB-INF/views/oa/leave/leaveApply.jsp index 97d12ae7fa..290e9729ac 100644 --- a/src/main/webapp/WEB-INF/views/oa/leave/leaveApply.jsp +++ b/src/main/webapp/WEB-INF/views/oa/leave/leaveApply.jsp @@ -43,7 +43,7 @@ }, 5000);
    - +
    请假申请 diff --git a/src/main/webapp/WEB-INF/views/oa/leave/running.jsp b/src/main/webapp/WEB-INF/views/oa/leave/running.jsp index aa9a29328d..a9d61f1104 100644 --- a/src/main/webapp/WEB-INF/views/oa/leave/running.jsp +++ b/src/main/webapp/WEB-INF/views/oa/leave/running.jsp @@ -43,7 +43,7 @@ - + @@ -53,7 +53,7 @@ @@ -62,5 +62,6 @@
    ${leave.startTime } ${leave.endTime } - ${task.name } + ${task.name } ${task.createTime } ${pi.suspended ? "已挂起" : "正常" };V: ${leave.processDefinition.version }
    + diff --git a/src/main/webapp/WEB-INF/views/oa/leave/taskList.jsp b/src/main/webapp/WEB-INF/views/oa/leave/taskList.jsp index a243173fa4..05d4f62424 100644 --- a/src/main/webapp/WEB-INF/views/oa/leave/taskList.jsp +++ b/src/main/webapp/WEB-INF/views/oa/leave/taskList.jsp @@ -51,7 +51,7 @@ - + @@ -61,7 +61,7 @@ ${leave.startTime } ${leave.endTime } - ${task.name } + ${task.name } <%--${task.name } --%> ${task.createTime } @@ -79,7 +79,7 @@ - + diff --git a/src/main/webapp/WEB-INF/views/workflow/model-list.jsp b/src/main/webapp/WEB-INF/views/workflow/model-list.jsp new file mode 100644 index 0000000000..3b23b8fbf4 --- /dev/null +++ b/src/main/webapp/WEB-INF/views/workflow/model-list.jsp @@ -0,0 +1,123 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + <%@ include file="/common/global.jsp"%> + + <%@ include file="/common/meta.jsp" %> + <%@ include file="/common/include-base-styles.jsp" %> + <%@ include file="/common/include-jquery-ui-theme.jsp" %> + <%@ include file="/common/include-custom-styles.jsp" %> + 流程列表 + + + + + + + +
    +
    +

    + 提示:${message}

    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    IDKEYNameVersion创建时间最后更新时间元数据操作
    ${model.id }${model.key }${model.name}${model.version}${model.createTime}${model.lastUpdateTime}${model.metaInfo} + 编辑 + 部署 + 导出(BPMN + | JSON + | SVG) + 删除 +
    +
    +
    + + + + + + + + + + + + + +
    名称: + +
    KEY: + +
    描述: + +
    +
    +
    + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/views/workflow/process-list.jsp b/src/main/webapp/WEB-INF/views/workflow/process-list.jsp index 6bfbed729f..d152e769d1 100644 --- a/src/main/webapp/WEB-INF/views/workflow/process-list.jsp +++ b/src/main/webapp/WEB-INF/views/workflow/process-list.jsp @@ -12,6 +12,7 @@ <%@ include file="/common/meta.jsp" %> <%@ include file="/common/include-base-styles.jsp" %> <%@ include file="/common/include-jquery-ui-theme.jsp" %> + <%@ include file="/common/include-custom-styles.jsp" %> 流程列表 @@ -45,7 +46,7 @@
    提示:点击xml或者png链接可以查看具体内容!
    部署流程 - 重新部署流程 +