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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM