天天看點

jbpm會簽的實作一、會簽的概念

1.1什麼是會簽

  即共同協商或審批。會簽,又稱會審,也就是流程中某個業務需要經過多人表決,并且根據表決意見的彙總結果,比對設定的規則,決定流程的走向

1.2會簽有多種類型

  1.多人隻發表意見,并決策;2.部分人決策、部分隻發現意見;3.如有決策,決策規則有以下幾類:i:一票通過;ii:一票否決;iii:計同意票數;iv:計同意票數占比等。

二、典型會簽實作邏輯

2.1參與會簽人均需發表意見,全部審批後進入下一節點;

2.2參與會簽人可以進行同意不同意的決策 ,全部進行決策後進入下一節點由下一節點審批人人工統計票數決定會簽是否通過

三、會簽實作方案

  jbpm并未直接提供會簽機制,通過查閱資料以及前期對子任務及決策節點的了解,我們提出了一種基于子任務和決策的會簽實作方案。

  會簽設定表結構如下:

<a href="http://s3.51cto.com/wyfs02/M02/59/9F/wKioL1TZ0CmwM6O5AAE9zWPX7Tc810.jpg" target="_blank"></a>

  流程定義如下:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<code>&lt;</code><code>process</code> <code>xmlns</code><code>=</code><code>'http://jbpm.org/4.4/jpdl'</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>start</code> <code>name</code><code>=</code><code>'start1'</code> <code>g</code><code>=</code><code>'195,109,48,48'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'進入會簽'</code> <code>g</code><code>=</code><code>'-25,-15'</code> <code>to</code><code>=</code><code>'會簽節點'</code><code>/&gt;</code>

<code>  </code><code>&lt;/</code><code>start</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>task</code> <code>g</code><code>=</code><code>'351.0909118652344,106.30681991577148,90,50'</code> <code>name</code><code>=</code><code>'會簽節點'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'進入決策'</code> <code>g</code><code>=</code><code>'-27,-11'</code> <code>to</code><code>=</code><code>'decision 1'</code><code>/&gt;</code>

<code>  </code><code>&lt;/</code><code>task</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>decision</code> <code>g</code><code>=</code><code>'536.0909118652344,106.30681991577148,48,48'</code> <code>name</code><code>=</code><code>'decision 1'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'決策路徑1'</code> <code>g</code><code>=</code><code>'-61,-19'</code> <code>to</code><code>=</code><code>'end 1'</code><code>/&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'決策路徑2'</code> <code>g</code><code>=</code><code>'-47,45'</code> <code>to</code><code>=</code><code>'其他節點'</code><code>/&gt;</code>

<code>  </code><code>&lt;/</code><code>decision</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>end</code> <code>g</code><code>=</code><code>'687.0909118652344,44.306819915771484,48,48'</code> <code>name</code><code>=</code><code>'end 1'</code><code>/&gt;</code>

<code>  </code><code>&lt;</code><code>task</code> <code>g</code><code>=</code><code>'677.0909118652344,163.30681991577148,90,50'</code> <code>name</code><code>=</code><code>'其他節點'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'正常結束'</code> <code>g</code><code>=</code><code>'-26,-21'</code> <code>to</code><code>=</code><code>'end 2'</code><code>/&gt;</code>

<code>  </code><code>&lt;</code><code>end</code> <code>g</code><code>=</code><code>'840.0909118652344,163.30681991577148,48,48'</code> <code>name</code><code>=</code><code>'end 2'</code><code>/&gt;</code>

<code>&lt;/</code><code>process</code><code>&gt;</code>

  流程圖如下:

  如果工作流不是每一步關聯不同表單,而采用同一表單根據步驟名稱确定權限的話,需要特别注意子任務的任務名生成方法。子任務名而不是activityName将用作權限的确定。

18

19

20

21

22

23

24

25

26

27

28

29

30

