Activiti Model Editor

Activiti Model Editor组件

我的了解Activiti Explorer及其Vaadin实现方式博文里提到Activiti Explorer使用的是Vaadin架构,但是Activiti 模型编辑器组件却没用使用Vaadin架构,而是采用Angular.JS的MVC模式。Activiti
模型编辑器组件的客户端代码位于Activiti\modules\activiti-webapp-explorer2\src\main\webapp\editor-app\。

该目录下的editor.html是Activiti Modeler Editor的主界面HTML代码

其中palette区是通过Angular.JS使用stencilsets\bpmn2.0\icons下多个子目录内的PNG图像形成的多组列表。其节点层次关系获取相关代码为:

  1. stencil-controller.js
  2. Activiti\modules\activiti-modeler\src\main\java\org\activiti\rest\editor\main\StencilsetRestResource.java
  3. Activiti\modules\activiti-webapp-explorer2\src\main\resources\stencilset.json


editor.html中的视图与两个控制器进行了绑定:

  • stencil-controller.js:处理对canvas中BPMN元素的操作,很多处理是通过editor目录下的QRYX库完成的
  • toolbar-controller.js:处理对工具栏的操作,很多处理由configuration\toolbar-default-actions.js完成

保存模型操作

保存模型操作,是通过toolbar-default-actions.js中的SaveModel方法完成的,它需要将三部分信息传给服务器:

  • 模型的元数据:例如模型名称、分类、创建时间、最后一次更新时间等等
  • 模型JSON数据:将canvas内的图像数据转换成JSON数据UTF8字符串
    {
     "resourceId": 53,
     "properties": {
      "process_id": "process",
      "name": "",
      "documentation": "",
      "process_author": "",
      "process_version": "",
      "process_namespace": "http://www.activiti.org/processdef",
      "executionlisteners": "",
      "eventlisteners": ""
     },
     "stencil": {
      "id": "BPMNDiagram"
     },
     "childShapes": [
      {
       "resourceId": "sid-4F7484B9-11EC-4FCE-8950-FEFFB723D88B",
       "properties": {
        "overrideid": "",
        "name": "",
        "documentation": "",
        "executionlisteners": "",
        "initiator": "",
        "formkeydefinition": "",
        "formproperties": ""
       },
       "stencil": {
        "id": "StartNoneEvent"
       },
       "childShapes": [],
       "outgoing": [
        {
         "resourceId": "sid-B589A0D9-FA79-4C12-95B7-253E72480384"
        }
       ],
       "bounds": {
        "lowerRight": {
         "x": 259,
         "y": 139
        },
        "upperLeft": {
         "x": 229,
         "y": 109
        }
       },
       "dockers": []
      },
      {
       "resourceId": "sid-1A762474-62B9-4F3D-A81C-1ADD46AF7D2F",
       "properties": {
        "overrideid": "",
        "name": "",
        "documentation": "",
        "asynchronousdefinition": "false",
        "exclusivedefinition": "false",
        "executionlisteners": "",
        "multiinstance_type": "None",
        "multiinstance_cardinality": "",
        "multiinstance_collection": "",
        "multiinstance_variable": "",
        "multiinstance_condition": "",
        "isforcompensation": "false",
        "usertaskassignment": "",
        "formkeydefinition": "",
        "duedatedefinition": "",
        "prioritydefinition": "",
        "formproperties": "",
        "tasklisteners": ""
       },
       "stencil": {
        "id": "UserTask"
       },
       "childShapes": [],
       "outgoing": [
        {
         "resourceId": "sid-4134C10E-B589-42FF-AACC-463D35D52016"
        }
       ],
       "bounds": {
        "lowerRight": {
         "x": 746,
         "y": 172
        },
        "upperLeft": {
         "x": 646,
         "y": 92
        }
       },
       "dockers": []
      },
      {
       "resourceId": "sid-B22A5CAB-94D0-419E-BB1E-E8538C6A7283",
       "properties": {
        "overrideid": "",
        "name": "",
        "documentation": "",
        "executionlisteners": ""
       },
       "stencil": {
        "id": "EndNoneEvent"
       },
       "childShapes": [],
       "outgoing": [],
       "bounds": {
        "lowerRight": {
         "x": 1089,
         "y": 138
        },
        "upperLeft": {
         "x": 1061,
         "y": 110
        }
       },
       "dockers": []
      },
      {
       "resourceId": "sid-B589A0D9-FA79-4C12-95B7-253E72480384",
       "properties": {
        "overrideid": "",
        "name": "",
        "documentation": "",
        "conditionsequenceflow": "",
        "executionlisteners": "",
        "defaultflow": "false"
       },
       "stencil": {
        "id": "SequenceFlow"
       },
       "childShapes": [],
       "outgoing": [
        {
         "resourceId": "sid-1A762474-62B9-4F3D-A81C-1ADD46AF7D2F"
        }
       ],
       "bounds": {
        "lowerRight": {
         "x": 645.5626565925471,
         "y": 131.10730365650525
        },
        "upperLeft": {
         "x": 259.12484340745283,
         "y": 124.26769634349473
        }
       },
       "dockers": [
        {
         "x": 15,
         "y": 15
        },
        {
         "x": 50,
         "y": 40
        }
       ],
       "target": {
        "resourceId": "sid-1A762474-62B9-4F3D-A81C-1ADD46AF7D2F"
       }
      },
      {
       "resourceId": "sid-4134C10E-B589-42FF-AACC-463D35D52016",
       "properties": {
        "overrideid": "",
        "name": "",
        "documentation": "",
        "conditionsequenceflow": "",
        "executionlisteners": "",
        "defaultflow": "false"
       },
       "stencil": {
        "id": "SequenceFlow"
       },
       "childShapes": [],
       "outgoing": [
        {
         "resourceId": "sid-B22A5CAB-94D0-419E-BB1E-E8538C6A7283"
        }
       ],
       "bounds": {
        "lowerRight": {
         "x": 1060.676003953202,
         "y": 130.93202152143962
        },
        "upperLeft": {
         "x": 746.595480421798,
         "y": 124.30235347856038
        }
       },
       "dockers": [
        {
         "x": 50,
         "y": 40
        },
        {
         "x": 14,
         "y": 14
        }
       ],
       "target": {
        "resourceId": "sid-B22A5CAB-94D0-419E-BB1E-E8538C6A7283"
       }
      }
     ],
     "bounds": {
      "lowerRight": {
       "x": 1200,
       "y": 1050
      },
      "upperLeft": {
       "x": 0,
       "y": 0
      }
     },
     "stencilset": {
      "url": "stencilsets/bpmn2.0/bpmn2.0.json",
      "namespace": "http://b3mn.org/stencilset/bpmn2.0#"
     },
     "ssextensions": []
    }
  • 模型的SVG图像数据:将canvas中的SVG图像数据经过过滤处理而得

