Fork me on GitHub
27 Dec 2015
分享到:
Comments

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

这又是一片迟来的博客,上一篇博文还是2014年4月24日写的,因为很多内容都在书(《Activiti实战》)里了已经有详细的解释了,不过由于书里面使用的是5.16.4版本,从5.17.0版本后Activiti Modeler的整合方式有些变化,所以写此博问作为补充内容。

声明

  1. 此教程适合Activiti 5.17+版本。
  2. 本博客所涉及的内容均可在kft-activiti-demo中找到。
  3. 在线demo可以访问 http://demo.kafeitu.me:8080/kft-activiti-demo 菜单路径:管理模块 -> 流程管理 -> 模型工作区,可以『创建』或者『编辑』模型

1. 简介

上一篇介绍整合Activiti Modeler《整合Activiti Modeler到业务系统(或BPM平台)》已经有2年多时间了,自从Activiti 5.17版本发布以后该教程已经不适用了,很多网友也反馈不知道怎么把Activiti Modeler整合到自己的项目中去,为此抽时间为适配5.17+版本的集成方法整理成这篇博文,希望对有需求的网友有帮助。

最新版本的kft-activiti-demo已经使用了5.17+版本的Activiti,并且集成了最新的Activiti Modeler组件,可以下载最新源码:https://github.com/henryyan/kft-activiti-demo

1.1 新版Activiti Modeler特性

先来欣赏一下新版的界面,相比上一版漂亮了许多,调性高了~~~

新版Activiti Modeler

界面布局:上(工具区)、左(组件类目)、右(工作区)、右下(属性区)

Activiti Modeler内部的实现上还是以oryx为图形组件为内核,用angular.js作为界面基本元素的基础组件以及调度oryx的API。

2. 官方Activiti Explorer的集成方式

先从Github下载官方Activiti源码,地址:https://github.com/Activiti/Activiti

2.1 Activiti Exploer的内部结构-Java

源码目录(如果是zip下载请先解压缩)中找到modules/activiti-webapp-explorer2/src/main子目录,结构如下:

├── assembly
├── java
│   └── org
│       └── activiti
├── resources
│   └── org
│       └── activiti
└── webapp
    ├── META-INF
    ├── VAADIN
    │   ├── themes
    │   └── widgetsets
    ├── WEB-INF
    ├── diagram-viewer
    │   ├── images
    │   └── js
    └── editor-app
        ├── configuration
        ├── css
        ├── editor
        ├── fonts
        ├── i18n
        ├── images
        ├── libs
        ├── partials
        ├── popups
        └── stencilsets

我们需要关注的目录是webapp/editor-app,以及java/org/activiti,目录结构:

Activiti Explorer源码目录

