工作流面試重點(diǎn)內(nèi)容!如何控制工作流流程?使用流程任務(wù)控制工作執(zhí)行操作

任務(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ù)定義需要指定scriptscriptFormat
<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)保存任何變量,只要把scriptTaskautoStoreVariables屬性設(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ò)誤事件子流程
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è)外出順序流:分別叫exceptionno-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)的
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容