flowable 上一節(jié)點(diǎn)任務(wù)撤回-(5)嵌入式子流程

場(chǎng)景:本章主要描述 下一節(jié)點(diǎn) 嵌入式子流程 如何進(jìn)行回退操作桂躏。

嵌入式子流程

上一章:flowable 上一節(jié)點(diǎn)任務(wù)撤回-(4)多重網(wǎng)關(guān)
下一章:flowable 上一節(jié)點(diǎn)任務(wù)撤回-(6)調(diào)用式子流程

環(huán)境
springboot:2.2.0.RELEASE
flowable:6.4.2

git地址:https://github.com/oldguys/flowable-modeler-demo/tree/branch_with_flowable_examples

所有章節(jié):

  1. flowable 上一節(jié)點(diǎn)任務(wù)撤回-(1)普通節(jié)點(diǎn)撤回
  2. flowable 上一節(jié)點(diǎn)任務(wù)撤回-(2)會(huì)簽任務(wù)(已完成)
  3. flowable 上一節(jié)點(diǎn)任務(wù)撤回-(3)會(huì)簽任務(wù)(正在執(zhí)行中)
  4. flowable 上一節(jié)點(diǎn)任務(wù)撤回-(4)多重網(wǎng)關(guān)
  5. flowable 上一節(jié)點(diǎn)任務(wù)撤回-(5)嵌入式子流程
  6. flowable 上一節(jié)點(diǎn)任務(wù)撤回-(6)調(diào)用式子流程
嵌入式子流程

嵌入式子流程具有一定的特殊性,操作撤回的時(shí)候,比如 :

  1. 節(jié)點(diǎn) A 進(jìn)入子流程這種邊界事件
  2. 子流程中的 各節(jié)點(diǎn)的跳轉(zhuǎn) b-1 b-2 b-3

與之前一樣,對(duì)系統(tǒng)的各種數(shù)據(jù)進(jìn)行分析

BpmnModel
Process 與 SubProcess 共性
ACT_RU_EXECUTION
  1. 從debug數(shù)據(jù)中可以看到饱亮,SubProcess 中的節(jié)點(diǎn) 存在于 節(jié)點(diǎn) SubProcess 中,不能直接通過(guò) getElement 拿到

  2. 然后 Process和 SubProcess 都實(shí)現(xiàn)于接口 org.flowable.bpmn.model.FlowElementsContainer辰如,并且調(diào)用的接口 是 FlowElementsContainer.getFlowElement(String id);

所以 可以從這兩處入手赞咙,進(jìn)行功能編寫

NextSubProcessRollbackOperateStrategy: 從嵌入式子流程撤回到普通節(jié)點(diǎn)

步驟:

  1. 如果下一節(jié)點(diǎn)是子流程 判定 子流程中 是否具有 已完成任務(wù)责循,如果具有,則不具備撤回條件攀操。如果正常則無(wú)所謂院仿。
  2. 像 之前一樣的步驟,構(gòu)建 Execution 速和,利用 Execution 生成 任務(wù)歹垫。(不過(guò)與普通任務(wù)不同 ,子流程前置 普通任務(wù)節(jié)點(diǎn)的 execution 已經(jīng)結(jié)束颠放,不是同一個(gè)排惨,所以無(wú)法使用,需要根據(jù)邊界子節(jié)點(diǎn) 父級(jí)節(jié)點(diǎn) 進(jìn)行構(gòu)建)
  3. 處理掉已生成的 子流程任務(wù)碰凶,另外暮芭,由上圖可以看出,子流程任務(wù) b-1 具有 頂級(jí) execution欲低,這個(gè)也需要進(jìn)行移除辕宏,不然會(huì)導(dǎo)致流程無(wú)法歸檔。
  4. 清理掉相關(guān)依賴數(shù)據(jù)砾莱。

如果是嵌入式子流程 內(nèi)部節(jié)點(diǎn)間處理瑞筐,則處理方式基本和 普通節(jié)點(diǎn)的處理方式一致,只需要判斷恤磷,如果 在 Process 找不到 flowElement面哼,則在SubProcess進(jìn)行找就行。所以之前的操作類直接滿足效果扫步。

基于模板方法模式魔策,構(gòu)建編寫通用 RollbackOperateStrategy.process() 操作
    @Override
    public void process(CommandContext commandContext, String assignee, Map<String, Object> variables) {

        this.commandContext = commandContext;
        this.assignee = assignee;
        this.variables = variables;

        log.info("處理 existNextFinishedTask");
        existNextFinishedTask();
        log.info("配置任務(wù)執(zhí)行人 setAssignee");
        setAssignee();
        log.info("處理 createExecution");
        createExecution();
        log.info("處理 deleteRuntimeTasks");
        deleteRuntimeTasks();
        log.info("處理 deleteHisActInstance");
        deleteHisActInstance();
    }