<code>if</code><code>(!CollectionUtils.isEmpty(userIds) &amp;&amp; !userIds.contains(</code><code>null</code><code>)) {</code>

<code>    </code><code>if</code><code>(userIds.size() &gt; </code><code>1</code><code>){</code>

<code>        </code><code>String deploymentId = processDefineService.queryById(startFlowRunTime.getProcessDefineId()).getDeploymentId();</code>

<code>        </code><code>if</code><code>(StringUtils.isNotEmpty(task.getId())){</code>

<code>            </code><code>deploymentId = jbpmOperatorService.getProcessDefinitionByTaskId(task.getId()).getDeploymentId();</code>

<code>        </code><code>}</code>

<code>        </code><code>UserAssignEntity userAssign = userAssignService.queryUserAssignById(deploymentId, task.getActivityName(), UserAssignConstants.USERASSIGN_FLAG_ASSIGNEE,</code><code>""</code><code>);</code>

<code>    </code><code>AssignsettingEntity assignsetting = </code><code>new</code> <code>AssignsettingEntity();</code>

<code>    </code><code>assignsetting.setDeployId(deploymentId);</code>

<code>    </code><code>assignsetting.setActivityName(task.getActivityName());</code>

<code>    </code><code>List&lt;AssignsettingEntity&gt; assignsettingList = assignsettingService.queryAssignsettingList(assignsetting);</code>

<code>    </code><code>//處理會簽</code>

<code>    </code><code>if</code><code>(userAssign != </code><code>null</code> <code>&amp;&amp; </code><code>"1"</code><code>.equals(userAssign.getIsSigned()) ){</code>

<code>        </code><code>if</code><code>(CollectionUtils.isEmpty(assignsettingList)){</code>

<code>            </code><code>jbpmOperatorService.createSubTask(task.getId(), userIds.toArray(</code><code>new</code> <code>String[userIds.size()]));</code>

<code>        </code><code>}</code><code>else</code> <code>{</code>

<code>            </code><code>//如需要通過子任務名确定表單權限</code>

<code>            </code><code>try</code><code>{</code>

<code>                </code><code>jbpmOperatorService.createAssignSubTask(task.getId(), assignsettingList);</code>

<code>                </code><code>}</code><code>catch</code> <code>(Exception e) {</code>

<code>                    </code><code>throw</code> <code>new</code> <code>ProcessActivityException(e.getMessage());</code>

<code>                </code><code>}</code>

<code>    </code><code>}</code><code>else</code> <code>{</code>

<code>        </code><code>//處理搶辦</code>

<code>        </code><code>for</code><code>(String userId : userIds){</code>

<code>            </code><code>jbpmOperatorService.addTaskParticipatingUser(task.getId(),userId);</code>

<code>    </code><code>}</code>

<code>}</code>

  上面提到如需要通過會簽子任務名确定表單權限,需特别注意createAssignSubTask方法:

31

<code>/**</code>

<code>     </code><code>* </code>

<code>     </code><code>* create sub task as assign task</code>

<code>     </code><code>* @author chao.gao</code>

<code>     </code><code>* @date 2015-2-10 上午10:09:58</code>

<code>     </code><code>* @see com.gaochao.oa.module.bpm.workflow.api.server.service.IJbpmOperatorService#createAssignSubTask(java.lang.String, java.util.List)</code>

<code>     </code><code>* @param id</code>

<code>     </code><code>* @param assignsettingList</code>

<code>     </code><code>* @throws Exception </code>

<code>     </code><code>*/</code>

<code>    </code><code>@Override</code>

<code>    </code><code>public</code> <code>void</code> <code>createAssignSubTask(String parentTaskId, List&lt;AssignsettingEntity&gt; assignsettingList) </code><code>throws</code> <code>Exception{</code>

<code>    </code><code>TaskServiceImpl taskServiceImpl = (TaskServiceImpl)processEngine.getTaskService();</code>

<code>        </code> 

<code>        </code><code>Task parentTask = taskServiceImpl.getTask(parentTaskId);</code>

<code>        </code><code>Map&lt;String,Object&gt; vars = </code><code>new</code> <code>HashMap&lt;String,Object&gt;();</code>

<code>        </code><code>taskServiceImpl.setVariables(parentTaskId, vars);</code>

<code>        </code><code>for</code><code>(AssignsettingEntity assignsetting : assignsettingList){</code>

<code>            </code><code>TaskImpl task = (TaskImpl)taskServiceImpl.newTask(parentTaskId);</code>

<code>            </code><code>task.setAssignee(assignsetting.getUserId());</code>

<code>            </code><code>task.setName(parentTask.getName() + </code><code>"-"</code> <code>+ assignsetting.getTaskName());</code>

<code>            </code><code>task.setActivityName(parentTask.getName());</code>

<code>            </code><code>task.setProcessInstance(getTaskById(parentTaskId).getExecution());</code>

<code>            </code><code>task.setDescription(parentTask.getDescription());</code>

<code>            </code><code>taskServiceImpl.saveTask(task);</code>

  在jbpm4_task表中生成的子任務清單如下,其中子任務通過SUPERTASK_字段與父任務關聯起來:

  子任務的辦理:在辦理子任務時首先獲得其父任務的子任務清單,判斷清單長度,如長度大于1,則隻需要關閉本子任務;如子任務清單長度=1,說明目前僅有本子任務未辦理,則将本任務及父任務同時關閉。

<code>     </code><code>* 處理父子任務,會簽任務,完成任務</code>

<code>     </code><code>* @date 2014-4-3 下午2:55:57</code>

<code>     </code><code>* @param parentTask</code>

<code>     </code><code>* @param subTask</code>

<code>     </code><code>* @param signalName</code>

<code>     </code><code>* @param variables</code>

<code>     </code><code>* @param opinion</code>

<code>    </code><code>private</code> <code>void</code> <code>acch(TaskImpl parentTask, TaskImpl subTask, String signalName, Map&lt;String,Object&gt; variables, String opinion) {</code>

<code>        </code><code>int</code> <code>subTasksSize = parentTask.getSubTasks().size();</code>

<code>        </code><code>jbpmOperatorService.evict(subTask);</code>

<code>        </code><code>jbpmOperatorService.evict(parentTask);</code>

<code>        </code><code>if</code><code>(subTasksSize &gt; </code><code>1</code><code>){</code><code>//如目前父任務的子任務清單大于1,直接完成任務審批</code>

<code>            </code><code>jbpmOperatorService.completeTask(subTask.getId());</code>

<code>        </code><code>}</code><code>else</code><code>{</code>

<code>            </code><code>jbpmOperatorService.completeTask(subTask.getId());</code><code>//先完成子任務</code>

<code>            </code><code>jbpmOperatorService.completeTask(parentTask.getId());</code><code>//關閉父任務</code>

<code>            </code><code>//更新父任務狀态</code>

<code>            </code><code>ProcessTaskEntity pT = processTaskService.queryByTaskId(parentTask.getId());</code><code>//更新父任務狀态</code>

<code>            </code><code>if</code><code>(pT != </code><code>null</code><code>){</code>

<code>                </code><code>pT.setStatus(</code><code>"1"</code><code>);</code>

<code>            </code><code>}</code>

<code>            </code><code>processTaskService.update(pT);</code>

  會簽是否通過的決策:

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

<code>/** </code>

<code> </code><code>* 流程決策</code>

<code> </code><code>* @author chao.gao</code>

<code> </code><code>* @date 2014-2-13 上午10:01:36</code>

<code> </code><code>* @see org.jbpm.api.jpdl.DecisionHandler#decide(org.jbpm.api.model.OpenExecution)</code>

<code> </code><code>* @param arg0</code>

<code> </code><code>* @return</code>

<code> </code><code>*/</code>

<code>@Override</code>

<code>public</code> <code>String decide(OpenExecution openExecution) {</code>

<code>    </code> 

<code>    </code><code>ProcessEngine processEngine = (ProcessEngine) SpringContextUtil.getApplicationContext().getBean(</code><code>"processEngine"</code><code>);</code>

<code>    </code><code>IDecisionRuleService decisionRuleService= (IDecisionRuleService)SpringContextUtil.getApplicationContext().getBean(</code><code>"decisionRuleService"</code><code>);</code>

<code>    </code><code>String processDefinitionId = openExecution.getProcessDefinitionId();</code>

<code>    </code><code>ProcessDefinition processDefinition = processEngine.getRepositoryService()</code>

<code>            </code><code>.createProcessDefinitionQuery()</code>

<code>            </code><code>.processDefinitionId(processDefinitionId)</code>

<code>            </code><code>.uniqueResult();</code>

<code>    </code><code>String deploymentId = processDefinition.getDeploymentId();</code>

<code>    </code><code>Activity curActivity = openExecution.getActivity();</code>

<code>    </code><code>DecisionRuleEntity decisionRule = decisionRuleService.queryByDeployIdAndActivityName(deploymentId, curActivity.getName());</code>

<code>    </code><code>if</code><code>(decisionRule!=</code><code>null</code><code>){</code>

<code>        </code><code>Interpreter it = </code><code>new</code> <code>Interpreter();</code>

<code>        </code><code>try</code><code>{</code>

<code>            </code><code>Map&lt;String, ?&gt; vars = openExecution.getVariables();</code>

<code>            </code><code>Iterator&lt;?&gt; iterator = vars.entrySet().iterator();</code>

<code>            </code><code>while</code> <code>(iterator.hasNext()) {</code>

<code>                </code><code>Map.Entry entry = (Entry) iterator.next();</code>

<code>                </code><code>String key = (String)entry.getKey();</code>

<code>                </code><code>Object val = entry.getValue();</code>

<code>                </code><code>it.set(key.replace(</code><code>"."</code><code>, </code><code>"_"</code><code>), val);</code>

<code>             </code><code>it.set(</code><code>"execution"</code><code>, openExecution);</code>

<code>             </code><code>it.eval(decisionRule.getRuleExpression().replace(</code><code>"'"</code><code>, </code><code>""</code><code>));</code>

<code>             </code><code>String tran = (String)it.get(</code><code>"tranTo"</code><code>);</code>

<code>             </code><code>return</code> <code>tran;</code>

<code>        </code><code>}</code><code>catch</code> <code>(Exception e) {</code>

<code>            </code><code>//e.printStackTrace();</code>

<code>            </code><code>throw</code> <code>new</code> <code>DecisionRuleException(</code><code>"條件判斷表達式錯誤"</code><code>);</code>

<code>            </code> 

<code>     </code><code>String defaultTran = </code><code>""</code><code>;</code>

<code>     </code><code>List outs = curActivity.getOutgoingTransitions();</code>

<code>     </code><code>if</code> <code>(outs.size() &gt; </code><code>0</code><code>) {</code>

<code>         </code><code>defaultTran = ((Transition)outs.get(</code><code>0</code><code>)).getName();</code>

<code>     </code><code>}</code>

<code>     </code><code>return</code> <code>defaultTran;</code>

  通過以上邏輯,我們可以得到類似會簽的效果,另外通過配置設定子任務方法我們也可以友善的進行加簽(生成子任務)、減簽(銷毀子任務)。

四、其他會簽方案

4.1 fork-join

<a href="http://s3.51cto.com/wyfs02/M00/59/9F/wKioL1TZ1A6RHI8zAADXIHZ3glI143.jpg" target="_blank"></a>

  流程定義:

<code>  </code><code>&lt;</code><code>start</code> <code>name</code><code>=</code><code>'start1'</code> <code>g</code><code>=</code><code>'250,100,48,48'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'進行會簽'</code> <code>g</code><code>=</code><code>'-28,-8'</code> <code>to</code><code>=</code><code>'fork 1'</code><code>/&gt;</code>

<code>  </code><code>&lt;</code><code>fork</code> <code>g</code><code>=</code><code>'384.0909118652344,103.30681991577148,48,48'</code> <code>name</code><code>=</code><code>'fork 1'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'會簽分支1'</code> <code>g</code><code>=</code><code>'-68,-14'</code> <code>to</code><code>=</code><code>'task 1'</code><code>/&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'會簽分支2'</code> <code>g</code><code>=</code><code>'-67,31'</code> <code>to</code><code>=</code><code>'task 2'</code><code>/&gt;</code>

<code>  </code><code>&lt;/</code><code>fork</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>task</code> <code>g</code><code>=</code><code>'486.0909118652344,35.306819915771484,90,50'</code> <code>name</code><code>=</code><code>'task 1'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'會簽彙聚1'</code> <code>to</code><code>=</code><code>'join 1'</code><code>/&gt;</code>

<code>  </code><code>&lt;</code><code>task</code> <code>g</code><code>=</code><code>'494.0909118652344,169.30681991577148,90,50'</code> <code>name</code><code>=</code><code>'task 2'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'會簽彙聚1'</code> <code>g</code><code>=</code><code>'5,34'</code> <code>to</code><code>=</code><code>'join 1'</code><code>/&gt;</code>

<code>  </code><code>&lt;</code><code>join</code> <code>g</code><code>=</code><code>'635.0909118652344,96.30681991577148,48,48'</code> <code>name</code><code>=</code><code>'join 1'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'會簽結束'</code> <code>g</code><code>=</code><code>'-27,-16'</code> <code>to</code><code>=</code><code>'end 1'</code><code>/&gt;</code>

<code>  </code><code>&lt;/</code><code>join</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>end</code> <code>g</code><code>=</code><code>'771.0909118652344,96.30681991577148,48,48'</code> <code>name</code><code>=</code><code>'end 1'</code><code>/&gt;</code>

  fork-join的join節點具有multiplicity屬性,通過該屬性标記是全部task完成\僅有一個task完成進入join,或者是幾個task完成才進入join,這也是fork-join可以用來實作會簽的原因。

4.2 for-each(動态分支)

  流程圖:

<a href="http://s3.51cto.com/wyfs02/M01/59/A3/wKiom1TZ1aGCR7sKAACG6-e4Qho926.jpg" target="_blank"></a>

       流程定義:

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'進入會簽'</code> <code>g</code><code>=</code><code>'-26,-18'</code> <code>to</code><code>=</code><code>'foreach 1'</code><code>/&gt;</code>

<code>  </code><code>&lt;</code><code>foreach</code> <code>g</code><code>=</code><code>'357.0909118652344,99.30681991577148,48,48'</code> <code>name</code><code>=</code><code>'foreach 1'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'進入會簽任務'</code> <code>g</code><code>=</code><code>'-39,-17'</code> <code>to</code><code>=</code><code>'會簽任務'</code><code>/&gt;</code>

<code>  </code><code>&lt;/</code><code>foreach</code><code>&gt;</code>

<code>  </code><code>&lt;</code><code>task</code> <code>g</code><code>=</code><code>'512.0909118652344,98.30681991577148,90,50'</code> <code>name</code><code>=</code><code>'會簽任務'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'會簽決策'</code> <code>g</code><code>=</code><code>'-23,-13'</code> <code>to</code><code>=</code><code>'join 1'</code><code>/&gt;</code>

<code>  </code><code>&lt;</code><code>join</code> <code>g</code><code>=</code><code>'680.0909118652344,97.30681991577148,48,48'</code> <code>name</code><code>=</code><code>'join 1'</code><code>&gt;</code>

<code>    </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>'結束'</code> <code>g</code><code>=</code><code>'-18,-17'</code> <code>to</code><code>=</code><code>'end 1'</code><code>/&gt;</code>

<code>  </code><code>&lt;</code><code>end</code> <code>g</code><code>=</code><code>'798.0909118652344,98.30681991577148,48,48'</code> <code>name</code><code>=</code><code>'end 1'</code><code>/&gt;</code>

  foreach(動态分支)屬于jbpm的進階應用,其能夠實作會簽的原理與fork-join相近,fork-join是fork之後生成多個分支,不同分支各是不同節點,最多分支量是提前确定的;而foreach則是通過設定其in\var等屬性動态生成分支,其最多分支量可以進行設定。分支生成以後的會簽工作與fork-join類似。

4.3 custom節點

  我們看一下其定義:

<code>&lt;</code><code>custom</code> <code>class</code><code>=</code><code>"sofocus.bpm.countersign.CountersignActivity"</code> <code>g</code><code>=</code><code>"259,218,92,52"</code>  

<code>          </code><code>name</code><code>=</code><code>"上司會簽"</code><code>&gt;  </code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"description"</code><code>&gt;  </code>

<code>      </code><code>&lt;</code><code>string</code> <code>value</code><code>=</code><code>"#{equipment}裝置訂購會簽"</code> <code>/&gt;  </code>

<code>    </code><code>&lt;/</code><code>property</code><code>&gt;  </code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"form"</code><code>&gt;  </code>

<code>      </code><code>&lt;</code><code>string</code>   

<code>        </code><code>value</code><code>=</code><code>"/buyEquipment.do?action=countersign&amp;amp;taskId=:{TASK_ID}"</code> <code>/&gt;  </code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"strategy"</code><code>&gt;  </code>

<code>      </code><code>&lt;</code><code>object</code> <code>class</code><code>=</code><code>"sofocus.bpm.countersign.AllAgreeStrategy"</code> <code>/&gt;  </code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"passTransiton"</code><code>&gt;  </code>

<code>      </code><code>&lt;</code><code>string</code> <code>value</code><code>=</code><code>""</code> <code>/&gt;  </code>

<code>    </code><code>&lt;</code><code>property</code> <code>name</code><code>=</code><code>"nopassTransiton"</code><code>&gt;  </code>

<code>    </code><code>&lt;</code><code>on</code> <code>event</code><code>=</code><code>"start"</code><code>&gt;  </code>

<code>      </code><code>&lt;</code><code>event-listener</code> <code>class</code><code>=</code><code>"test.com.yy.ah.SetBuyEquipmetnCounterSignUsers"</code> <code>/&gt;  </code>

<code>    </code><code>&lt;/</code><code>on</code><code>&gt;  </code>

<code>    </code><code>&lt;</code><code>transition</code> <code>g</code><code>=</code><code>"-41,-8"</code> <code>name</code><code>=</code><code>"to 會簽結果判斷"</code> <code>to</code><code>=</code><code>"會簽結果判斷"</code> <code>/&gt;  </code>

<code>  </code><code>&lt;/</code><code>custom</code><code>&gt;</code>

  在這個定義中主要有兩個類,一個是CountersignActivity,一個是AllAgreeStragy,另外還有一個配置設定子任務的類。其實作本身不複雜,也是利用子任務,但卻實作了最大的發揮自由度。感興趣的同學可以通過連結進一步學習其思路和實作方案。

4.4 assignHandler

<code> </code><code>&lt;</code><code>task</code> <code>g</code><code>=</code><code>"182,379,92,52"</code> <code>name</code><code>=</code><code>"審批"</code><code>&gt;  </code>

<code>      </code><code>&lt;</code><code>assignment-handler</code> <code>class</code><code>=</code><code>"org.jbpm.examples.attendance.commercialtrip.CommercialTripAssignment"</code><code>&gt;&lt;/</code><code>assignment-handler</code><code>&gt;  </code>

<code>      </code><code>&lt;</code><code>transition</code> <code>g</code><code>=</code><code>"147,329:-47,-17"</code> <code>name</code><code>=</code><code>"審批不通過"</code> <code>to</code><code>=</code><code>"申請"</code><code>/&gt;  </code>

<code>      </code><code>&lt;</code><code>transition</code> <code>name</code><code>=</code><code>"審批通過"</code> <code>to</code><code>=</code><code>"end1"</code> <code>g</code><code>=</code><code>"-47,-17"</code><code>/&gt;  </code>

<code> </code><code>&lt;/</code><code>task</code><code>&gt;</code>

  

     本文轉自 gaochaojs 51CTO部落格,原文連結:http://blog.51cto.com/jncumter/1613419,如需轉載請自行聯系原作者

繼續閱讀