服务器侧保存模型的代码位于Activiti\modules\activiti-modeler\src\main\java\org\activiti\rest\editor\model\ModelSaveRestResource.java。

  • 通过RepositoryService的saveModel方法将模型的元数据存入数据库的ACT_RE_MODEL表
  • 通过RepositoryService的addModelEditorSource方法将模型JSON数据UTF8字符串存入数据库的ACT_GE_BYTEARRAY表
  • 通过Apache Batik SVG Toolkit将模型的SVG图像数据转换成PNG格式,通过RepositoryService的addModelEditorSourceExtra方法将PNG图像存入数据库的ACT_GE_BYTEARRAY表

Activiti Explorer操作已保存模型

对模型的编辑操作是在Activiti Model Editor组件里实现的,对已保存模型的其他操作还是在Activiti Explorer里基于Vaadin架构实现的。
客户端代码位于:Activiti\modules\activiti-explorer\src\main\java\org\activiti\editor\ui\。
下图的HTML界面由EditorProcessDefinitionDetailPanel.java实现。 

显示已保存模型

  1. 选择模型,会调用EditorProcessDefinitionPage类的showProcessDefinitionDetail方法
  2. EditorProcessDefinitionDetailPanel类的initUI方法调用initProcessDefinitionInfo方法,它会加入EditorProcessDefinitionInfoComponent实例
  3. 在构造EditorProcessDefinitionInfoComponent实例时,其initImage方法会被调用,通过RepositoryService的getModelEditorSourceExtra方法获得PNG格式图像,最终被显示到浏览器界面上。