新版本的Activiti Explorer放弃了XML方式的配置方式,采用Bean Configuration的方式代替,上图中org/activiti/explorer/conf包中就是各种配置,在org/activiti/explorer/servlet/WebConfigurer类用Servlet 3.0方式配置Servlet映射关系,映射的路径为/service/*

2.2 Activiti Exploer的内部结构-Web

新版本Activiti Modeler的Web资源不再像旧版那么散乱,新版本只需要关注:

  • src/main/webapp/editor-app:目录中包含设计器里面所有的资源:angular.js、oryx.js以及配套的插件及css
  • src/main/webapp/modeler.html:设计器的主页面,用来引入各种web资源
  • src/main/resources/stencilset.json: bpmn标准里面各种组件的json定义,editor以import使用。

3. 整合到自己的项目中

了解过网友的需求不知道如何整合新版Activiti Modeler的原因有两个:

  1. 不知道怎么把注解的方式转换为XML方式
  2. editor-app目录的结构位置
  3. 和自己应用的整合参数配置

3.1 Activiti Rest接口与Spring MVC配置

3.1.1 Maven依赖

Activiti Modeler对后台服务的调用通过Spring MVC方式实现,所有的Rest资源统一使用注解RestController标注,所以在整合到自己项目的时候需要依赖Spring MVC,Modeler模块使用的后台服务都存放在activiti-modeler模块中,在自己的项目中添加依赖:

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-modeler</artifactId>
    <version>5.19.0</version>
</dependency>
<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-diagram-rest</artifactId>
    <version>5.19.0</version>
</dependency>

模块作用:

  • activiti-modeler模块提供模型先关的操作:创建、保存、转换json与xml格式等
  • activiti-diagram-rest模块用来处理流程图有关的功能:流程图布局(layout)、节点高亮等

3.1.2 准备基础服务类

复制文件(https://github.com/henryyan/kft-activiti-demo/tree/master/src/main/java/org/activiti/explorer) 里面的java文件到自己项目中。

3.1.3 Activiti Spring配置

创建文件src/main/resources/beans/beans-activiti.xml定义Activiti引擎的beans:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd">

    <context:component-scan
            base-package="org.activiti.conf,org.activiti.rest.editor">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>

    <!-- 单例json对象 -->
    <bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"/>

    <!-- 引擎内部提供的UUID生成器,依赖fastxml的java-uuid-generator模块 -->
    <bean id="uuidGenerator" class="org.activiti.engine.impl.persistence.StrongUuidGenerator" />

    <!-- Activiti begin -->
    <bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
        <property name="dataSource" ref="dataSource"/>
        <property name="transactionManager" ref="transactionManager"/>
        <property name="databaseSchemaUpdate" value="true"/>
        <property name="jobExecutorActivate" value="true"/>
    </bean>

    <bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
        <property name="processEngineConfiguration" ref="processEngineConfiguration"/>
    </bean>

    <!-- 7大接口 -->
    <bean id="repositoryService" factory-bean="processEngine" factory-method="getRepositoryService"/>
    <bean id="runtimeService" factory-bean="processEngine" factory-method="getRuntimeService"/>
    <bean id="formService" factory-bean="processEngine" factory-method="getFormService"/>
    <bean id="identityService" factory-bean="processEngine" factory-method="getIdentityService"/>
    <bean id="taskService" factory-bean="processEngine" factory-method="getTaskService"/>
    <bean id="historyService" factory-bean="processEngine" factory-method="getHistoryService"/>
    <bean id="managementService" factory-bean="processEngine" factory-method="getManagementService"/>

</beans>

在spring初始化的时候引入即可,例如在web.xml中使用通配符方式:

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:/beans/beans-*.xml</param-value>
</context-param>

3.1.4 Spring MVC配置

创建文件WEB-INF/spring-mvc-modeler.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

    <!-- 自动扫描且只扫描@Controller -->
    <context:component-scan base-package="org.activiti.rest.editor,org.activiti.rest.diagram">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <mvc:annotation-driven />
</beans>

上面XML中告知spring mvc扫描路径为**

3.1.5 web.xml中配置Servlet服务

web.xml中配置下面的Servlet:

<servlet>
    <servlet-name>ModelRestServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring-mvc-modeler.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>ModelRestServlet</servlet-name>
    <url-pattern>/service/*</url-pattern>
</servlet-mapping>

3.1.6 模型设计器的Web资源

  1. 直接从Activiti Explorer中复制文件modeler.html文件到src/main/webapp目录即可,该文件会引入定义基本的布局(div)、引入css以及js文件。

  2. 修改editor-app/app-cfg.js文件的contextRoot属性为自己的应用名称,例如/kft-activiti-demo/service

3.1.7 模型控制器

《整合Activiti Modeler到业务系统(或BPM平台)》中已经介绍过ModelController类的作用了,这里需要在基础上稍微做一点调整:

  • create方法中在创建完Model后跳转页面由service/editor?id=改为modeler.html?modelId=
  • 当从模型列表编辑某一个模型时也需要把路径修改为modeler.html?modelId=

4. 整合Activiti Rest

有了Activiti Modeler的基础只需要依葫芦画瓢即可。

4.1 Maven依赖

<dependency>
    <groupId>org.activiti</groupId>
    <artifactId>activiti-rest</artifactId>
    <version>5.19.0</version>
</dependency>

4.3 Activiti组件包扫描

文件src/main/resources/beans/beans-activiti.xmlcontext:component-scan标签的base-package属性中添加org.activiti.rest.service包,包里面包含了所有Rest API的接口Rest Controller。

4.4 添加Rest安全认证组件

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();
    }
}

4.5 spring mvc配置文件

创建文件WEB-INF/spring-mvc-rest.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">

    <!-- 自动扫描且只扫描@Controller -->
    <context:component-scan base-package="org.activiti.rest">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
    </context:component-scan>

    <mvc:annotation-driven />
</beans>

4.6 配置Servlet映射

<servlet>
    <servlet-name>RestServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring-mvc-rest.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>RestServlet</servlet-name>
    <url-pattern>/rest/*</url-pattern>
</servlet-mapping>

4.7 访问Rest接口

现在启动应用可以访问 http://localhost:8080/your-app/rest/management/properties 以Rest方式查看引擎的属性列表,如果在网页中访问会提示输入用户名密码;也可以访问在线demo测试 http://demo.kafeitu.me:8080/kft-activiti-demo/rest/management/properties (用户名:kafeitu,密码:000000)

5. 结束语

以上步骤如果在实施过程中有问题可以参考kft-activiti-demo中的配置,有其他问题可以在本博客中留言或者到QQ群问询。

最后再广告一下我的书《Activiti实战》,Tijs强力推荐的哦;同时也感谢一直支持和活跃在Activiti社区的你。

24 Apr 2014
分享到:
Comments

集成Diagram Viewer跟踪流程

首先这是一篇迟来的教程,因为从5.12版本(目前最新版本为5.15.1)开始就已经提供了Diagram Viewer这个流程图跟踪组件,不管如何总归有人需要用到,所以我觉得还是要和大家分享一下。

1. 前言

目前被大家所采用的流程图跟踪有两种方式:

  • 一种是由引擎后台提供图片,可以把当前节点标记用红色
  • 一种是比较灵活的方式,先用引擎接口获取流程图(原图),然后再通过解析引擎的Activity对象逐个解析(主要是判断哪个是当前节点),最后把这些对象组成一个集合转换成JSON格式的数据输出给前端,用Javascript和Css技术实现流程的跟踪

这两种方式在kft-activiti-demo中都有演示,这里就不介绍了,参考流程跟踪部门代码即可。

2. Diagram Viewer简介

Diagram Viewer是官方在5.12版本中添加的新组件,以Raphaël为基础库,用REST(参考:《如何使用Activiti Rest模块》)方式获取JSON数据生成流程图并把流程的处理过程用不同的颜色加以标注,最终的效果如下图所示。

在应用中使用时也很方便,把这个组件的源码复制到项目中再配置一个REST拦截器,最后拼接一个URL即可;举个例子:

http://demo.kafeitu.me/kft-activiti-demo/diagram-viewer/index.html?processDefinitionId=leave-jpa:1:22&processInstanceId=27

这个URL中有两个参数:

  • processDefinitionId: 流程定义ID
  • processInstanceId: 流程实例ID

3. 集成Diagram Viewer

3.1 创建REST路由类

REST路由类源码在官方的Activiti Explorer里面有提供,代码如下:

package org.activiti.explorer.rest;

import org.activiti.rest.common.api.DefaultResource;
import org.activiti.rest.common.application.ActivitiRestApplication;
import org.activiti.rest.common.filter.JsonpFilter;
import org.activiti.rest.diagram.application.DiagramServicesInit;
import org.activiti.rest.editor.application.ModelerServicesInit;
import org.restlet.Restlet;
import org.restlet.routing.Router;

public class ExplorerRestApplication extends ActivitiRestApplication {
  
  public ExplorerRestApplication() {
    super();
  }
  /**
   * Creates a root Restlet that will receive all incoming calls.
   */
  @Override
  public synchronized Restlet createInboundRoot() {
    Router router = new Router(getContext());
    router.attachDefault(DefaultResource.class);
    ModelerServicesInit.attachResources(router);
    DiagramServicesInit.attachResources(router);
    JsonpFilter jsonpFilter = new JsonpFilter(getContext());
    jsonpFilter.setNext(router);
    return jsonpFilter;
  }

}

