任務(wù)
用戶(hù)任務(wù)
描述
- 用戶(hù)任務(wù)用來(lái)設(shè)置必須由人員完成的工作
- 當(dāng)流程執(zhí)行到用戶(hù)任務(wù),會(huì)創(chuàng)建一個(gè)新任務(wù),并把這個(gè)新任務(wù)加入到分配人或群組的任務(wù)列表中
圖形標(biāo)記
-
用戶(hù)任務(wù)顯示成一個(gè)普通任務(wù)(圓角矩形),左上角有一個(gè)小用戶(hù)圖標(biāo)
在這里插入圖片描述
XML內(nèi)容
- XML中的用戶(hù)任務(wù)定義:id屬性是必須的,name屬性是可選的:
<userTask id="theTask" name="Important task" />
- 用戶(hù)任務(wù)可以設(shè)置描述,添加documentation元素可以定義描述:
<userTask id="theTask" name="Schedule meeting" >
<documentation>
Schedule an engineering meeting for next week with the new hire.
</documentation>
- 描述文本可以通過(guò)標(biāo)準(zhǔn)的java方法來(lái)獲取:
task.getDescription()
持續(xù)時(shí)間
- 任務(wù)可以用一個(gè)字段來(lái)描述任務(wù)的持續(xù)時(shí)間
- 可以使用查詢(xún)API來(lái)對(duì)持續(xù)時(shí)間進(jìn)行搜索,根據(jù)在時(shí)間之前或之后進(jìn)行搜索
- Activiti提供了一個(gè)節(jié)點(diǎn)擴(kuò)展,在任務(wù)定義中設(shè)置一個(gè)表達(dá)式,這樣在任務(wù)創(chuàng)建時(shí)就可以設(shè)置初始持續(xù)時(shí)間
- 表達(dá)式應(yīng)該是:
- java.util.Date
- java.util.String(ISO8601格式),ISO8601持續(xù)時(shí)間(比如PT50M)
- null
- 在流程中使用上述格式輸入日期,或在前一個(gè)服務(wù)任務(wù)中計(jì)算一個(gè)時(shí)間.這里使用了持續(xù)時(shí)間,持續(xù)時(shí)間會(huì)基于當(dāng)前時(shí)間進(jìn)行計(jì)算,再通過(guò)給定的時(shí)間段累加: 使用"PT30M"作為持續(xù)時(shí)間,任務(wù)就會(huì)從現(xiàn)在開(kāi)始持續(xù)30分鐘
<userTask id="theTask" name="Important task" activiti:dueDate="${dateVariable}"/>
- 任務(wù)的持續(xù)時(shí)間也可以通過(guò)TaskService修改,或在TaskListener中通過(guò)傳入的DelegateTask參數(shù)修改
用戶(hù)分配
- 用戶(hù)任務(wù)可以直接分配給一個(gè)用戶(hù),通過(guò)humanPerformer元素定義
- humanPerformer定義需要一個(gè)resourceAssignmentExpression來(lái)實(shí)際定義用戶(hù).目前只支持formalExpressions
<process ... >
...
<userTask id='theTask' name='important task' >
<humanPerformer>
<resourceAssignmentExpression>
<formalExpression>kermit</formalExpression>
</resourceAssignmentExpression>
</humanPerformer>
</userTask>
- 只有一個(gè)用戶(hù)可以作為任務(wù)的執(zhí)行者分配用戶(hù)
- 在activiti中,用戶(hù)叫做執(zhí)行者
- 擁有執(zhí)行者的用戶(hù)不會(huì)出現(xiàn)在其他人的任務(wù)列表中,只能出現(xiàn)執(zhí)行者的個(gè)人任務(wù)列表中
- 直接分配給用戶(hù)的任務(wù)可以通過(guò)TaskService獲取:
List<Task> tasks = taskService.createTaskQuery().taskAssignee("kermit").list();
- 任務(wù)也可以加入到人員的候選任務(wù)列表中.需要使用potentialOwner元素
- 用法和humanPerformer元素類(lèi)似,需要指定表達(dá)式中的每個(gè)項(xiàng)目是人員還是群組
<process ... >
...
<userTask id='theTask' name='important task' >
<potentialOwner>
<resourceAssignmentExpression>
<formalExpression>user(kermit), group(management)</formalExpression>
</resourceAssignmentExpression>
</potentialOwner>
</userTask>
- 使用potentialOwner元素定義的任務(wù)可以通過(guò)TaskService獲取:
List<Task> tasks = taskService.createTaskQuery().taskCandidateUser("kermit");
這會(huì)獲取所有kermit為候選人的任務(wù),表達(dá)式中包含user(kermit).這也會(huì)獲得所有分配包含kermit這個(gè)成員的群組(比如,group(management),前提是kermit是這個(gè)組的成員,并且使用了activiti的賬號(hào)組件).用戶(hù)所在的群組是在運(yùn)行階段獲取的, 它們可以通過(guò)IdentityService進(jìn)行管理
- 如果沒(méi)有顯式指定設(shè)置的是用戶(hù)還是群組,引擎會(huì)默認(rèn)當(dāng)做群組處理
- 下面的設(shè)置與使用group(accountancy)一樣:
<formalExpression>accountancy</formalExpression>
Activiti對(duì)任務(wù)分配的擴(kuò)展
- 當(dāng)分配不復(fù)雜時(shí),用戶(hù)和組的設(shè)置非常麻煩.為避免復(fù)雜性,可以使用用戶(hù)任務(wù)的自定義擴(kuò)展
- assignee屬性: 直接把用戶(hù)任務(wù)分配給指定用戶(hù)(和使用humanPerformer 效果完全一樣)
<userTask id="theTask" name="my task" activiti:assignee="kermit" />
- candidateUsers屬性: 為任務(wù)設(shè)置候選人(和使用potentialOwner效果完全一樣,不需要像使用potentialOwner通過(guò)user(kermit)聲明,這個(gè)屬性只能用于人員)
<userTask id="theTask" name="my task" activiti:candidateUsers="kermit, gonzo" />
- candidateGroups屬性: 為任務(wù)設(shè)置候選組(和使用potentialOwner效果完全一樣,不需要像使用potentialOwner通過(guò)group(management)聲明,這個(gè)屬性只能用于群組)
<userTask id="theTask" name="my task" activiti:candidateGroups="management, accountancy" />
- candidateUsers和candidateGroups可以同時(shí)設(shè)置在同一個(gè)用戶(hù)任務(wù)中
- Activiti中雖然有賬號(hào)管理組件和IdentityService ,賬號(hào)組件不會(huì)檢測(cè)設(shè)置的用戶(hù)是否存在. Activiti允許與其他已存的賬戶(hù)管理方案集成
- 使用創(chuàng)建事件的任務(wù)監(jiān)聽(tīng)器 來(lái)實(shí)現(xiàn)自定義的分配邏輯:
<userTask id="task1" name="My task" >
<extensionElements>
<activiti:taskListener event="create" class="org.activiti.MyAssignmentHandler" />
</extensionElements>
</userTask>
- DelegateTask會(huì)傳遞給TaskListener的實(shí)現(xiàn),通過(guò)它可以設(shè)置執(zhí)行人,候選人和候選組
public class MyAssignmentHandler implements TaskListener {
public void notify(DelegateTask delegateTask) {
// Execute custom identity lookups here
// and then for example call following methods:
delegateTask.setAssignee("kermit");
delegateTask.addCandidateUser("fozzie");
delegateTask.addCandidateGroup("management");
...
}
}
- 使用spring時(shí),使用表達(dá)式把任務(wù)監(jiān)聽(tīng)器設(shè)置為spring代理的bean,讓這個(gè)監(jiān)聽(tīng)器監(jiān)聽(tīng)任務(wù)的創(chuàng)建事件
- 示例:執(zhí)行者會(huì)通過(guò)調(diào)用ldapService這個(gè)spring bean的findManagerOfEmployee方法獲得.流程變量emp會(huì)作為參數(shù)傳遞給bean
<userTask id="task" name="My Task" activiti:assignee="${ldapService.findManagerForEmployee(emp)}"/>
- 可以用來(lái)設(shè)置候選人和候選組:
<userTask id="task" name="My Task" activiti:candidateUsers="${ldapService.findAllSales()}"/>
- 方法返回類(lèi)型只能為String(候選人) 或Collection < String >(候選組):
public class FakeLdapService {
public String findManagerForEmployee(String employee) {
return "Kermit The Frog";
}
public List<String> findAllSales() {
return Arrays.asList("kermit", "gonzo", "fozzie");
}
}
腳本任務(wù)
描述
- 腳本任務(wù)是一個(gè)自動(dòng)節(jié)點(diǎn)
- 當(dāng)流程到達(dá)腳本任務(wù),會(huì)執(zhí)行對(duì)應(yīng)的腳本
圖形標(biāo)記
-
腳本任務(wù)顯示為標(biāo)準(zhǔn)BPMN 2.0任務(wù)(圓角矩形),左上角有一個(gè)腳本小圖標(biāo)
在這里插入圖片描述
XML內(nèi)容
- 腳本任務(wù)定義需要指定script和scriptFormat
<scriptTask id="theScriptTask" name="Execute script" scriptFormat="groovy">
<script>
sum = 0
for ( i in inputArray ) {
sum += i
}
</script>
</scriptTask>
scriptFormat的值必須兼容JSR-223(java平臺(tái)的腳本語(yǔ)言).默認(rèn)Javascript會(huì)包含在JDK中,不需要額外的依賴(lài).如果要使用其他的腳本引擎,必須要是JSR-223引擎兼容的.還需要把對(duì)應(yīng)的jar添加到classpath下, 并使用合適的名稱(chēng):activiti單元測(cè)試經(jīng)常使用groovy
- groovy腳本引擎放在groovy-all.jar中,在2.0版本之前,腳本引擎是groovy jar的一部分.使用需要添加依賴(lài):
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy-all</artifactId>
<version>2.x.x<version>
</dependency>
腳本變量
- 到達(dá)腳本任務(wù)的流程可以訪問(wèn)的所有流程變量,都可以在腳本中使用
<script>
sum = 0
for ( i in inputArray ) {
sum += i
}
</script>
- 也可以在腳本中設(shè)置流程變量,直接調(diào)用execution.setVariable("variableName", variableValue)
- 默認(rèn),不會(huì)自動(dòng)保存變量(activiti 5.12之前)
- 可以在腳本中自動(dòng)保存任何變量,只要把scriptTask的autoStoreVariables屬性設(shè)置為true
- 最佳實(shí)踐是不要使用,而是顯式調(diào)用execution.setVariable()
<scriptTask id="script" scriptFormat="JavaScript" activiti:autoStoreVariables="false">
參數(shù)默認(rèn)為false: 如果沒(méi)有為腳本任務(wù)定義設(shè)置參數(shù),所有聲明的變量將只存在于腳本執(zhí)行的階段
- 在腳本中設(shè)置變量: 這些命名已經(jīng)被占用,不能用作變量名- out, out:print, lang:import, context, elcontext.
<script>
def scriptVar = "test123"
execution.setVariable("myVar", scriptVar)
</script>
腳本結(jié)果
- 腳本任務(wù)的返回值可以通過(guò)制定流程變量的名稱(chēng),分配給已存在或者一個(gè)新流程變量,需要使用腳本任務(wù)定義的'activiti:resultVariable'屬性
- 任何已存在的流程變量都會(huì)被腳本執(zhí)行的結(jié)果覆蓋
- 如果沒(méi)有指定返回的變量名,腳本的返回值會(huì)被忽略
<scriptTask id="theScriptTask" name="Execute script" scriptFormat="juel" activiti:resultVariable="myVar">
<script>#{echo}</script>
</scriptTask>
腳本的結(jié)果-表達(dá)式 #{echo} 的值會(huì)在腳本完成后,設(shè)置到myVar變量中
Java服務(wù)任務(wù)
描述
- Java服務(wù)任務(wù)用來(lái)調(diào)用外部Java類(lèi)
圖形標(biāo)記
-
Java服務(wù)任務(wù)顯示為圓角矩形,左上角有一個(gè)齒輪小圖標(biāo)
在這里插入圖片描述
XML內(nèi)容
- 聲明Java調(diào)用邏輯有四種方式:
- 實(shí)現(xiàn)JavaDelegate或者ActivityBehavior
- 執(zhí)行解析代理對(duì)象的表達(dá)式
- 調(diào)用一個(gè)方法表達(dá)式
- 調(diào)用一個(gè)值表達(dá)式
- 執(zhí)行一個(gè)在流程執(zhí)行中調(diào)用的類(lèi),需要在activiti:class屬性中設(shè)置全類(lèi)名:
<serviceTask id="javaService"
name="My Java Service Task"
activiti:class="org.activiti.MyJavaDelegate" />
- 使用表達(dá)式調(diào)用一個(gè)對(duì)象,對(duì)象必須遵循一些規(guī)則,并使用activiti:delegateExpression屬性進(jìn)行創(chuàng)建:
<serviceTask id="serviceTask" activiti:delegateExpression="${delegateExpressionBean}" />
delegateExpressionBean是一個(gè)實(shí)現(xiàn)了JavaDelegate接口的bean,定義在實(shí)例的spring容器中
要執(zhí)行指定的UEL方法表達(dá)式, 需要使用activiti:expression:
<serviceTask id="javaService"
name="My Java Service Task"
activiti:expression="#{printer.printMessage()}" />
方法printMessage()會(huì)調(diào)用名為printer對(duì)象的方法
- 為表達(dá)式中的方法傳遞參數(shù):
<serviceTask id="javaService"
name="My Java Service Task"
activiti:expression="#{printer.printMessage(execution, myVar)}" />
調(diào)用名為printer對(duì)象上的方法printMessage.第一個(gè)參數(shù)是DelegateExecution, 在表達(dá)式環(huán)境中默認(rèn)名稱(chēng)為execution. 第二個(gè)參數(shù)傳遞的是當(dāng)前流程的名為myVar的變量
要執(zhí)行指定的UEL方法表達(dá)式, 需要使用activiti:expression:
<serviceTask id="javaService"
name="My Java Service Task"
activiti:expression="#{split.ready}" />
ready屬性的getter方法:getReady() 會(huì)作用于名為split的bean上.這個(gè)對(duì)象會(huì)被解析為流程對(duì)象和spring環(huán)境中的對(duì)象
實(shí)現(xiàn)
- 要在流程執(zhí)行中實(shí)現(xiàn)一個(gè)調(diào)用的類(lèi),這個(gè)類(lèi)需要實(shí)現(xiàn)org.activiti.engine.delegate.JavaDelegate接口,并在execute方法中提供對(duì)應(yīng)的業(yè)務(wù)邏輯.當(dāng)流程執(zhí)行到特定階段,會(huì)指定方法中定義好的業(yè)務(wù)邏輯,并按照默認(rèn)BPMN 2.0中的方式離開(kāi)節(jié)點(diǎn)
-
示例:
- 創(chuàng)建一個(gè)java類(lèi)的例子,對(duì)流程變量中字符串轉(zhuǎn)換為大寫(xiě)
- 這個(gè)類(lèi)需要實(shí)現(xiàn)org.activiti.engine.delegate.JavaDelegate接口,要求實(shí)現(xiàn)execute(DelegateExecution) 方法,包含的業(yè)務(wù)邏輯會(huì)被引擎調(diào)用
- 流程實(shí)例信息:流程變量和其他信息,可以通過(guò)DelegateExecution接口訪問(wèn)和操作
public class ToUppercase implements JavaDelegate {
public void execute(DelegateExecution execution) throws Exception {
String var = (String) execution.getVariable("input");
var = var.toUpperCase();
execution.setVariable("input", var);
}
}
-
serviceTask定義的class只會(huì)創(chuàng)建一個(gè)java類(lèi)的實(shí)例
- 所有流程實(shí)例都會(huì)共享相同的類(lèi)實(shí)例,并調(diào)用execute(DelegateExecution)
- 類(lèi)不能使用任何成員變量,必須是線(xiàn)程安全的,必須能模擬在不同線(xiàn)程中執(zhí)行.影響著屬性注入的處理方式
- 流程定義中引用的類(lèi)(activiti:class)不會(huì)在部署時(shí)實(shí)例化
- 只有當(dāng)流程第一次執(zhí)行到使用類(lèi)的時(shí)候,類(lèi)的實(shí)例才會(huì)被創(chuàng)建
- 如果找不到類(lèi),會(huì)拋出一個(gè)ActivitiException
- 這個(gè)原因是部署環(huán)境(更確切是的classpath)和真實(shí)環(huán)境往往是不同的:當(dāng)使用ant或業(yè)務(wù)歸檔上傳到Activiti Explorer來(lái)發(fā)布流程,classpath沒(méi)有包含引用的類(lèi)
- 內(nèi)部實(shí)現(xiàn)類(lèi)也可以提供實(shí)現(xiàn)org.activiti.engine.impl.pvm.delegate.ActivityBehavior接口的類(lèi)
- 實(shí)現(xiàn)可以訪問(wèn)更強(qiáng)大的ActivityExecution,它可以影響流程的流向
- 注意: 這應(yīng)該盡量避免.只有在高級(jí)情況下并且確切知道要做什么的情況下,再使用ActivityBehavior接口
屬性注入
-
為代理類(lèi)的屬性注入數(shù)據(jù). 支持如下類(lèi)型的注入:
- 固定的字符串
- 表達(dá)式
- 如果有效的話(huà),數(shù)值會(huì)通過(guò)代理類(lèi)的setter方法注入,遵循java bean的命名規(guī)范(比如fistName屬性對(duì)應(yīng)setFirstName(Xxx)方法)
- 如果屬性沒(méi)有對(duì)應(yīng)的setter方法,數(shù)值會(huì)直接注入到私有屬性中
- 一些環(huán)境的SecurityManager不允許修改私有屬性,要把想注入的屬性暴露出對(duì)應(yīng)的setter方法來(lái)
- 無(wú)論流程定義中的數(shù)據(jù)是什么類(lèi)型,注入目標(biāo)的屬性類(lèi)型都應(yīng)該是 org.activiti.engine.delegate.Expression
-
示例:
- 把一個(gè)常量注入到屬性中
- 屬性注入可以使用class屬性
- 在聲明實(shí)際的屬性注入之前,需要定義一個(gè)extensionElements的XML元素
<serviceTask id="javaService"
name="Java service invocation"
activiti:class="org.activiti.examples.bpmn.servicetask.ToUpperCaseFieldInjected">
<extensionElements>
<activiti:field name="text" stringValue="Hello World" />
</extensionElements>
</serviceTask>
ToUpperCaseFieldInjected類(lèi)有一個(gè)text屬性,類(lèi)型是org.activiti.engine.delegate.Expression. 調(diào)用text.getValue(execution) 時(shí),會(huì)返回定義的字符串Hello World
- 可以使用長(zhǎng)文字(比如,內(nèi)嵌的email),使用activiti:string子元素:
<serviceTask id="javaService"
name="Java service invocation"
activiti:class="org.activiti.examples.bpmn.servicetask.ToUpperCaseFieldInjected">
<extensionElements>
<activiti:field name="text">
<activiti:string>
Hello World
</activiti:string>
</activiti:field>
</extensionElements>
</serviceTask>
- 可以使用表達(dá)式,實(shí)現(xiàn)在運(yùn)行期動(dòng)態(tài)解析注入的值
- 這些表達(dá)式可以使用流程變量或spring定義的bean.
- 服務(wù)任務(wù)中的java類(lèi)實(shí)例會(huì)在所有流程實(shí)例中共享:
- 為了動(dòng)態(tài)注入屬性的值,可以在org.activiti.engine.delegate.Expression中使用值和方法表達(dá)式
- 會(huì)使用傳遞給execute方法的DelegateExecution參數(shù)進(jìn)行解析
<serviceTask id="javaService" name="Java service invocation"
activiti:class="org.activiti.examples.bpmn.servicetask.ReverseStringsFieldInjected">
<extensionElements>
<activiti:field name="text1">
<activiti:expression>${genderBean.getGenderString(gender)}</activiti:expression>
</activiti:field>
<activiti:field name="text2">
<activiti:expression>Hello ${gender == 'male' ? 'Mr.' : 'Mrs.'} ${name}</activiti:expression>
</activiti:field>
</ extensionElements>
</ serviceTask>
-
示例:
- 注入表達(dá)式,并使用在當(dāng)前傳入的DelegateExecution解析:
public class ReverseStringsFieldInjected implements JavaDelegate {
private Expression text1;
private Expression text2;
public void execute(DelegateExecution execution) {
String value1 = (String) text1.getValue(execution);
execution.setVariable("var1", new StringBuffer(value1).reverse().toString());
String value2 = (String) text2.getValue(execution);
execution.setVariable("var2", new StringBuffer(value2).reverse().toString());
}
}
- 可以把表達(dá)式設(shè)置成一個(gè)屬性,而不是子元素:
- 因?yàn)閖ava類(lèi)實(shí)例會(huì)被重用,注入只會(huì)發(fā)生一次,當(dāng)服務(wù)任務(wù)調(diào)用第一次的時(shí)候發(fā)生注入
- 當(dāng)代碼中的屬性改變了,值也不會(huì)重新注入,把它們看作是不變的,不用修改它們
服務(wù)任務(wù)結(jié)果
- 服務(wù)流程返回的結(jié)果(使用表達(dá)式的服務(wù)任務(wù))可以分配給已經(jīng)存在的或新的流程變量
- 通過(guò)指定服務(wù)任務(wù)定義的activiti:resultVariable屬性來(lái)實(shí)現(xiàn)
- 指定的流程變量會(huì)被服務(wù)流程的返回結(jié)果覆蓋
- 如果沒(méi)有指定返回變量名,就會(huì)忽略返回結(jié)果
<serviceTask id="aMethodExpressionServiceTask"
activiti:expression="#{myService.doSomething()}"
activiti:resultVariable="myVar" />
服務(wù)流程的返回值(在myService上調(diào)用doSomething() 方法的返回值,myService可能是流程變量,也可能是spring的bean),在服務(wù)執(zhí)行完成之后,會(huì)設(shè)置到名為myVar的流程變量里
處理異常
執(zhí)行自定義邏輯時(shí),常常需要捕獲對(duì)應(yīng)的業(yè)務(wù)異常,在流程內(nèi)部進(jìn)行處理
-
拋出BPMN Errors:
- 在服務(wù)任務(wù)或腳本任務(wù)的代碼里拋出BPMN error:
- 要從JavaDelegate,腳本,表達(dá)式和代理表達(dá)式中拋出名為BpmnError的特殊ActivitiExeption
- 引擎會(huì)捕獲這個(gè)異常,把它轉(zhuǎn)發(fā)到對(duì)應(yīng)的錯(cuò)誤處理中:邊界錯(cuò)誤事件或錯(cuò)誤事件子流程
- 在服務(wù)任務(wù)或腳本任務(wù)的代碼里拋出BPMN error:
public class ThrowBpmnErrorDelegate implements JavaDelegate {
public void execute(DelegateExecution execution) throws Exception {
try {
executeBusinessLogic();
} catch (BusinessException e) {
throw new BpmnError("BusinessExceptionOccured");
}
}
}
構(gòu)造參數(shù)是錯(cuò)誤代碼,會(huì)被用來(lái)決定哪個(gè)錯(cuò)誤處理器會(huì)來(lái)響應(yīng)這個(gè)錯(cuò)誤
這個(gè)機(jī)制只用于業(yè)務(wù)失敗,應(yīng)該被流程定義中設(shè)置的邊界錯(cuò)誤事件或錯(cuò)誤事件子流程處理. 技術(shù)上的錯(cuò)誤應(yīng)該使用其他異常類(lèi)型,通常不會(huì)在流程里處理
-
異常順序流:
內(nèi)部實(shí)現(xiàn)類(lèi)在一些異常發(fā)生時(shí),讓流程進(jìn)入其他路徑
<serviceTask id="javaService"
name="Java service invocation"
activiti:class="org.activiti.ThrowsExceptionBehavior">
</serviceTask>
<sequenceFlow id="no-exception" sourceRef="javaService" targetRef="theEnd" />
<sequenceFlow id="exception" sourceRef="javaService" targetRef="fixException" />
這里的服務(wù)任務(wù)有兩個(gè)外出順序流:分別叫exception和no-exception. 異常出現(xiàn)時(shí)會(huì)使用順序流的ID來(lái)決定流向
public class ThrowsExceptionBehavior implements ActivityBehavior {
public void execute(ActivityExecution execution) throws Exception {
String var = (String) execution.getVariable("var");
PvmTransition transition = null;
try {
executeLogic(var);
transition = execution.getActivity().findOutgoingTransition("no-exception");
} catch (Exception e) {
transition = execution.getActivity().findOutgoingTransition("exception");
}
execution.take(transition);
}
}
JavaDelegate使用Activiti服務(wù)
- 需要在Java服務(wù)任務(wù)中使用Activiti服務(wù)的場(chǎng)景: 比如,通過(guò)RuntimeService啟動(dòng)流程實(shí)例,而callActivity不滿(mǎn)足需求
- org.activiti.engine.delegate.DelegateExecution允許通過(guò) org.activiti.engine.EngineServices接口直接獲得這些服務(wù):
public class StartProcessInstanceTestDelegate implements JavaDelegate {
public void execute(DelegateExecution execution) throws Exception {
RuntimeService runtimeService = execution.getEngineServices().getRuntimeService();
runtimeService.startProcessInstanceByKey("myProcess");
}
}
- 所有activiti服務(wù)的API都可以通過(guò)這個(gè)接口獲得
- 使用這些API調(diào)用出現(xiàn)的所有數(shù)據(jù)改變,都是在當(dāng)前事務(wù)中
- 在例如spring和CDI這樣的依賴(lài)注入環(huán)境也會(huì)起作用,無(wú)論是否啟用了JTA數(shù)據(jù)源
- 示例: 下面的代碼功能與上面的代碼一致,這是RuntimeService是通過(guò)依賴(lài)注入獲得,而不是通過(guò)org.activiti.engine.EngineServices接口
@Component("startProcessInstanceDelegate")
public class StartProcessInstanceTestDelegateWithInjection {
@Autowired
private RuntimeService runtimeService;
public void startProcess() {
runtimeService.startProcessInstanceByKey("oneTaskProcess");
}
}
- 因?yàn)榉?wù)調(diào)用是在當(dāng)前事務(wù)里,數(shù)據(jù)的產(chǎn)生或改變,在服務(wù)任務(wù)執(zhí)行完之前,還沒(méi)有提交到數(shù)據(jù)庫(kù).所以API對(duì)于數(shù)據(jù)庫(kù)數(shù)據(jù)的操作,意味著未提交的操作在服務(wù)任務(wù)的API調(diào)用中都是不可見(jiàn)的


