Activiti事件監聽入門
1. 介紹
在Activiti提供的功能中,事件監聽(Event Listener)可支援無侵入性的方式,以外掛的模式開發功能,例如:記錄額外資訊到資料庫、發送提醒通知審核或狀態。理論上,預期大多數實作的功能在使用Activiti API或SDK的程式中都能完成,但採用事件監聽方式來開發,可維持基礎功能的簡潔、易讀,抽出來實作也有助於模組化以便於維護,也可省去在每份bpmn.xml當中進行設定(Listener/Delegate)。
2. 事件類型
在Activiti中,不同的實例(Entity、Process、Task...)或工具(Timer、Job...)可以有不同的事件類型,而類型即為狀態,例如: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. 參考