把这个路由配置到web.xml中:


    ExplorerRestletServlet
    org.restlet.ext.servlet.ServerServlet
    
        
        org.restlet.application
        org.activiti.explorer.rest.ExplorerRestApplication
    



    ExplorerRestletServlet
    /service/*

3.2 复制Diagram Viewer组件

在官方提供的Zip文件(可以从www.activiti.org/download.html下载)中有一个wars目录,用压缩工具解压activiti-explorer.war文件,目录结构如下图:

diagram-viewer复制到项目的webapp目录(或者是WebRoot目录)下,在项目中需要跟踪的地方拼接访问diagram-viewer/index.html的URL即可,别忘记了刚刚介绍的两个重要参数。

http://demo.kafeitu.me/kft-activiti-demo/diagram-viewer/index.html?processDefinitionId=leave-jpa:1:22&processInstanceId=27

URL中有两个参数:

  • processDefinitionId: 流程定义ID
  • processInstanceId: 流程实例ID

这是一个独立的页面,你可以直接打开它或者把它嵌入在一个对话框里面(kft-activiti-demo就是用的嵌入方式)。

18 Apr 2014
分享到:
Comments

在Activiti中集成JPA(解决动态表单生成的大量数据)

1. 为何集成JPA

在《比较Activiti中三种不同的表单及其应用》一文中介绍了不同表单的特点以及表现形式,相信这是每个初学者都会面临表单类型的选择。

如果选择了使用动态表单那么将面临一个比较“严峻”的问题——大数据量,我们知道动态表单的内容都保存在一张表中(ACT_HI_DETAIL),我们也清楚动态表单中每一个Field都会在该表中插入一条记录,假如一个流程共有20个字段,这个数据量大家可以计算一下,每天多少个流程实例,每个月、每年多少?

日积月累的大数据会影响系统的性能,尤其涉及到关联查询时影响更深,除了性能之外动态表单还有一个弊端那就是数据是以的形式存储没有任何数据结构可言,流程运行中生成的数据很难被用于分析、查询,如何破解嘞?

2. 如何集成JPA

Activiti除了核心的Engine之外对企业现有的技术、平台、架构都有所支持,对于业务实体的持久化当然也会有所支持,那就是EJB的标准之一)——JPA,引擎把JPA的API引入到了内部,使用JPA功能的时候只需要把entityManagerFactory配置到引擎配置对象(参考:谈谈Activiti的引擎与引擎配置对象)即可。

参考用户手册的JPA章节,介绍了引擎配置对象中的几个jpa有关的属性,如下:

  • jpaPersistenceUnitName: 使用持久化单元的名称(要确保该持久化单元在类路径下是可用的)。根据该规范,默认的路径是/META-INF/persistence.xml)。要么使用 jpaEntityManagerFactory 或者jpaPersistenceUnitName。
  • jpaEntityManagerFactory: 一个实现了javax.persistence.EntityManagerFactory的bean的引用。它将被用来加载实体并且刷新更新。要么使用jpaEntityManagerFactory 或者jpaPersistenceUnitName。
  • jpaHandleTransaction: 在被使用的EntityManager 实例上,该标记表示流程引擎是否需要开始和提交/回滚事物。当使用Java事物API(JTA)时,设置为false。
  • jpaCloseEntityManager: 该标记表示流程引擎是否应该关闭从 EntityManagerFactory获取的 EntityManager的实例。当EntityManager 是由容器管理的时候需要设置为false(例如 当使用并不是单一事物作用域的扩展持久化上下文的时候)。

2.1 配置持久化单元或者EntityManagerFactory

要在引擎中使用JPA需要提供EntityManagerFactory或者提供持久化单元名称(引擎会自动查找最终获取到EntityManagerFactory对象),在使用的时候可以根据自己的实际情况进行选择,在kft-activiti-demo中使用了jpaEntityManagerFactory属性注入EntityManagerFactory对象的方式。

2.2 Standalone模式的JPA配置

    
    
    

2.3 Spring(托管)模式的JPA配置

    
    
    

3. 实例分析

在最新版本(1.10)的kft-activiti-demo中添加了JPA演示,大家可以从Github上下载源码查看源码。

请假流程-JPA版本

3.1 相关说明

  • 流程定义文件:leave-jpa.bpmn
  • 实体文件:me.kafeitu.demo.activiti.entity.oa.LeaveJpaEntity
  • 实体管理器:me.kafeitu.demo.activiti.service.oa.leave.LeaveEntityManager

3.2 创建实体

在流程定义文件中定义了一个流程的start类型监听器:


  

这个监听器的触发的时候会执行一个表达式,调用名称为leaveEntityManager的Spring Bean对象的newLeave方法,并且把引擎的Execution对象传递过去,得到一个LeaveJpaEntity对象后设置到引擎的变量中(名称为leave)。

下面是LeaveEntityManager.java的代码:

@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;
    
    ...
}
@Service
public class LeaveEntityManager {

    @PersistenceContext
    private EntityManager entityManager;
    
    /* 把流程变量的值赋值给JPA实体对象并保存到数据库 */
    @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;
    }

    public LeaveJpaEntity getLeave(Long id) {
        return entityManager.find(LeaveJpaEntity.class, id);
    }

}