部署已保存模型

EditorProcessDefinitionDetailPanel类的deployModel方法处理部署已保存模型的操作。

  1. 通过RepositoryService的getModelEditorSource方法获得模型JSON数据的UTF8字符串
  2. 通过FasterXML/jackson-databind转换成Java对象树
  3. 通过Activiti\modules\activiti-json-converter\src\main\java\org\activiti\editor\language\json\converter\BpmnJsonConverter.java将模型JSON数据的Java对象树转换成BpmnModel实例
  4. 通过Activiti\modules\activiti-bpmn-converter\src\main\java\org\activiti\bpmn\converter\BpmnXMLConverter.java 将BpmnModel实例转成BPMN XML数据
  5. 通过RepositoryService的createDeployment方法将BPMN XML数据进行部署

导出已保存模型

EditorProcessDefinitionDetailPanel类的exportModel方法处理导出已保存模型的操作。

  1. 通过RepositoryService的getModelEditorSource方法获得模型数据的JSON字符串
  2. 通过FasterXML/jackson-databind转换成Java对象树
  3. 通过Activiti\modules\activiti-json-converter\src\main\java\org\activiti\editor\language\json\converter\BpmnJsonConverter.java将模型JSON数据的Java对象树转换成BpmnModel实例
  4. 通过Activiti\modules\activiti-bpmn-converter\src\main\java\org\activiti\bpmn\converter\BpmnXMLConverter.java 将BpmnModel实例转成BPMN XML数据

编辑已保存模型

EditorProcessDefinitionDetailPanel类内注册了EditModelClickListener监听器用于处理导入BPMN模型操作。
EditModelClickListener的showModeler会生成访问模型编辑器组件的URL地址,打开指定的模型。

  1. Activiti\modules\activiti-webapp-explorer2\src\main\webapp\editor-app\app.js中的监听器处理$includeContentLoaded事件,调用了fetchModel方法
  2. Activiti\modules\activiti-modeler\src\main\java\org\activiti\rest\editor\model\ModelEditorJsonRestResource.java处理该REST请求,返回由RepositoryService的getModel和getModelEditorSource方法获得Activiti模型元数据和JSON数据

导入BPMN模型

EditorProcessDefinitionDetailPanel类内注册了ImportModelClickListener监听器用于处理导入BPMN模型操作。
ImportPopupWindow界面完成BPMN模型操作后,ImportUploadReceiver类的deployUploadedFile方法处理上传的BPMN XML数据。

  1. 通过Activiti\modules\activiti-bpmn-converter\src\main\java\org\activiti\bpmn\converter\BpmnXMLConverter.java 将BPMN XML数据转换成BpmnModel实例
  2. 通过BpmnModel实例生成模型的元数据,通过RepositoryService的saveModel方法将模型的元数据存入数据库的ACT_RE_MODEL表
  3. 通过Activiti\modules\activiti-json-converter\src\main\java\org\activiti\editor\language\json\converter\BpmnJsonConverter.java将BpmnModel实例转换成模型JSON数据的Java对象树,通过RepositoryService的addModelEditorSource方法将模型JSON数据UTF8字符串存入数据库的ACT_GE_BYTEARRAY表

一些疑惑和想法:
  • 这里BpmnXMLConverter和BpmnJsonConverter用的比较频繁,而且成对出现。为什么不跳过中间的BpmnModel?
  • 导入BPMN模型为什么不生成PNG图像?
  • 数据库存储的模型数据不采用BPMN XML格式而是采用JSON格式,很灵活,可以随意添加Activiti扩展内容。但是如果没有现成的JSON schema,分析起来够麻烦。
时间: 2025-01-31 10:56:52

Activiti Model Editor的相关文章

Activiti实战

实 战 Activiti实战 闫洪磊 著 图书在版编目(CIP)数据 Activiti实战/闫洪磊著. -北京:机械工业出版社,2014.12 (实战) ISBN 978-7-111-48595-7 I. A- II.闫- III. JAVA语言-程序设计 IV. TP312 中国版本图书馆CIP数据核字(2014)第270580号 本书版权登记号:图字:01-2013-1390 Authorized translation from the English language edition,