判定是否具有已完成任務(wù),此處需要判定標(biāo)識(shí)是從 SubProcess 中獲取的


    @Override
    public void existNextFinishedTask() {

        Map<String, SubProcess> subProcessMap = paramsTemplate.getSubProcessMap();

        List<HistoricTaskInstance> historicTaskInstances = CommandContextUtil.getHistoricTaskService(commandContext)
                .findHistoricTaskInstancesByQueryCriteria(
                        (HistoricTaskInstanceQueryImpl) new HistoricTaskInstanceQueryImpl()
                                .taskCompletedAfter(paramsTemplate.getHisTask().getEndTime())
                                .finished()
                );

        String key = subProcessMap.keySet().iterator().next();
        this.subProcess = subProcessMap.get(key);

        subProcess.getFlowElements().forEach(obj -> subProcessItemKeySet.add(obj.getId()));
        if (!historicTaskInstances.isEmpty()) {
            historicTaskInstances.forEach(obj -> {
                if (subProcessItemKeySet.contains(obj.getTaskDefinitionKey())) {
                    LOGGER.error("出現(xiàn)已完成任務(wù)河胎,無(wú)法進(jìn)行流程節(jié)點(diǎn)撤回: [" + obj + "]");
                    throw new FlowableRuntimeException("出現(xiàn)已完成任務(wù)闯袒,無(wú)法進(jìn)行流程節(jié)點(diǎn)撤回");
                }
            });
        }

    }

構(gòu)建 Execution:主要區(qū)別在于只能通過(guò)相鄰節(jié)點(diǎn)進(jìn)行獲取,不然當(dāng)出現(xiàn)多層級(jí)網(wǎng)關(guān)的時(shí)候游岳,可能會(huì)出現(xiàn)層級(jí)錯(cuò)誤bug

  @Override
    public void createExecution() {

        HistoricTaskInstance hisTask = paramsTemplate.getHisTask();
        ExecutionEntity executionEntity = CommandContextUtil.getExecutionEntityManager(commandContext).findById(hisTask.getExecutionId());

        /**
         *  subProcess 作為下一節(jié)點(diǎn)的時(shí)候政敢,hisTask的execution會(huì)被關(guān)閉調(diào)。所以需要重新創(chuàng)建
         */
        if (null == executionEntity) {
            LOGGER.info("hisTask:execution 為 null");

            List<ExecutionEntity> executionEntityList = CommandContextUtil
                    .getExecutionEntityManager(commandContext)
                    .findExecutionsByParentExecutionAndActivityIds(hisTask.getProcessInstanceId(), paramsTemplate.getNextFlowIdList());
            if (executionEntityList.isEmpty()) {
                throw new FlowableRuntimeException("沒(méi)有找到臨近節(jié)點(diǎn)");
            }
            executionEntity = executionEntityList.get(0);
        }
        // 創(chuàng)建主線
        ExecutionEntity newExecution = CommandContextUtil.getExecutionEntityManager(commandContext).createChildExecution(executionEntity.getParent());

        // 創(chuàng)建新任務(wù)
        createExecution(newExecution);
        // 移除歷史任務(wù)
        removeHisTask(hisTask);
    }

刪除歷史連線

    @Override
    public void deleteHisActInstance() {

        List<ActivityInstance> activityInstanceEntityList = CommandContextUtil.getActivityInstanceEntityManager(commandContext)
                .findActivityInstancesByQueryCriteria(
                        new ActivityInstanceQueryImpl()
                                .processInstanceId(paramsTemplate.getHisTask().getProcessInstanceId())
                );


        List<String> ids = new ArrayList<>();
        activityInstanceEntityList.forEach(obj -> {
            // 時(shí)間大于 任務(wù)創(chuàng)建時(shí)間 之后線條
            if (obj.getStartTime().getTime() > paramsTemplate.getHisTask().getCreateTime().getTime()
                    && subProcessItemKeySet.contains(obj.getActivityId())) {
                ids.add(obj.getId());
            }
            // 當(dāng)前任務(wù)的連線 ID
            if (paramsTemplate.getHisTask().getTaskDefinitionKey().equals(obj.getActivityId())
                    && obj.getEndTime().getTime() > paramsTemplate.getHisTask().getCreateTime().getTime()
            ) {
                ids.add(obj.getId());
            }
        });

        LOGGER.debug("移除歷史任務(wù)連線");
        ids.forEach(obj -> historyActivityInstanceMapper.delete(obj));

    }