当启动流程后查看表LEAVE_JPA中的数据与表单填写的一致。

3.3 在流程中更改实体的值

部门领导或者人事审批节点完成时需要把审批结果更新到LeaveJpaEntity属性中(即更新表LEAVE_JPA),所以在这两个任务上添加一个complete类型的监听器,如下所示:


    
        
    



    
        
    

3.4 流程结束后删除表单数据

熟悉Activiti表的应该知道表单数据会保存在表ACT_HI_DETAIL中,特性是字段TYPE_字段的值为FormProperty,我们只要根据流程实例ID过滤删除记录就可以清理掉已经结束流程的表单数据。

在最新版本的Demo中(1.10版本)添加了一个类用来执行SQL:

@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;
    }

}

流程中定义了一个流程级别的结束监听器me.kafeitu.demo.activiti.service.oa.leave.LeaveProcessEndListener

@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);
    }
}

3.5 已知问题(未解决)

由于引擎的Bug导致数据不能完整删除

图中的三条数据因为是在销假任务完成后设置的,不知道是不是引擎的Bug导致插入这三个表单属性比调用流程结束监听器还晚(从引擎的日志中可以分析出来)导致这三条记录不能被删除,因为在删除的时候这三条数据还没有插入到数据库。

这个问题后面会继续跟踪,解决了会在这里更新!!!

