整合Activiti Modeler到业务系统(或BPM平台)

标签: activiti modeler 业务 | 发表时间:2013-03-10 16:00 | 作者:
出处:http://www.kafeitu.me/

1. 为什么要整合

Activiti 5.10版本把原本独立的Activiti Modeler模块整合到了Activiti Explorer中,两者相结合使用起来很方便,通过Modeler设计的流程模型可以直接部署到引擎,也可以把已经部署的流程转换为Model从而在Modeler中编辑。

在实际应用中也有这样的需求,把Modeler整合到业务系统中可以供管理员使用,或者作为BPM平台的一部分存在,很遗憾官方没有给出如何整合Modeler的文档。

2. 整合工作

2.1 下载源码

首先需要从Github下载源码: https://github.com/Activiti/Activiti;可以直接用Git克隆,也可以下载zip格式的压缩包。

Activit源码结构

2.2 复制文件

复制的所有文件均在 activiti-webapp-explorer2目录中。

  1. editor复制到项目的webapp目录(与WEB-INF目录同级)
  2. src/main/resources中的 editor.html、stencilset.json、plugins.xml到项目 源码的根目录
  3. src/main/webapp中的 api、editor、explorer、libs到项目的webapp目录(与WEB-INF目录同级)

2.3 添加依赖


    org.activiti
    activiti-explorer
    5.12
    
        
            vaadin
            com.vaadin
        
        
            dcharts-widget
            org.vaadin.addons
        
        
            activiti-simple-workflow
            org.activiti
        
    


    org.activiti
    activiti-modeler
    5.12

2.4 添加Java类

添加一个 ExplorerRestApplication.java类保存到项目中,注册了一些REST路由。

package org.activiti.explorer.rest.application;

import org.activiti.editor.rest.application.ModelerServicesInit;
import org.activiti.rest.api.DefaultResource;
import org.activiti.rest.application.ActivitiRestApplication;
import org.activiti.rest.filter.JsonpFilter;
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);
    JsonpFilter jsonpFilter = new JsonpFilter(getContext());
    jsonpFilter.setNext(router);
    return jsonpFilter;
  }

}

2.5 配置web.xml

在web.xml文件中添加如下配置:



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




    RestletServlet
    /service/*

2.6 控制器

使用Spring MVC做了一个简单的封装,也可以使用其他的MVC实现。

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 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.codehaus.jackson.JsonNode;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.node.ObjectNode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.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")
  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() + "/service/editor?id=" + 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的xml文件
   */
  @RequestMapping(value = "export/{modelId}")
  public void export(@PathVariable("modelId") String modelId, HttpServletResponse response) {
    try {
      Model modelData = repositoryService.getModel(modelId);
      BpmnJsonConverter jsonConverter = new BpmnJsonConverter();
      JsonNode editorNode = new ObjectMapper().readTree(repositoryService.getModelEditorSource(modelData.getId()));
      BpmnModel bpmnModel = jsonConverter.convertToBpmnModel(editorNode);
      BpmnXMLConverter xmlConverter = new BpmnXMLConverter();
      byte[] bpmnBytes = xmlConverter.convertToXML(bpmnModel);

      ByteArrayInputStream in = new ByteArrayInputStream(bpmnBytes);
      IOUtils.copy(in, response.getOutputStream());
      String filename = bpmnModel.getMainProcess().getId() + ".bpmn20.xml";
      response.setHeader("Content-Disposition", "attachment; filename=" + filename);
      response.flushBuffer();
    } catch (Exception e) {
      logger.error("导出model的xml文件失败:modelId={}", modelId, e);
    }
  }

}

2.7 注意事项

如果使用Spring代理引擎,并且在项目中同时有activiti.cfg.xml文件(不管在main/resources还是test/resources目录),在activiti.cfg.xml里面的引擎中添加下面的配置参数,否则会导致打开Modeler的编辑页面时读取数据返回 204状态码。


引擎默认名称为default,ProcessEngines.getDefaultProcessEngine()查询时会先检索main/resources,然后再检索test/resources的activiti.cfg.xml和activiti-context.xml文件,所以当main/resources监测不到指定文件时就会导致该引擎被当做web应用的引擎对象,这样会导致有两个引擎,所以把引擎的名称改为非默认的“default”。

3. 效果截图

在最新的kft-activiti-demo版本(1.7.0)中已经集成了Activiti Modeler,可以在线访问,也可以下载源码学习如何配置。

登录 http://aws.kafeitu.me:8080/kft-activiti-demo后选择 流程管理-> 模型工作区菜单项即可。

kft-activiti-demo中的效果截图 kft-activiti-demo中的效果截图

转载自:

相关 [activiti modeler 业务] 推荐:

整合Activiti Modeler到业务系统(或BPM平台)