刪除正在進(jìn)行任務(wù)

    @Override
    public void deleteRuntimeTasks() {
        HistoricTaskInstance hisTask = paramsTemplate.getHisTask();

        List<TaskEntity> taskEntityList = CommandContextUtil.getTaskService(commandContext).findTasksByProcessInstanceId(hisTask.getProcessInstanceId());

        taskEntityList.forEach(obj -> {
            if (subProcessItemKeySet.contains(obj.getTaskDefinitionKey())) {
                LOGGER.info("移除正在執(zhí)行的下一節(jié)點(diǎn)任務(wù)");
                // 移除任務(wù)
                removeRuntimeTaskOperate(obj);
            }
        });

        // 獲取 subProcess 的 ExecutionEntity
        Collection<ExecutionEntity> executionEntities = CommandContextUtil
                .getExecutionEntityManager(commandContext)
                .findExecutionsByParentExecutionAndActivityIds(hisTask.getProcessInstanceId(), Collections.singletonList(subProcess.getId()));

        executionEntities.forEach(obj -> {
            LOGGER.info("移除 subProcess 層級(jí)execution");
            List<ExecutionEntity> children = CommandContextUtil
                    .getExecutionEntityManager(commandContext)
                    .findChildExecutionsByParentExecutionId(obj.getId());

            // 移除級(jí)聯(lián)子節(jié)點(diǎn)
            children.forEach(item -> CommandContextUtil
                    .getExecutionEntityManager(commandContext)
                    .delete(item));

            // 移除 subProcess 頂級(jí)
            CommandContextUtil
                    .getExecutionEntityManager(commandContext)
                    .delete(obj);
        });

    }

以上 完成對(duì) 上一節(jié)點(diǎn)任務(wù)撤回 架構(gòu)設(shè)計(jì) 及 第 5 種情況 解決方案講述胚迫。
git地址:https://github.com/oldguys/flowable-modeler-demo/tree/branch_with_flowable_examples

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末喷户,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子访锻,更是在濱河造成了極大的恐慌褪尝,老刑警劉巖闹获,帶你破解...
    沈念sama閱讀 222,378評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異河哑,居然都是意外死亡避诽,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門璃谨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)沙庐,“玉大人,你說(shuō)我怎么就攤上這事佳吞」俺” “怎么了?”我有些...
    開封第一講書人閱讀 168,983評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵底扳,是天一觀的道長(zhǎng)古涧。 經(jīng)常有香客問(wèn)我,道長(zhǎng)花盐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,938評(píng)論 1 299
  • 正文 為了忘掉前任菇爪,我火速辦了婚禮算芯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘凳宙。我一直安慰自己熙揍,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,955評(píng)論 6 398
  • 文/花漫 我一把揭開白布氏涩。 她就那樣靜靜地躺著届囚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪是尖。 梳的紋絲不亂的頭發(fā)上意系,一...
    開封第一講書人閱讀 52,549評(píng)論 1 312
  • 那天,我揣著相機(jī)與錄音饺汹,去河邊找鬼蛔添。 笑死,一個(gè)胖子當(dāng)著我的面吹牛兜辞,可吹牛的內(nèi)容都是我干的迎瞧。 我是一名探鬼主播,決...
    沈念sama閱讀 41,063評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼逸吵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼凶硅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起扫皱,我...
    開封第一講書人閱讀 39,991評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤足绅,失蹤者是張志新(化名)和其女友劉穎捷绑,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體编检,經(jīng)...
    沈念sama閱讀 46,522評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胎食,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,604評(píng)論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了允懂。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片厕怜。...
    茶點(diǎn)故事閱讀 40,742評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蕾总,靈堂內(nèi)的尸體忽然破棺而出粥航,到底是詐尸還是另有隱情,我是刑警寧澤生百,帶...
    沈念sama閱讀 36,413評(píng)論 5 351
  • 正文 年R本政府宣布递雀,位于F島的核電站,受9級(jí)特大地震影響蚀浆,放射性物質(zhì)發(fā)生泄漏缀程。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,094評(píng)論 3 335
  • 文/蒙蒙 一市俊、第九天 我趴在偏房一處隱蔽的房頂上張望杨凑。 院中可真熱鬧,春花似錦摆昧、人聲如沸撩满。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)伺帘。三九已至,卻和暖如春忌锯,著一層夾襖步出監(jiān)牢的瞬間伪嫁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工偶垮, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留礼殊,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,159評(píng)論 3 378
  • 正文 我出身青樓针史,卻偏偏與公主長(zhǎng)得像晶伦,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子啄枕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,747評(píng)論 2 361