23 Jan 2014
分享到:
Comments

剖析Activiti的Activity

1. 窥视Activity内部

在设计流程时每一个组件在Activiti中都可以称之为——Activity,部署流程时引擎把XML文件保存到数据库,当启动流程、完成任务时会从数据库读取XML并转换为Java对象,很多人想在处理任务时获取任务的一些配置,例如某个任务配置了哪些监听器或者条件Flow配置了什么条件表达式。

2. 代码

下面的代码做了简单的演示,根据不同的Activity类型输出属性,读者可以继续探索其他不同类型Activity的属性,最终可以获取到所有Activity的属性。

3. 输出结果示例

{taskDefinition=org.activiti.engine.impl.task.TaskDefinition@19c6e4d1, default=null, name=部门领导审批, documentation=null, type=userTask}
{conditionText=${!deptLeaderPass}, condition=org.activiti.engine.impl.el.UelExpressionCondition@50d8628f, name=不同意, documentation=null}
{conditionText=${deptLeaderPass}, condition=org.activiti.engine.impl.el.UelExpressionCondition@2e2ec3c0, name=同意, documentation=null}
{taskDefinition=org.activiti.engine.impl.task.TaskDefinition@3589f0, default=null, name=调整申请, documentation=null, type=userTask}
{taskDefinition=org.activiti.engine.impl.task.TaskDefinition@3af2ebab, default=null, name=人事审批, documentation=null, type=userTask}
{conditionText=${hrPass}, condition=org.activiti.engine.impl.el.UelExpressionCondition@224e45c9, name=同意, documentation=null}
{conditionText=${!hrPass}, condition=org.activiti.engine.impl.el.UelExpressionCondition@40c7a0b7, name=不同意, documentation=null}
{taskDefinition=org.activiti.engine.impl.task.TaskDefinition@72086f9a, default=null, name=销假, documentation=null, type=userTask}
{conditionText=${reApply}, condition=org.activiti.engine.impl.el.UelExpressionCondition@7d721f3, name=重新申请, documentation=null}
{conditionText=${!reApply}, condition=org.activiti.engine.impl.el.UelExpressionCondition@3cf5dc8a, name=结束流程, documentation=null}
{name=Start, documentation=null, type=startEvent}
{name=End, documentation=null, type=endEvent}