- - 咖啡兔
Activiti 5.10版本把原本独立的Activiti Modeler模块整合到了Activiti Explorer中,两者相结合使用起来很方便,通过Modeler设计的流程模型可以直接部署到引擎,也可以把已经部署的流程转换为Model从而在Modeler中编辑. 在实际应用中也有这样的需求,把Modeler整合到业务系统中可以供管理员使用,或者作为BPM平台的一部分存在,很遗憾官方没有给出如何整合Modeler的文档.

整合activiti在线流程设计器(ACTIVITI-MODELER 5.18.0)

- - 企业架构 - ITeye博客
一直以来都是从事大量的工作流相关的项目,用过很多商用的工作流产品,包括国内与国外的,尽管商用的工作产品在UI操作上比较人性化,但个人用户觉得,这东西只需要一些初级用户,对于我们一直在为一些高级的客户提供一些专业的数据整合、流程梳理、系统间的数据穿透时,这些系统因为不开源,给项目的实施带来巨大的风险,在一些项目栽过跟头后,我更偏向于使用开源的平台了.

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

- - 开源软件 - ITeye博客
整合Acitiviti在线流程设计器(Activiti-Modeler 5.18.0).         一直以来都是从事大量的工作流相关的项目,用过很多商用的工作流产品,包括国内与国外的,尽管商用的工作产品在UI操作上比较人性化,但个人用户觉得,这东西只需要一些初级用户,对于我们一直在为一些高级的客户提供一些专业的数据整合、流程梳理、系统间的数据穿透时,这些系统因为不开源,给项目的实施带来巨大的风险,在一些项目栽过跟头后,我更偏向于使用开源的平台了.

Activiti 5.11 发布,业务流程管理

- - 开源中国社区最新新闻
这是我第一次为Activiti的发布撰文,因为这次的发布我觉得很有必要和大家分享,这其中包含了我期待的新特性和已知问题的修复;而且还有一个重量级的模块 Activiti Modeler. 在5.8版本之前一直以每两个月一版的的频率发布,但是在5.8~5.10之间波动比较大,5.9和5.10都是5个月才发布一版,不过从5.11开始又开始恢复每两个月一版的频率了,我认为短周期的发布有利于占领市场,对于开发者来说能尽快修复比较严重的问题.

Activiti用户指南之Activiti的API

- - ITeye博客
 一、流程引擎的API和服务(services).      引擎的API是影响Activiti最常见的一种方法. 我们一开始最关注的中心是ProcessEngine,像之前描述的那样,流程引擎可以被多种方式创建. 从这个流程引擎里面,你能获得各个包含workflow/BPM方法的服务. 流程引擎和这些获得的服务是线程安全的.

Activiti学习笔记

- - 企业架构 - ITeye博客
第一个Activiti的HelloWorld. 获取核心ProcessEngine对象 2. 根据需求,获取对应的服务实例 3. 使用服务方法,做事情 * * @author Administrator * */ public class HelloWorld {. // 加载核心API ProcessEngine.

Activiti工作流demo

- - CSDN博客综合推荐文章
继上篇《 Activiti工作流的环境配置》.        前几篇对Activiti工作流进行了介绍,并讲解了其环境配置. 本篇将会用一个demo来展示Activiti工作流具体的体现,直接上干货.        以HelloWorld程序为例.       首先说一下业务流程,员工张三提交了一个申请,然后由部门经理李四审核,审核通过后再由总经理王五审核,通过则张三申请成功.

Activiti - 设置会签

- - 企业架构 - ITeye博客
前些天在群里聊工作流和Activiti,群里有人分享了自己的工作流引擎开源项目,大伙纷纷问这问那(比如为什么突然自己搞个process engine、有没有eclipse plugin、能不能绘制流程图等等). 现实生活中的工作流程,我们也经常碰到需要会签的情况,支持会签是很必要的. 正好有两个人问道:支持会签吗.

activiti工作流使用

- - 行业应用 - ITeye博客
activiti 开发流程. JBPM 与 Activiti. jBPM项目于2002年3月由Tom Baeyens发起,2003年12月发布1.0版本. 2004年10月18日,发布了2.0版本,并在同一天加入了JBoss. 2011 年 jBPM的创建者Tom Baeyens离开JBoss了, 他的离开产生了两个结果:.

ACTIVITI 学习笔记 - 监听

- - 企业架构 - ITeye博客
ACTIVITI 学习笔记 - 监听. 所有分发的事件都是org.activiti.engine.delegate.event.ActivitiEvent的子类. 监听器监听的流程引擎已经创建完毕,并准备好接受API调用. 监听器监听的流程引擎已经关闭,不再接受API调用. 创建了一个新实体,初始化也完成了.