• Activiti CamelTask(骆驼任务)


    Activiti CamelTask(骆驼任务)

    作者:Jesai

     

    人生想讲个不成熟的建议

     

     

    前言:

    Camel任务可以从Camel发送和介绍消息,由此强化了activiti的集成功能。 注意camel任务不是BPMN 2.0规范定义的官方任务。 (它也没有对应的图标)。 在activiti中,camel任务时由专用的服务任务实现的。

    什么是Camel?

    Camel能够在大量的领域语言中让你定义路由以及中间规则,包括基于Java的Fluent API,Spring或者Blueprint XML配置文件,甚至是Scala(是一种基于JVM,集合了面向对象编程和函数式编程优点的高级程序设计语言)DSL。 您能够通过你的IDE或者Java、Scala或者XML编辑器里获得智能化路由规则补全功能。

    camel首先是一个规则引擎。其次才是一个开源项目。

    Apache Camel是Apache基金会下的一个开源项目,它是一个基于规则路由和中介引擎,提供企业集成模式的Java对象的实现,通过应用程序接口(或称为陈述式的Java领域特定语言(DSL))来配置路由和中介的规则。领域特定语言意味着Apache Camel支持你在的集成开发工具中使用平常的,类型安全的,可自动补全的Java代码来编写路由规则,而不需要大量的XML配置文件。同时,也支持在Spring中使用XML配置定义路由和中介规则。

    Camel提供的基于规则的路由(Routing)引擎

    from().to().to()

    这种表述可以使用Camel定义的DSL语言,xml语言以及scala语言。如下例:

    from(“file:path").to("activemq:queue:queuename") 将某文件,读入并写入到ActiveMQ的JMS中。

    form("file:path").to("ftp://url")将一个文件,读入并写入到ftp某目录中。

     

    开发涉及的jar包

    camel-core-2.19.1.jar

    camel-spring-2.19.1.jar

    activiti-camel-5.22.0.jar

    Camel任务图标

     

    注意:camel任务不是BPMN 2.0标准,它只是Activiti的一个扩展。

    流程图设计以及配置:

     

    这是一个非常简单的流程图,只有开始和结束、camel任务节点。实际应用中根据实际情况扩展。

    流程图源码:

     1 <?xml version='1.0' encoding='UTF-8'?>
     2 
     3 <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="http://www.activiti.org/processdef">
     4 
     5   <process id="CamelProcess" isExecutable="true">
     6 
     7     <startEvent id="sid-80400B65-221F-4DE2-A7AF-1788341E7FAA">
     8 
     9       <extensionElements>
    10 
    11         <activiti:executionListener event="start" class="light.mvc.workflow.taskListener.CamelListenerImpl" />
    12 
    13       </extensionElements>
    14 
    15     </startEvent>
    16 
    17     <serviceTask id="MyCamelCall" name="camel任务" activiti:type="camel" />
    18 
    19     <endEvent id="sid-6920138F-F17F-43A3-8C54-D339AC234DF8" />
    20 
    21     <sequenceFlow id="sid-23D8E093-77BF-4D8A-8954-3730952ADEF6" sourceRef="MyCamelCall" targetRef="sid-6920138F-F17F-43A3-8C54-D339AC234DF8" />
    22 
    23     <sequenceFlow id="sid-7B6E8FB0-B1F6-425A-8897-C9CF6A2050CB" sourceRef="sid-80400B65-221F-4DE2-A7AF-1788341E7FAA" targetRef="MyCamelCall" />
    24 
    25   </process>
    26 
    27   <bpmndi:BPMNDiagram id="BPMNDiagram_CamelProcess">
    28 
    29     <bpmndi:BPMNPlane bpmnElement="CamelProcess" id="BPMNPlane_CamelProcess">
    30 
    31       <bpmndi:BPMNShape bpmnElement="sid-80400B65-221F-4DE2-A7AF-1788341E7FAA" id="BPMNShape_sid-80400B65-221F-4DE2-A7AF-1788341E7FAA">
    32 
    33         <omgdc:Bounds height="30.0" width="30.0" x="223.75" y="86.0" />
    34 
    35       </bpmndi:BPMNShape>
    36 
    37       <bpmndi:BPMNShape bpmnElement="MyCamelCall" id="BPMNShape_MyCamelCall">
    38 
    39         <omgdc:Bounds height="80.0" width="100.36219727999998" x="356.56890136" y="61.0" />
    40 
    41       </bpmndi:BPMNShape>
    42 
    43       <bpmndi:BPMNShape bpmnElement="sid-6920138F-F17F-43A3-8C54-D339AC234DF8" id="BPMNShape_sid-6920138F-F17F-43A3-8C54-D339AC234DF8">
    44 
    45         <omgdc:Bounds height="28.0" width="28.0" x="600.0" y="87.0" />
    46 
    47       </bpmndi:BPMNShape>
    48 
    49       <bpmndi:BPMNEdge bpmnElement="sid-23D8E093-77BF-4D8A-8954-3730952ADEF6" id="BPMNEdge_sid-23D8E093-77BF-4D8A-8954-3730952ADEF6">
    50 
    51         <omgdi:waypoint x="456.93109863999996" y="101.0" />
    52 
    53         <omgdi:waypoint x="600.0" y="101.0" />
    54 
    55       </bpmndi:BPMNEdge>
    56 
    57       <bpmndi:BPMNEdge bpmnElement="sid-7B6E8FB0-B1F6-425A-8897-C9CF6A2050CB" id="BPMNEdge_sid-7B6E8FB0-B1F6-425A-8897-C9CF6A2050CB">
    58 
    59         <omgdi:waypoint x="253.75" y="101.0" />
    60 
    61         <omgdi:waypoint x="356.56890136" y="101.0" />
    62 
    63       </bpmndi:BPMNEdge>
    64 
    65     </bpmndi:BPMNPlane>
    66 
    67   </bpmndi:BPMNDiagram>
    68 
    69 </definitions>

    这里在开始任务设置了一个监听类:

     

    监听类实现代码:

     

      1 /**
      2 
      3  *
      4 
      5  */
      6 
      7 package light.mvc.workflow.taskListener;
      8 
      9  
     10 
     11 import java.util.HashMap;
     12 
     13 import java.util.Map;
     14 
     15  
     16 
     17 import light.mvc.service.workflow.impl.DelegateServiceImpl;
     18 
     19 import light.mvc.workflow.model.DelegateInfo;
     20 
     21  
     22 
     23 import org.activiti.engine.delegate.DelegateExecution;
     24 
     25 import org.activiti.engine.delegate.DelegateTask;
     26 
     27 import org.activiti.engine.delegate.JavaDelegate;
     28 
     29 import org.activiti.engine.delegate.TaskListener;
     30 
     31 import org.springframework.beans.factory.annotation.Autowired;
     32 
     33  
     34 
     35 /**  
     36 
     37  *   
     38 
     39  * 项目名称:lightmvc  
     40 
     41  * 类名称:TaskAsigneeListenerImpl  
     42 
     43  * 类描述:  
     44 
     45  * 创建人:邓家海  
     46 
     47  * 创建时间:2017年6月1日 下午11:48:55  
     48 
     49  * 修改人:deng  
     50 
     51  * 修改时间:2017年6月1日 下午11:48:55  
     52 
     53  * 修改备注:  
     54 
     55  * @version   
     56 
     57  *   
     58 
     59  */
     60 
     61  
     62 
     63 public class CamelListenerImpl implements TaskListener,JavaDelegate {
     64 
     65 @Override
     66 
     67 public void notify(DelegateTask delegateTask) {
     68 
     69  System.out.println("CamelListenerImpl notify is running");
     70 
     71   Map<String,Object> map = delegateTask.getVariables();
     72 
     73  
     74 
     75   
     76 
     77   Map<String, Object> variables = new HashMap<String, Object>();
     78 
     79  
     80 
     81   variables.put("input", "Hello");
     82 
     83   Map<String, String> outputMap = new HashMap<String, String>();
     84 
     85   variables.put("outputMap", outputMap);
     86 
     87   delegateTask.setVariables(variables);
     88 
     89 }
     90 
     91  
     92 
     93 @Override
     94 
     95 public  void execute(DelegateExecution delegateTask) throws Exception {
     96 
     97 // TODO Auto-generated method stub
     98 
     99  System.out.println("CamelListenerImpl execute is running");
    100 
    101   Map<String,Object> map = delegateTask.getVariables();
    102 
    103  
    104 
    105   
    106 
    107   Map<String, Object> variables = new HashMap<String, Object>();
    108 
    109  
    110 
    111   variables.put("input", "Hello");
    112 
    113   Map<String, String> outputMap = new HashMap<String, String>();
    114 
    115   variables.put("outputMap", outputMap);
    116 
    117   delegateTask.setVariables(variables);
    118 
    119 }
    120 
    121 }

    Camel路由规则的配置:

    路由的设置有两种方式,第一种是通过java类来配置,另外一种是通过Spring配置文件配置。

    (1)Java类配置:

    Spring的环境下扫描路由配置

    1 <camelContext id="camelContext" xmlns="http://camel.apache.org/schema/spring">
    2 
    3         <packageScan>
    4 
    5                 <package>light.mvc.workflow.camelRoute</package>
    6 
    7         </packageScan>
    8 
    9 </camelContext>

    Java配置类

     1 /**
     2 
     3  *
     4 
     5  */
     6 
     7 package light.mvc.workflow.camelRoute;
     8 
     9  
    10 
    11 import org.apache.camel.builder.RouteBuilder;
    12 
    13  
    14 
    15 /**  
    16 
    17  *   
    18 
    19  * 项目名称:lightmvc  
    20 
    21  * 类名称:MyCamelCallRoute  
    22 
    23  * 类描述:  
    24 
    25  * 创建人:邓家海  
    26 
    27  * 创建时间:2017年6月24日 下午9:00:55  
    28 
    29  * 修改人:deng  
    30 
    31  * 修改时间:2017年6月24日 下午9:00:55  
    32 
    33  * 修改备注:  
    34 
    35  * @version   
    36 
    37  *   
    38 
    39  */
    40 
    41  
    42 
    43 public class MyCamelCallRoute extends RouteBuilder  {
    44 
    45     public MyCamelCallRoute(){
    46 
    47      System.out.println("MyCamelCallRoute is running");
    48 
    49     }
    50 
    51 @Override
    52 
    53 public void configure() throws Exception {
    54 
    55 // TODO Auto-generated method stub
    56 
    57 // from("activiti:CamelProcess:MyCamelCall").to("log:light.mvc.workflow.camelRoute");
    58 
    59 System.out.println("MyCamelCallRoute is running");
    60 
    61  
    62 
    63 from("activiti:CamelProcess:MyCamelCall").to("direct:start-activiti");
    64 
    65 from("direct:start-activiti").to("activiti:CamelStartprocess");
    66 
    67 //from("activiti:CamelProcess:MyCamelCall?copyCamelBodyToBody=true").transform().simple("${property.input} ,jesai");
    68 
    69  
    70 
    71  
    72 
    73 }
    74 
    75 }

    (2)Spring配置文件配置:

        

     1 <camelContext id="testCamelContext" xmlns="http://camel.apache.org/schema/spring">  
     2 
     3          <route>  
     4 
     5              <from uri="file:d:/temp/inbox?delay=30000"/>  
     6 
     7               <process ref="fileConverter"/>  
     8 
     9              <to uri="file:d:/temp/outbox"/>  
    10 
    11          </route>  
    12 
    13      </camelContext>  

    至此。一个简单的Activiti整合Camel的例子就已经完成了。运行部署就可以发现,控制台输出

    CamelListenerImpl execute is running

     

    同步和异步

    之前的例子都是同步的。流程会等到camel规则返回之后才会停止。 一些情况下,我们需要activiti工作流继续运行。这时camelServiceTask的异步功能就特别有用。 你可以通过设置camelServiceTask的async属性来启用这个功能。

    1 <serviceTask id="serviceAsyncPing" activiti:type="camel" activiti:async="true"/>


                   

    通过设置这个功能,camel规则会被activiti的jobExecutor异步执行。 当你在camel规则中定义了一个队列,activiti流程会在camelServiceTask执行时继续运行。 camel规则会以完全异步的方式执行。 如果你想在什么地方等待camelServiceTask的返回值,你可以使用一个receiveTask。

    1 <receiveTask id="receiveAsyncPing" name="Wait State" />

     

    关于Camel路由规则:

    例如:

    1 public class SimpleCamelCallRoute extends RouteBuilder {
    2 
    3   @Override
    4   public void configure() throws Exception {
    5 
    6           from("activiti:SimpleCamelCallProcess:simpleCall").to("log: org.activiti.camel.examples.SimpleCamelCall");
    7   }
    8 }

     

    注:部分 说明

    终端URL 引用activiti终端

    SimpleCamelCallProcess 流程名

    simpleCall 流程中的Camel服务

     

    (1)from("activiti:CamelProcess:MyCamelCall").to("log:light.mvc.workflow.camelRoute");

    这个路由规则只是打印日志,什么也不做。

    (2)

    from("activiti:CamelProcess:MyCamelCall").to("direct:start-activiti");

    from("direct:start-activiti").to("activiti:CamelStartprocess");

    这个规则可以从已有的任务启动过程中去启动另外一个已经部署完成等待启动的任务。比如在这里,我们可以尝试去启动一个ServiceTask任务

    1)首先我们有一个已经部署好的可以运行的ServiceTask任务。流程名称叫做CamelStartprocess

     

     

    2)这个规则任务有一个监听类:

     1 /**
     2 
     3  *
     4 
     5  */
     6 
     7 package light.mvc.workflow.serviceTask;
     8 
     9  
    10 
    11 import org.activiti.engine.delegate.DelegateExecution;
    12 
    13 import org.activiti.engine.delegate.Expression;
    14 
    15 import org.activiti.engine.delegate.JavaDelegate;
    16 
    17  
    18 
    19 /**  
    20 
    21  *   
    22 
    23  * 项目名称:lightmvc  
    24 
    25  * 类名称:ServiceTask  
    26 
    27  * 类描述:  
    28 
    29  * 创建人:邓家海  
    30 
    31  * 创建时间:2017年6月4日 下午6:18:11  
    32 
    33  * 修改人:deng  
    34 
    35  * 修改时间:2017年6月4日 下午6:18:11  
    36 
    37  * 修改备注:  
    38 
    39  * @version   
    40 
    41  *   
    42 
    43  */
    44 
    45  
    46 
    47 public class ServiceTask implements JavaDelegate{
    48 
    49 //流程变量
    50 
    51 private Expression text1;
    52 
    53  
    54 
    55 //重写委托的提交方法
    56 
    57 @Override
    58 
    59 public void execute(DelegateExecution execution) throws Exception {
    60 
    61 System.out.println("serviceTask已经执行已经执行!");
    62 
    63 String value1 = (String) text1.getValue(execution);
    64 
    65 System.out.println(value1);
    66 
    67     execution.setVariable("var1", new StringBuffer(value1).reverse().toString());
    68 
    69 }
    70 
    71  
    72 
    73 }

    3)部署这个流程

    4)设置规则

    from("activiti:CamelProcess:MyCamelCall").to("direct:start-activiti");

    from("direct:start-activiti").to("activiti:CamelStartprocess");

    5)启动我们的Camel任务。可以看到结果

     

    注:这里,我们启动的是Camel任务,但是Camel任务的路由规则又去启动一个Server任务。所以这里一共运行了两个流程实例。

    Table 8.5. 已有的camel行为:

    行为

    URL

    描述

    CamelBehaviorDefaultImpl

    copyVariablesToProperties

    把Activiti变量复制为Camel属性

    CamelBehaviorCamelBodyImpl

    copyCamelBodyToBody

    只把名为"camelBody"Activiti变量复制成camel的消息体

    CamelBehaviorBodyAsMapImpl

    copyVariablesToBodyAsMap

    把activiti的所有变量复制到一个map里,作为Camel的消息体


    上面的表格解释和activiti变量如何传递给camel。下面的表格解释和camel的变量如何返回给activiti。 它只能配置在规则URL中。

    Table 8.6. 已有的camel行为:

    Url

    描述

    默认

    如果Camel消息体是一个map,把每个元素复制成activiti的变量,否则把整个camel消息体作为activiti的"camelBody"变量。

    copyVariablesFromProperties

    将Camel属性以相同名称复制为Activiti变量

    copyCamelBodyToBodyAsString

    和默认一样,但是如果camel消息体不是map时,先把它转换成字符串,再设置为"camelBody"。

    copyVariablesFromHeader

    额外把camel头部以相同名称复制成Activiti变量

     

     

    上面两个表是关于流程变量的设置。那么我们在规则里面去实验这几个变量启用会有什么效果:

    我们设置了两个变量,一个字符串变量input和一个集合变量OutPutMap

              Map<String, Object> variables = new HashMap<String, Object>();

      variables.put("input", "Hello");

      Map<String, String> outputMap = new HashMap<String, String>();

      variables.put("outputMap", outputMap);

    from("activiti:CamelProcess:MyCamelCall").transform().simple("${property.input} ,jesai");

    Camel变量传递给Activiti

    1)copyCamelBodyToBody

    from("activiti:CamelProcess:MyCamelCall?copyCamelBodyToBody=true").transform().simple("${property.input} ,jesai");

     

    可以看到camelBody只把名为"camelBody"Activiti变量复制成camel的消息体

    2)copyVariablesToProperties

    from("activiti:CamelProcess:MyCamelCall?copyVariablesToProperties=true").transform().simple("${property.input} ,jesai");

     

    这里,已经把Activiti变量InputHello复制作为camelBody的消息

    Activiti变量复制为Camel属性

    3)copyVariablesToBodyAsMap

    from("activiti:CamelProcess:MyCamelCall?copyVariablesToBodyAsMap=true").transform().simple("${property.input} ,jesai");

     

    变量放到OutPutMap里面去了。

    Activiti变量传递给Camel

    1)默认

    如果Camel消息体是一个map,把每个元素复制成activiti的变量,否则把整个camel消息体作为activiti的"camelBody"变量。

    2)copyVariablesFromProperties

    from("activiti:CamelProcess:MyCamelCall?copyVariablesFromProperties=true").transform().simple("${property.input} ,jesai");

    Camel属性以相同名称复制为Activiti变量

    3)copyCamelBodyToBodyAsString

    from("activiti:CamelProcess:MyCamelCall?copyCamelBodyToBodyAsString=true").transform().simple("${property.input} ,jesai");

     

    和默认一样,但是如果camel消息体不是map时,先把它转换成字符串,再设置为"camelBody"。

    4)copyVariablesFromHeader

    from("activiti:CamelProcess:MyCamelCall?copyVariablesFromHeader=true").transform().simple("${property.input} ,jesai");

     

    额外把camel头部以相同名称复制成Activiti变量

    注:路由规则是在启动部署系统的时候就已经初始化好了的。不支持热更改。而且系统一单部署完成,运行流程实例的时候,不会执行路由配置。

    实验:我们在路由的配置类里面打印一个控制台:

     

    启动系统就会看到:

     

    你会发现,它是在系统启动的时候执行的。并不是在流程执行的时候。

     

     Activiti交流QQ群:634320089

  • 相关阅读:
    自定义滚动条mCustomScrollbar
    怒怼外媒,为中国正名,这个《流浪地球》捧红的犹太小哥太励志了
    Memcached部署和用法
    SpringMVC中向服务器传递时间参数时出现的问题
    spring4 mvc 出错
    【转】ContextLoaderListener 和 DispatcherServlet
    【转】Myeclipse建立Maven项目
    【转】Docker 常用命令
    docker push到本地仓库失败
    转:Docker学习---挂载本地目录
  • 原文地址:https://www.cnblogs.com/dengjiahai/p/7078120.html
Copyright © 2020-2023  润新知