更多博客

在Activiti中使用UUID作为主键生成策略 30 Aug 2013 Comments
Activiti 5.13修复版本5.13.1-kft发布 17 Jul 2013 Comments
一个基于Maven的配置文件管理成功案例 29 Jun 2013 Comments
利用100行代码动态创建并部署流程 27 May 2013 Comments
谈谈Activiti的引擎与引擎配置对象 19 Apr 2013 Comments
博客论坛正式上线 13 Apr 2013 Comments
Activiti 5.12.X 衍生版本发布 05 Apr 2013 Comments
IntelliJ IDEA中文乱码解决办法 26 Mar 2013 Comments
Activiti Designer 5.12.0 发布 23 Mar 2013 Comments
Activiti快速入门项目kft-activiti-demo 1.7.0版本发布 10 Mar 2013 Comments
整合Activiti Modeler到业务系统(或BPM平台) 10 Mar 2013 Comments
Activiti 5.12发布 06 Mar 2013 Comments
利用静态服务提升读取Activiti流程图的性能 14 Feb 2013 Comments
如何使用Activiti Rest模块 12 Jan 2013 Comments
kft-activiti-demo 1.5.0 发布 15 Dec 2012 Comments
Activiti Explorer 5.11登录页面乱码解决办法 15 Dec 2012 Comments
jQuery UI Portlet V1.1.0 发布 08 Dec 2012 Comments
Activiti 5.11发布 05 Dec 2012 Comments
基于jQuery UI的Portlet插件—jQuery UI Portlet 22 Nov 2012 Comments
Activiti 5.10支持直接部署扩展名为bpmn的流程文件 22 Oct 2012 Comments
新版Activiti Modeler发布以及教程 30 Sep 2012 Comments
Activiti Explorer中文汉化 30 Sep 2012 Comments
activiti:initiator的作用及其使用 14 Sep 2012 Comments
jqGrid启用列冻结之后列高度不一致问题解决办法 25 Aug 2012 Comments
谈谈Activiti中流程对象之间的关系 09 Aug 2012 Comments
比较Activiti中三种不同的表单及其应用 05 Aug 2012 Comments
Activiti入门,学习资源索引 04 Aug 2012 Comments
Zsh(oh-my-zsh)的Maven自动提示插件(zsh-maven-complection) 18 Jul 2012 Comments
如何打包Activiti的流程资源文件(bpmn20.xml、form、png) 18 Jul 2012 Comments
如何使用Signavio打包Activiti Modeler 07 Jun 2012 Comments
Activiti快速入门项目-kft-activiti-demo 26 May 2012 Comments
Activiti设置流程发起用户信息 20 May 2012 Comments
我是如何在Linux(Ubuntu)上工作的? 19 May 2012 Comments
让Activiti记录变量历史信息 18 May 2012 Comments
从Activiti Designer5.8升级到5.9遇到的问题 01 May 2012 Comments
同步或者重构Activiti Identify用户数据的多种方案比较 23 Apr 2012 Comments
在Linux(Ubuntu)+Nginx安装配置AjaXplorer 14 Apr 2012 Comments
在Ubuntu(Debian)上安装最新版Git 10 Apr 2012 Comments
在Ubuntu上安装Git1.7.10-rc4(中文化) 05 Apr 2012 Comments
推荐:jQuery提示插件qTip2 03 Apr 2012 Comments
Git Submodule使用完整教程 27 Mar 2012 Comments
我最喜爱的工具-oh-my-zsh 25 Mar 2012 Comments
工作流引擎Activiti使用总结 22 Mar 2012 Comments
从Wordpress迁移到Github 21 Mar 2012 Comments
Linux(Ubuntu)环境安装配置Nginx+Dokuwiki 04 Feb 2012 Comments
Linux下springside4快捷脚本(quick-start、generate-project) 09 Dec 2011 Comments
Linux下springside3快捷脚本(quick-start、generate-project) 13 Aug 2011 Comments
jQuery UI及其插件在企业环境的应用总结 24 Jul 2011 Comments
Ubuntu配置ngnix+phpmyadmin 16 Jul 2011 Comments
Ubuntu安装ORACLE-XE 15 Jul 2011 Comments
Windows Server 2008 R2 X64安装Oracle 10g R2后不能创建数据库问题解决办法 26 Jun 2011 Comments
推荐:国内第一本Maven书籍——《Maven实战》 19 Nov 2010 Comments
Maven多模块布局实例详解 11 Nov 2010 Comments
CAS单点登录(SSO)完整教程(2012-02-01更新) 05 Nov 2010 Comments
maven-war-plugin插件的warSourceExcludes和packagingExcludes参数的区别 03 Nov 2010 Comments
公布一下我的Evernote分享地址 03 Nov 2010 Comments
Maven常见问题收集(持续更新-2010-12-15) 01 Nov 2010 Comments
《Maven实战》最新消息,11月初出版 27 Oct 2010 Comments
jquery.validate插件remote规则相同值不验证的问题解决办法 25 Oct 2010 Comments
城市级联选择插件jquery.area2select闪亮登场(前后台设计) 18 Oct 2010 Comments
工欲善其事必先利其器--Java Web快速开发框架--Springside 12 Oct 2010 Comments
Struts2 Annotation实现文件下载功能 03 Oct 2010 Comments
利用Windows的计划任务自动更新最新的Chromium 01 Oct 2010 Comments
利用JavaScript获取窗口/Body的宽度和高度(让jqGrid自适应窗口大小) 20 Aug 2010 Comments
Apache Asia Roadshow 2010 Juven Maven PPT和视频下载 16 Aug 2010 Comments
Hudson系列教程 15 Aug 2010 Comments
Apache Asia Roadshow 2010归来 15 Aug 2010 Comments
推荐精选3枚jQuery遮罩插件 12 Aug 2010 Comments
Eclipse+Maven+WTP+Tomcat不能Run On Server其中一个原因 10 Aug 2010 Comments
Springside3.3.3报错:java.lang.NoClassDefFoundError: org/codehaus/classworlds/Launcher解决办法 09 Aug 2010 Comments
Maven学习引导 07 Aug 2010 Comments
工欲善其事,必先利其器 30 Jul 2010 Comments
为jstree添加双击事件切换[展开/收缩]功能 19 Jun 2010 Comments
JasperReports iReport导出PDF中文解决办法 30 May 2010 Comments
[转][推荐]15 个 JavaScript Web UI 库 20 May 2010 Comments
解决a different object with the same identifier value was already associated with the session错误 18 May 2010 Comments
jqGrid查询中文乱码问题解决办法(2011-11-11) 23 Apr 2010 Comments
Maven下用mvn assembly:assembly打包class文件重复 22 Apr 2010 Comments
[转][评论]谷歌重申不过滤搜索结果 做好停止中国业务准备 12 Mar 2010 Comments
Win7下不能安装Oracle11g解决办法 03 Mar 2010 Comments
直逼 Flash 的流畅感:jQuery 运动特效展示 02 Mar 2010 Comments
IE6浏览器葬礼的背后 02 Mar 2010 Comments
[转][推荐]程序员们,请珍爱自己的身体 25 Feb 2010 Comments
Sexy Buttons(Web 按钮[图标]素材) 10 Feb 2010 Comments
jQuery 1.4.1 中文文档 CHM 版发布 02 Feb 2010 Comments
转:关于web2.0网站易用性设计的一些原则 27 Jan 2010 Comments
jQuery1.4 API 区别与更新中文版 19 Jan 2010 Comments
分享:Java日期工具类 15 Jan 2010 Comments
jQuery 1.4 正式版发布啦(14 Days of jQuery) 15 Jan 2010 Comments
推荐:基于jQuery开发仿Google Calendar(jQuery Week Calendar) 12 Jan 2010 Comments
推荐:2009 年度最佳 jQuery 插件 12 Dec 2009 Comments
程序员的学历有多重要 18 Nov 2009 Comments
推荐:正则表达式口诀及教程 03 Nov 2009 Comments
Json-lib 与 hibernate 共同使用的问题 24 Oct 2009 Comments
备忘:金格、用友CELL不能在IE8下使用的解决办法 14 Oct 2009 Comments
22岁生日 22 Aug 2009 Comments
使用hibernate和json-lib时忽略属性和集合 04 Aug 2009 Comments
Hibernate的映射类型 hibernate mysql映射类型 30 Jul 2009 Comments
叽歪怎么了? 29 Jul 2009 Comments
[推荐]改进的提示插件-jQuery.hiAlerts.1.0 27 Jul 2009 Comments
《疯狂程序员》一书中的奥秘 23 Jul 2009 Comments
Twitter用户发起“拒绝IE6”请愿活动 18 Jul 2009 Comments
推荐一个ajax资源站点 16 Jul 2009 Comments
做了一次集成服务:基于weebox和simpletree的dialogtree诞生了 16 Jul 2009 Comments
站点GBK编码下jQuery Ajax中文乱码解决方案 01 Jul 2009 Comments
简单实现在基于Java的AJAX环境下未登录自动跳转流程详解(spring代理struts的action) 22 Jun 2009 Comments
如何判断一个请求是否为AJAX请求 22 Jun 2009 Comments
夏天到了,终于收到迟来的WordPress T恤了 08 Jun 2009 Comments
jQuery性能优化指南 23 May 2009 Comments
心系5.12(2009年5.12日 2:28分我们集体默哀3分钟) 11 May 2009 Comments
2009.5.1~5.3杭州之旅(露营、雨中游西湖) 05 May 2009 Comments
IE中丢失session问题解决办法 21 Apr 2009 Comments
6个你必须用到AJAX的地方与6个不必用到的地方 04 Apr 2009 Comments
庆祝博客PageRank提升到了3/10 04 Apr 2009 Comments
wordcamp 2009 in ShangHai归来 04 Apr 2009 Comments
推荐国外著名的xhtml+css模板 29 Mar 2009 Comments
一行jQuery代码打印九九乘法表 25 Mar 2009 Comments
IE浏览器下的JS实用调试小工具——fullsource(2K) 11 Mar 2009 Comments
jQuery.plugin——强大的遮罩层(nyroModal) 02 Mar 2009 Comments
HR教你怎么投简历 01 Mar 2009 Comments
实例解析java + jQuery + json工作过程(获取JSON数据) 28 Feb 2009 Comments
自己动手定制ajax loading图片 26 Feb 2009 Comments
实例解析java + jQuery + json工作过程(登录) 24 Feb 2009 Comments
推荐一个不错的js编辑工具Spket IDE for eclipse 22 Feb 2009 Comments
模拟google相册鼠标移动提示信息 22 Feb 2009 Comments
推荐日期选择组件My97 DatePicker 21 Feb 2009 Comments
既爱又恨Firefox 21 Feb 2009 Comments
转:Javascript 脚本的调试经验 21 Feb 2009 Comments
分享:JavaScript在线压缩工具 21 Feb 2009 Comments
从Google搜索联想到了jQuery 20 Feb 2009 Comments
单表查询树形结构的SQL语句 20 Feb 2009 Comments
申请友链及说明 20 Feb 2009 Comments
我暴露了程序员的习惯 19 Feb 2009 Comments
推荐jQuery插件系列——表单验证formValidator 18 Feb 2009 Comments
jQuery1.3中文API下载(HTML、chm版) 14 Feb 2009 Comments
基于Java、jQuery应用的账务管理系统开源了(09.3.19更新) 14 Feb 2009 Comments
程序员的十种级别,看看你属于哪个级别的程序员 14 Feb 2009 Comments
基于Java、jQuery开发的账务管理系统(个人版)即将开源 13 Feb 2009 Comments
推荐使用轻量级ajax框架-jQuery 10 Feb 2009 Comments
基于jQuery开发的账务管理系统(个人版)演示 08 Feb 2009 Comments
优秀程序员的两大要素:懒+笨 08 Feb 2009 Comments
《jQuery in Action》中文版即将上市 08 Feb 2009 Comments
经典:从追MM谈Java的23种设计模式 07 Feb 2009 Comments
javascript中字符串累加的性能优化(String和StringBuffer) 07 Feb 2009 Comments
出现net.sf.json.JSONException: There is a cycle in the hierarchy异常的解决办法 07 Feb 2009 Comments
关于WEB开发中引入javascript文件方式的一点建议 07 Feb 2009 Comments