集成新版(5.17+)Activiti Modeler与Rest服务

声明: 此教程适合Activiti 5.17+版本. 本博客所涉及的内容均可在kft-activiti-demo中找到. 在线demo可以访问 http://demo.kafeitu.me:8080/kft-activiti-demo 菜单路径:管理模块 -> 流程管理 -> 模型工作区,可以『创建』或者『编辑』模型 1. 简介 上一篇介绍整合Activiti Modeler<整合Activiti Modeler到业务系统(或BPM平台)>已经有2年多时间了,自从Activiti

activiti自定义流程之Spring整合activiti-modeler5.16实例(二):创建流程模型

注:(1)环境搭建:activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建 1.maven导包,这里就没有什么多的好说了,直接代码: <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </de

activiti自定义流程之Spring整合activiti-modeler5.16实例(一):环境搭建

项目中需要整合activiti-modeler自定义流程,找了很多资料后,终于成功的跳转到activiti-modeler流程设计界面,以下是记录: 一.整合基础:eclipse4.4.1.tomcat7.jdk1.7.mysql5.6.25.maven3.2.5.activiti5.16.3.spring4.0.9二.步骤:    1.下载activiti-5.16.3.zip: http://www.activiti.org/download.html    2.解压zip文件,解压后的目录

activiti中的bug列表

分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) Bug [ACT-1968] - Custom Database schema on PostgreSQL not working [ACT-4113] - REST Task API Not working: /service/runtime/tasks?assigneeLike=XX and service/runtime/tasks?ownerLike=YY

Activiti 简易教程一 version5.10

一搭建环境 1.1   JDK 6+ activiti 运行在版本 6以上的 JDK上.转到 Oracle Java SE下载页面,点击按钮"下载 JDK".网页中也有安装说明.要核实安装是否成功,在命令行上运行 java–version.将打印出安装的 JDK的版本. 1.2   Ant 1.8.1+ 从 Ant[http://ant.apache.org/bindownload.cgi]下载页面下载最新稳定版的 Ant.解压文件,确保其 bin文件夹在操作系统的 path 下.在命

Activiti实战. 3.3基于Eclipse插件的流程设计器Activiti Designer

3.3基于Eclipse插件的流程设计器Activiti Designer 在客户的需求确定之后,由业务人员利用Activiti Modeler设计完业务流程,此时可以将设计结果导出为bpmn20.xml文件,之后由开发人员继续基于设计进一步添加涉及技术细节的配置,例如排他分支的条件.Java服务.任务监听器等. 3.3.1Activiti Designer特点 Java程序员每天工作使用的主要工具是IDE,而应用最广泛的IDE当然是Eclipse,任何开发人员都可以很容易地开发Eclipse的

activiti自定义流程之整合(一):整体环境配置

结合之前所说的自定义流程的思路,分别是后台.前台.整合,之前的内容也分别进行了相关的练习和尝试,现在就该到了最后的整合了,依旧是以实现功能为目的,细节暂且不去管他. 因为我们实际项目后端用的是spring.spring mvc.mysql.mybatis,前台用的angular js,因此在整合时我也自己搭建使用了这样的环境. 1. 所使用的环境基础:eclipse4.4.mysql5.6.angularjs1.4.tomcat7.jdk1.7.maven3.2.spring4.0.9.acti

整合Acitiviti在线流程设计器(Activiti-Modeler 5.19)

1.概述前言 一直以来都是从事大量的工作流相关的项目,用过很多商用的工作流产品,包括国内与国外的,尽管商用的工作产品在UI操作上比较人性化,但个人用户觉得,这东西只需要一些初级用户,对于我们一直在为一些高级的客户提供一些专业的数据整合.流程梳理.系统间的数据穿透时,这些系统因为不开源,给项目的实施带来巨大的风险,在一些项目栽过跟头后,我更偏向于使用开源的平台了.但开源平台最大的难点是在于你是否有足够的技术人员来学习及掌握它,否则,它也一样面临项目实施失败的风险.后来在一些项目上使用JBPM4,A