Activiti EventListener

Activiti事件監聽入門

葉文華 Todd Yeh 2022/05/05 12:19:34
920

1. 介紹

Activiti提供的功能中,事件監聽(Event Listener)可支援無侵入性的方式,以外掛的模式開發功能,例如:記錄額外資訊到資料庫、發送提醒通知審核或狀態。理論上,預期大多數實作的功能在使用Activiti APISDK程式中都能完成,但採用事件監聽方式來開發,可維持基礎功能的簡潔、易讀,抽出來實作也有助於模組化以便於維護,也可省去在每份bpmn.xml當中進行設定(Listener/Delegate)。

 

2.  事件類型

Activiti中,不同的實例(EntityProcessTask...)或工具(TimerJob...)可以有不同的事件類型,而類型即為狀態,例如:created(建立)completed(完成)deleted(刪除)...等等。

org.activiti.engine.delegate.event.ActivitiEventType中包含了所有可能的事件類型。表列說明如下:

事件類型

說明

ENTITY_CREATED

流程實例:建立

ENTITY_INITIALIZED

流程實例:初始化完成

ENTITY_UPDATED

流程實例:更新

ENTITY_DELETED

流程實例:刪除

ENTITY_SUSPENDED

流程實例:暫停

ENTITY_ACTIVATED

流程實例:啟用

TIMER_SCHEDULED

定時器:建立

TIMER_FIRED

定時器:觸發

JOB_CANCELED

作業:取消

JOB_EXECUTION_SUCCESS

作業:執行成功

JOB_EXECUTION_FAILURE

作業:執行失敗

JOB_RETRIES_DECREMENTED

作業:重試次數已減少

CUSTOM

作業:自定義

ENGINE_CREATED

引擎:建立

ENGINE_CLOSED

引擎:關閉

ACTIVITY_STARTED

流程(元件/組件):開始

ACTIVITY_COMPLETED

流程(元件/組件):完成

ACTIVITY_CANCELLED

流程(元件/組件):取消

ACTIVITY_SIGNALED

流程(元件/組件):收到信號

ACTIVITY_COMPENSATE

流程(元件/組件):執行一項節點事件以補償目標節點

ACTIVITY_MESSAGE_SENT

流程(元件/組件):訊息發送

ACTIVITY_MESSAGE_WAITING

流程(元件/組件):訊息等待

ACTIVITY_MESSAGE_RECEIVED

流程(元件/組件):訊息接收

ACTIVITY_ERROR_RECEIVED

流程(元件/組件):接收失敗

HISTORIC_ACTIVITY_INSTANCE_CREATED

歷史流程(元件/組件):建立

HISTORIC_ACTIVITY_INSTANCE_ENDED

歷史流程(元件/組件):結束

SEQUENCEFLOW_TAKEN

連線:從來源進行到目的流程(元件/組件)

UNCAUGHT_BPMN_ERROR

錯誤未在BPMN中進行捕獲

VARIABLE_CREATED

變數:建立

VARIABLE_UPDATED

變數:更新

VARIABLE_DELETED

變數:刪除

TASK_CREATED

任務實例:建立

TASK_ASSIGNED

任務實例:指派

TASK_COMPLETED

任務實例:完成

PROCESS_STARTED

流程實例:開始

PROCESS_COMPLETED

流程實例:完成

PROCESS_COMPLETED_WITH_ERROR_END_EVENT

流程實例:異常結束

PROCESS_CANCELLED

流程實例:取消

HISTORIC_PROCESS_INSTANCE_CREATED

歷史流程實例:建立

HISTORIC_PROCESS_INSTANCE_ENDED

歷史流程實例:結束

MEMBERSHIP_CREATED

成員:建立

MEMBERSHIP_DELETED

成員:刪除

MEMBERSHIPS_DELETED

所有成員:刪除

 

3.  事件監聽:實作監聽器

要開發事件監聽,必須先實作ActivitiEventListener,並覆寫onEvent方法,其中將取得ActivitiEvent物件,可映射出各事件類型對應實例或工具的相關物件。例如:以下監聽HISTORIC_PROCESS_INSTANCE_ENDED類型,可轉換為HistoricProcessInstanceEntityImpl物件來操作使用。

public class BpmActivitiProcessCompleteListener implements ActivitiEventListener {

    private static final Logger LOGGER = LoggerFactory.getLogger(BpmActivitiProcessCompleteListener.class);

    @Override
    public void onEvent(ActivitiEvent event) {
        if (event instanceof ActivitiEntityEventImpl) {
            ActivitiEntityEventImpl eventImpl = (ActivitiEntityEventImpl) event;
            Object entity = eventImpl.getEntity();
            if (entity instanceof HistoricProcessInstanceEntityImpl) {
                HistoricProcessInstanceEntityImpl hiProcInstEntityImpl = (HistoricProcessInstanceEntityImpl) entity;
                if (LOGGER.isInfoEnabled()) {
                    LOGGER.info("A process has ended: {}", hiProcInstEntityImpl.getProcessInstanceId());
                }
            }
        }
    }

    @Override
    public boolean isFailOnException() {
        return false;
    }
}

 

實作了事件監聽器後,要使用它則必須將其啟動或是添加到組態當中讓Activiti跟著帶起來。

方法1:直接啟動(只需在Activiti服務起來後執行一次)

RuntimeService.addEventListener(new BpmActivitiProcessCompleteListener());

方法2:添加到組態

SpringProcessEngineConfiguration configuration = new SpringProcessEngineConfiguration();
// 監聽流程結束
Map<String, List<ActivitiEventListener>> typedListeners = new HashMap<>();
List<ActivitiEventListener> bpmActivitiProcessCompletedEventListener = new ArrayList<>();
bpmActivitiProcessCompletedEventListener.add(getBpmActivitiProcessCompleteListener());
typedListeners.put(ActivitiEventType.HISTORIC_PROCESS_INSTANCE_ENDED.name(), bpmActivitiProcessCompletedEventListener);
configuration.setTypedEventListeners(typedListeners);

 

4.  事件監聽:註冊監聽器

如下方示例,也可以直接註冊相關事件的監聽器,並實作其中需要的邏輯即可:

@Bean
public TaskRuntimeEventListener<TaskCreatedEvent> taskCreatedListener() {
    return taskCreated -> {
        LOGGER.info("Task ID: {}", taskCreated.getEntity().getId());
    };
}

 

5.  問題與限制

事件監聽,是針對事件的狀態做處理,除了可應用的物件、方法受限於其原本的實例或工具外,例如:不能取得BPMN上前一節點設定屬性(像是FieldExtensions);亦不能超出其生命周期,取得非周期內存在的狀態或屬性值,例如:TaskCreatedEvent事件若是在啟動流程階段觸發(未完成啟動流程),將無法透過RuntimeService查詢出ProcessInstance流程實例。

 

6. 參考

Activiti User Guide

Activiti7事件監聽

 

葉文華 Todd Yeh