零全零美(www.zzgwt.com)
          生活中的很多事情,并不像If...Else那么簡(jiǎn)單!
          posts - 96,comments - 52,trackbacks - 0
                Fork節(jié)點(diǎn)在整個(gè)JBPM流程運(yùn)轉(zhuǎn)過(guò)程中配合Join使用提供使多于一個(gè)的節(jié)點(diǎn)如:TaskNode、State等并行運(yùn)行的作用,很可惜我們不能利用Fork提供的現(xiàn)有機(jī)制實(shí)現(xiàn)需求中經(jīng)常遇到的并發(fā)子流程的效果,當(dāng)然雖然JBPM并不支持并發(fā)子流程的機(jī)制,并不代表我們不能變通的實(shí)現(xiàn),我將在另一篇文章中詳細(xì)說(shuō)明我的并發(fā)子流程的實(shí)現(xiàn)方式
                Fork類的注釋中說(shuō):if this fork behaviour is not sufficient for your needs, consider writing your own custom TokenHandler.看來(lái)連JBPM開發(fā)小組也意識(shí)到Fork可能不能滿足某些特殊的需求。注釋中還說(shuō)Fork節(jié)點(diǎn)有三種配置方式,我很奇怪為什么代碼中只能找到兩種:
                      1、without configuration : in that case the fork will launch one new sub-token over each of the leaving tranisions of the fork node.
                      2、a script : can be used to calculate a collection of transition names at runtime. if a script is configured, the script must have exactly one variable with 'write' access. that variable should be assigned a java.util.Collection in the script expression.
               Fork類繼承自Node并實(shí)現(xiàn)了Parsable接口。Fork類相對(duì)簡(jiǎn)單,他的私有成員變量只有一個(gè):
          1/**
          2       * a script that calculates the transitionNames at runtime.
          3       */

          4      Script script = null;
                  
                  Fork中的Script可以在運(yùn)行時(shí)對(duì)Fork節(jié)點(diǎn)選擇Transition,所以在實(shí)際應(yīng)用中可以使用Fork+Script的方式進(jìn)行多路路由選擇.但是有一點(diǎn)要特別注意:JBBM User Guide文檔中說(shuō):the script in a fork is not persisted.  script in fork might be removed in later versions of jPDL,原本以為這句話的前半句是說(shuō)Script不會(huì)被持久化進(jìn)數(shù)據(jù)庫(kù),實(shí)驗(yàn)了才知道其實(shí)Script還是被存進(jìn)了數(shù)據(jù)庫(kù),這半句的意思應(yīng)該是說(shuō)"fork中的script不被堅(jiān)持",JBPM開發(fā)小組要在新版本中放棄Script,我相信他們一定會(huì)提供更好的解決方案,讓我們拭目以待。 Fork重寫了Node類的read(Element forkElement, JpdlXmlReader jpdlReader)方法,其主要作用是解析JPDL中Fork節(jié)點(diǎn)Script的配置,并初始化自己的成員變量script。下面是execute(ExecutionContext executionContext)方法中的相關(guān)處理

           1Token token = executionContext.getToken();
           2        // 聲明離開轉(zhuǎn)向的集合
           3        Collection transitionNames = null;
           4        //聲明子Token容器
           5        List forkedTokens = new ArrayList();
           6
           7        // 如果沒(méi)有Script,默認(rèn)按照其父類Node的getLeavingTransitionsMap取得所有離開轉(zhuǎn)向
           8        if (script == null{
           9            transitionNames = getLeavingTransitionsMap().keySet();
          10        }
           else 
          11            //如果有Script,按照規(guī)范該Script應(yīng)該返回一個(gè)Collection類型的數(shù)據(jù),作為Fork的離開轉(zhuǎn)向集合
          12            Map outputMap = null;
          13            try {
          14                //執(zhí)行Script,得到返回的Collection數(shù)據(jù)
          15                outputMap = script.eval(token);
          16            }
           catch (Exception e) {
          17                this.raiseException(e, executionContext);
          18            }

          19            if (outputMap.size() == 1{
          20                Object result = outputMap.values().iterator().next();
          21                if (result instanceof Collection) {
          22                    transitionNames = (Collection) result;
          23                }

          24            }

          25            if (transitionNames == null{
          26                throw new JbpmException("script for fork '" + name + "' should produce one collection (in one writable variable): " + transitionNames);
          27            }

          28        }

          下面讓我們來(lái)看一下,F(xiàn)ork產(chǎn)生的子Token的命名方式:
           1    /**
           2     * 功能描述:為子Token取名字<BR>
           3     * @param parent 父Token
           4     * @param transitionName 離開轉(zhuǎn)向的名字
           5     */

           6    protected String getTokenName(Token parent, String transitionName) {
           7        String tokenName = null;
           8        //如果transitionName不為空
           9        if (transitionName != null{
          10            //如果父Tokehn中不存在以transitionName命名的子Token
          11            if (!parent.hasChild(transitionName)) {
          12                //以transitionName的名字為子Token命名
          13                tokenName = transitionName;
          14            }
           else {
          15                //如果已經(jīng)存在則以transitionName+2的方式命名
          16                int i = 2;
          17                tokenName = transitionName + Integer.toString(i);
          18                //如果加2之后依然存在,開始循環(huán),直到父Token中不存在相同名稱的子Token
          19                while (parent.hasChild(tokenName)) {
          20                    i++;
          21                    tokenName = transitionName + Integer.toString(i);
          22                }

          23            }

          24        }
           else {
          25            //如果transitionName為空,則判但父Token中是否有子Token,如果有則以parent.getChildren().size() + 1法命名,
          26            //如果沒(méi)有直接命名為1
          27            int size = (parent.getChildren() != null ? parent.getChildren().size() + 1 : 1);
          28            tokenName = Integer.toString(size);
          29        }

          30        return tokenName;
          31    }

          名字定好之后,F(xiàn)ork為每個(gè)離開轉(zhuǎn)向分別創(chuàng)建了一個(gè)子Token,加入一開始創(chuàng)建的forkedTokens中。最后開始循環(huán)列表,執(zhí)行Node的leave方法,并觸發(fā)Node-leave事件
          iter = forkedTokens.iterator();
                  
          while (iter.hasNext()) {
                      ForkedToken forkedToken 
          = (ForkedToken) iter.next();
                      Token childToken 
          = forkedToken.token;
                      String leavingTransitionName 
          = forkedToken.leavingTransitionName;
                      ExecutionContext childExecutionContext 
          = new ExecutionContext(childToken);
                      
          if (leavingTransitionName != null{
                          leave(childExecutionContext, leavingTransitionName);
                      }
           else {
                          leave(childExecutionContext);
                      }

                  }
                  
                  看了這段代碼我們應(yīng)該明白:Fork的Node-leave事件是會(huì)執(zhí)行多遍的,具體要看產(chǎn)生的子Token的個(gè)數(shù).至于ForkedToken類,其實(shí)是Fork的一個(gè)內(nèi)被類,只起到一個(gè)普通Bean的作用.
            到這里,F(xiàn)ork類的大體內(nèi)容我們已經(jīng)解讀完畢,但是還有一點(diǎn)要注意的地方:
             add some way of blocking the current token here and disable that blocking when the join reactivates this token Then an exception can be thrown by in case someone tries to signal a token that is waiting in a fork.Suspend and resume can NOT be used for this since that will also suspend any related timers, tasks and messages...So a separate kind of blocking should be created for this.

                  文章原創(chuàng),轉(zhuǎn)載請(qǐng)注明出處!
          posted on 2008-11-05 16:41 零全零美 閱讀(2110) 評(píng)論(0)  編輯  收藏 所屬分類: jbpm
          主站蜘蛛池模板: 武冈市| 江陵县| 宜兰市| 疏附县| 滕州市| 如皋市| 万州区| 贵州省| 易门县| 景洪市| 禹城市| 招远市| 泰州市| 华阴市| 石首市| 历史| 扶绥县| 光泽县| 施甸县| 平潭县| 山丹县| 长岛县| 沾益县| 如皋市| 南召县| 乌鲁木齐市| 奇台县| 东山县| 潞西市| 西和县| 涿州市| 盘山县| 托克托县| 京山县| 茌平县| 依安县| 友谊县| 广西| 防城港市| 修武县| 穆棱市|