定時啟動執行在 WPS 上的業務流程的兩種方式

CloudSpace發表於2010-08-30
朱 珣, 軟體工程師, IBM

簡介: 通常情況下,當一個業務流程模板啟動後,它便進入了等待狀態。當客戶端發起請求或者有觸發事件的時候,便基於業務流程模板新建一個流程例項。但某些情況下,流程不通過客戶端來觸發,而是需要系統自動、定期地啟動。這種情況下,就需要應用某些機制,來完成流程的自動定期觸發。本文主要介紹定期啟動執行在 WebSphere Process Server 上的業務流程的兩種方式:WebSphere Application Server 的排程程式服務機制和 EJB 2.1 計時器機制。

引言

通常情況下,當一個業務流程模板啟動後,它便進入了等待狀態。當客戶端發起請求或者有觸發事件的時候,便基於業務流程模板新建一個流程例項。但某些情況下,流程不通過客戶端來觸發,而是需要系統自動、定期地啟動。例如,一些完成系統維護功能的業務流程,或者是一些需要定期執行的業務流程。這種情況下,就需要應用某些機制,來完成流程的自動定期觸發。

本文主要介紹如何定期啟動執行在 WebSphere Process Server(WPS)上的業務流程。我們可以通過如下兩種方式來完成流程的定期啟動:

  1. 使用 WebSphere Application Server 的排程程式服務(Scheduler)機制
  2. 使用 EJB 2.1 的計時器功能

在本文中,我們將首先建立一個簡單的業務流程。然後我們將詳細介紹如何應用上述兩種機制來完成業務流程的定期啟動。

為簡化起見,在這一部分,我們將在 WID 中建立一個非常簡單的業務流程―― AutoProcess,這個流程的主要任務就是接收請求並將請求資料列印出來。


圖 1. 業務流程
圖 1. 業務流程

在 snippet log1 中,我們將流程的輸入列印出來:


清單 1. snippet log1 程式碼

				 
 System.out.println("----Auto process invoked----"); 
 System.out.println("----Input field1 is: " + input1.getString("field1") + "----"); 
 System.out.println("----Input field2 is: " + input1.getInt("field2") + "----"); 
          

在 snippet create output 中,我們對流程的 output 進行賦值:


清單 2. snippet create output 程式碼

				 
 input1.setString("field1", "return: " + input1.getString("field1")); 
 input1.setInt("field2", input1.getInt("field2")); 
          

在 snippet log2 中,我們將流程的輸出列印出來:


清單 3. snippet log2 程式碼

				 
 System.out.println("----Output field1 is: " + input1.getString("field1") + "----"); 
 System.out.println("----Output field2 is: " + input1.getInt("field2") + "----"); 
           

流程的介面如下 :


圖 2. 業務流程介面
圖 2. 業務流程介面

排程程式服務(Scheduler)是一個負責在特定時刻或時間間隔啟動相應操作的 WebSphere 變成擴充套件。排程程式是持久的事務計時器服務,它們執行 Enterprise JavaBean 方法或使用任何 J2EE 伺服器應用程式傳送 java 服務訊息。排程程式服務通過充分利用現有的計算資源,有助於將 IT 成本降至最低、提高應用程式速度和響應。

使用排程程式服務包括如下步驟:

    1. 建立和配置排程程式、建立和配置排程程式的資料庫以及管理排程程式的指示資訊
    2. 開發排程任務
    3. 向排程程式提交任務
    4. 管理排程任務

在這一部分中,我們將詳細介紹如何用過這四個步驟來完成業務流程的定時啟動。

建立排程程式服務

我們可以在 WebSphere Process Server 的管理控制檯中建立和配置排程程式服務。每個配置後的排程程式是一個獨立任務排程引擎,它擁有唯一的 java 命名與目錄介面(JNDI)名稱、持久存貯裝置和守護程式。

排程程式的執行依賴於一個資料庫,以用於存貯它的持久資訊。因此,在建立和配置排程程式服務之前,請先確保建立了資料庫,並在 WebSphere Process Server 的管理控制檯中建立了相應的資料來源。

接下來,我們就可以通過如下步驟來建立和配置排程程式服務了:

  1. 開啟 WebSphere Process Server 的管理控制檯,單擊 Resources->Scheduler,新建一個排程程式服務

    圖 3. 新建排程程式服務
    圖 3. 新建排程程式服務

  2. 填寫排程程式服務的屬性

    圖 4. 排程程式服務的屬性
    圖 4. 排程程式服務的屬性

    上圖中:

    scope:排程程式服務定義的範圍,本文中,將排程程式服務定義在 server1 範圍內

    Name:新建的排程程式服務的名稱

    JNDI name:新建的排程程式服務的 JNDI 名稱。這個名稱很重要,在程式裡呼叫排程程式服務的時候需要用到這個名稱

    Description:這一項是可選項。是排程程式服務的描述。

    Category:可選項。表示排程程式服務的類別

    Data source JDNI name:這一項用來指定排程程式服務使用的資料庫的資料來源。這個資料來源需要事先定義好

    Data source alias:用來連線到資料來源的 J2C 別名。這個別名需要事先定義好。

    Table prefix:指定資料庫中表名的字首

    Poll interval:這一項用來指定排程程式服務輪巡資料庫的時間間隔

    Work manager JNDI name:用來指定排程程式服務使用的 Work Manager 的名稱。本文中我們使用預設的 Work Manager

  3. 為排程程式服務建立資料庫表

    圖 5. 為排程程式服務建立資料庫表
    圖 5. 為排程程式服務建立資料庫表

  4. 驗證排程程式服務的資料庫表

    圖 6. 驗證排程程式服務的資料庫表
    圖 6. 驗證排程程式服務的資料庫表

  5. 至此,我們已經建立並配置好了一個新的排程程式服務。在使用排程程式服務之前,我們還需要重起 WebSphere Process Server,以使新建的排程程式服務生效

開發排程任務

排程程式服務可以排程兩種方式的任務:會話 bean 任務和傳送 java 訊息的服務。本文采用第一種方式,建立一個會話 bean,在這個會話 bean 中啟動業務流程。為使會話 bean 能夠被排程程式服務使用,會話 bean 必須使用如下主介面和遠端介面:


清單 4. 會話 bean 需要實現的主介面和遠端介面

				 
 com.ibm.websphere.scheduler.TaskHandlerHome 
 com.ibm.websphere.scheduler.TaskHandler 
           

排程程式服務在執行的時候,會定期呼叫 TaskHandler 中的 process() 方法,因此,會話 bean 需要實現 TaskHandler 介面中定義的 process() 方法,並在 process() 方法中啟動業務流程。

接下來我們就詳細介紹一下開發排程任務的具體步驟:

  1. 在 WID 中新建一個 EJB 工程


圖 7. 新建 EJB 工程
圖 7. 新建 EJB 工程

  1. 在 AutoProcessInvokerEJB 專案中,新建一個會話 bean--AutoProcessInvokerBean,將 TaskHandlerHome 和 TaskHandler 指定為 bean 的主介面和遠端介面


圖 8. 新建會話 bean -- AutoProcessInvokerBean
圖 8. 新建會話 bean -- AutoProcessInvokerBean

  1. 在 AutoProcessInvokerBean 中實現 TaskHandler 介面的 process() 方法,並在該方法中,啟動業務流程,程式碼如下:


清單 5. TaskHandler 介面的 process() 方法實現程式碼

				 
 public void process(TaskStatus status) { 
 String sourceMethod = "process"; 
 System.out.println("----AutoprocessInvoker called by Scheduler----"); 
 // 查詢 Business Flow Managerd 的引用,以啟動流程
 LocalBusinessFlowManager bfm = null; 
 try { 
 Context context = new InitialContext(); 
 Object result = context 
 .lookup("java:comp/env/ejb/LocalBusinessFlowManagerHome"); 
 LocalBusinessFlowManagerHome home = 
  (LocalBusinessFlowManagerHome) javax.rmi.PortableRemoteObject 
 .narrow(result, LocalBusinessFlowManagerHome.class); 
 bfm = home.create(); 
 } catch (Exception e) { 
 System.out.println("----ERROR getting Business Flow Manager reference----"); 
 e.printStackTrace(); 
 return; 
 } 
 // 如果沒有找到引用,則返回
 if (null == bfm) { 
 System.out.println("----ERROR getting Business Flow Manager reference----"); 
 return; 
 } 
 // 查詢名稱為 AutoProc 的業務流程模版
 String whereClause = "PROCESS_TEMPLATE.NAME = 'AutoProc'"; 
 String rderByClause = "PROCESS_TEMPLATE.VALID_FROM DESC"; 
 try { 
 ProcessTemplateData[] templates = bfm.queryProcessTemplates( 
 whereClause, orderByClause, null, null); 
 if (templates != null && templates.length > 0) { 
 ProcessTemplateData template = templates[0]; 
 // 生成流程的輸入訊息
 ClientObjectWrapper cow = 
  bfm.createMessage(template.getID(), template.getInputMessageTypeName()); 
 DataObject input = (DataObject) cow.getObject(); 
 DataObject processRequest = input.createDataObject("input1"); 
 processRequest.setString("field1", "called at " + System.currentTimeMillis()); 
 processRequest.setInt("field2", 10); 
 // 將流程的輸入訊息列印到控制檯上
 BOXMLSerializer serializer = null; //!!! reference used in multiple scopes 
 serializer = (BOXMLSerializer) ServiceManager. 
 INSTANCE.locateService("com/ibm/websphere/bo/BOXMLSerializer"); 
 serializer. 
 writeDataObject(processRequest, processRequest.getType().getURI(), "", System.out); 
 // 啟動流程並獲取流程的返回訊息
 ClientObjectWrapper cowOut = bfm.call("AutoProc", cow); 
 DataObject response = (DataObject) cowOut.getObject(); 
 DataObject responseData = response.getDataObject("output1"); 
 serializer
 .writeDataObject(responseData, responseData.getType().getURI(), "", System.out); 
 } 
 } catch (Exception e) { 
 System.out.println("----error getting Scheduler!----"); 
 e.printStackTrace(); 
 } 
 } 
			

在這段程式碼中,我們首先獲取 Business Flow Manager 物件,然後建立流程的輸入資料(在實際專案中,流程的輸入資料也可以從檔案中讀取),最後啟動流程,並獲取流程的返回資料。

至此,我們已經成功建立了排程任務,接下來,我們需要將排程任務提交給排程程式服務,並啟動該排程任務。

向排程程式服務提交任務

我們在建立排程程式服務的時候,曾經指定了一個 JNDI 名字(test/scheduler)。通過查詢這個 JNDI 名稱,我們可以獲取一個 com.ibm.websphere.scheduler.Scheduler 的 java 物件.利用這個物件,我們可以對任務執行建立、暫掛、取消等操作。

在本文中,我們利用 startup bean 向排程程式服務提交任務。Startup bean 使業務邏輯能在啟動或停止應用程式時執行。我們可以使用 home 介面 com.ibm.websphere.startupservice.AppStartUpHome 來將一個 bean 指定成應用程式的 startup bean。是用遠端介面 com.ibm.websphere.startupservice.AppStartUp 來對該會話 bean 定義 start() 和 stop() 方法。當應用程式啟動時,會啟動 bean 的 start() 方法;當應用程式停止時,會啟動 bean 的 stop() 方法。

接下來,我們就詳細介紹如何建立 startup bean 將排程任務提交給排程程式服務。

  1. 在 AutoProcessInvokerEJB 專案中新建一個會話 bean – AutoProcessStarterBean,將 AppStartUpHome 指定為 bean 的主介面;將 AppStartUp 指定為 bean 的遠端介面。


圖 9. 新建會話 bean – AutoProcessStarterBean
圖 9. 新建會話 bean – AutoProcessStarterBean

  1. 在 AutoProcessStarterBean 中實現 AppStartUp 介面的 start() 方法,再次訪法中,將排程任務提交給排程程式服務,程式碼如下:


清單 6. AppStartUp 介面的 start() 方法實現程式碼

				 
 
 public boolean start() { 
 String sourceMethod = "start"; 
 System.out.println("----starting my StartupBean----"); 
 // initialize 
 InitialContext initialContext = null; 
 Scheduler scheduler = null; 
 // get Scheduler 
 try { 
 initialContext = new InitialContext(); 
 scheduler = (Scheduler) initialContext.lookup("test/scheduler"); 
 } catch (NamingException e) { 
 System.out.println("----error getting Scheduler!----"); 
 e.printStackTrace(); 
 } 
 if (scheduler == null) 
 return false; 
 try { 
 // create class BeanTaskInfo 
 BeanTaskInfo taskInfo = (BeanTaskInfo) scheduler 
 .createTaskInfo(BeanTaskInfo.class); 
 // lookup sessoin bean using its jndi name 
 Object bj = initialContext 
 .lookup("ejb/com/ibm/websphere/scheduler/AutoProcessInvoker"); 
 // Narrow session bean 
 TaskHandlerHome home = (TaskHandlerHome) PortableRemoteObject 
 .narrow(obj, TaskHandlerHome.class); 
 // add the schedule implementation into taskinfo class 
 taskInfo.setTaskHandler(home); 
 // set UserCalendar for task 
 Calendar now = Calendar.getInstance(); 
 taskInfo.setStartTime(new Date()); 
 taskInfo.setRepeatInterval("0 * * * * ?"); 
 taskInfo.setNumberOfRepeats(3); 
 taskInfo 
 .setUserCalendar( 
"com/ibm/websphere/scheduler/calendar/DefaultUserCalendarHome", 
"CRON"); 
 // submit the task to scheduler 
 TaskStatus ts = scheduler.create(taskInfo); 
 System.out.println("----Task created----"); 
 } catch (Exception e) { 
 e.printStackTrace(); 
 } 
 return true; 
 } 

在以上程式碼中,我們執行了如下操作:

    1. 查詢 JNDI 名字―― test/scheduler 獲取排程程式服務物件,並建立一個排程任務
    2. 查詢 JNDI 名字―― ejb/com/ibm/websphere/scheduler/AutoProcessInvoker,獲取 AutoProcessInvokerBean 物件的 TaskHandlerHome 介面
    3. 用 setTaskHandler 方法,將任務的邏輯實現提交給排程程式服務
    4. 用 setStartTime 方法設定任務的啟動時間為當前系統時間
    5. 用 setRepeatInterval 方法,設定任務重複間隔時間為1分鐘
    6. 用 setNumberOfRepeats 方法,設定任務的重複次數為3次

至此,我們便利用 startup bean,在應用程式啟動的時候,將任務提交給排程程式服務

管理排程任務

在本文中,我們將利用 startup bean 的 stop() 方法,在停止應用程式的時候,取消並清除排程任務,同時列印出排程任務的資訊。

在 AutoProcessStarterBean 中實現 AppStartUp 介面的 stop() 方法,程式碼如下:


清單 7. AppStartUp 介面的 stop() 方法實現程式碼

				 
 public void stop() {\ 
 String sourceMethod = "stop"; 
 System.out.println("----stopping ProcessScheudler----"); 
 InitialContext context; 
 try{> 
 context=new InitialContext(); 
 //lookup schedule using its jndi name 
 Scheduler scheduler=(Scheduler)context.lookup("test/scheduler"); 
 Iterator taskit = scheduler.findTasksByName("%"); 
 while (taskit.hasNext()){ 
 BeanTaskInfo taskinfo = (BeanTaskInfo)taskit.next(); 
 String taskid = taskinfo.getTaskId(); 
 System.out.println("----task id is: " + taskid); 
 System.out 
 .println("----task start time is: " + taskinfo.getStartTime().toString() + "----"); 
 System.out.println("----task interval is: " + taskinfo.getRepeatInterval() + "----"); 
 scheduler.cancel(taskid, true); 
 } 
 } 
 catch(Exception e){ 
 e.printStackTrace(); 
 } 
 } 
       

在這段程式碼中,我們通過查詢 JNDI 名字―― test/scheduler 獲取排程程式服務物件,然後依次查詢該排程程式服務中的任務,呼叫方法 cancel 取消並清除任務。

部署並執行流程和 EJB 專案

  1. 將業務流程模組 AutoProcessApp 部署到 WebSphere Process Server 上,並啟動流程模版
  2. 將 EJB 工程 AutoPorcessInvoker 部署到 WebSphere Process Server 上,並啟動該應用
  3. 檢視控制檯,如果有如下輸出,說明任務已經被排程程式服務啟動,從而達到了定期自動啟動流程的目的


清單 8. 控制檯輸出

				 
 [10-2-24 14:06:37:937 CST] 00000ab3 SystemOut     O ----starting my StartupBean---- 
 [10-2-24 14:06:38:515 CST] 00000ab3 SystemOut     O ----Task created---- 
 [10-2-24 14:06:38:546 CST] 00000ab3 ApplicationMg A   
 WSVR0221I: 應用程式已啟動:AutoProcessInvoker 
 [10-2-24 14:06:41:031 CST] 0000006c SystemOut     O 
 ----AutoprocessInvoker called by Scheduler---- 
 [10-2-24 14:06:41:562 CST] 0000006c SystemOut     O 
  
  
 called at 1266991601484 
 10 
  
 [10-2-24 14:06:42:500 CST] 0000006c SystemOut     O ----Auto process invoked---- 
 [10-2-24 14:06:42:500 CST] 0000006c SystemOut     O 
 ----Input field1 is: called at 1266991601484---- 
 [10-2-24 14:06:42:500 CST] 0000006c SystemOut     O ----Input field2 is: 10---- 
 [10-2-24 14:06:42:515 CST] 0000006c SystemOut     O 
 ----Output field1 is: return: called at 1266991601484---- 
 [10-2-24 14:06:42:515 CST] 0000006c SystemOut     O ----Output field2 is: 10---- 
 [10-2-24 14:06:42:593 CST] 0000006c SystemOut     O 
  
  
 return: called at 1266991601484 
 10 
  

以上我們介紹瞭如何用 WebSphere 擴充套件的排程程式服務功能來定時啟動業務流程。在這一部分中,我們將介紹定時啟動業務流程的另外一種方式:利用 EJB 2.1 計時器功能定時啟動業務流程。

同前一種方法一樣,我們需要建立一個會話 bean,用這個會話 bean 來啟動業務流程。要實現 EJB 2.1 計時器功能,這個會話 bean 需要實現 javax.ejb.TimedObject 介面。這個介面中的方法―― ejbTimeout 將定期被呼叫。因此,我們將在 ejbTimeout 方法中啟動業務流程。要想啟動計時器功能,還需要為計時器指定 Timer。同前一種方法一樣,我們選擇在啟動應用的時候,啟用計時器功能,在停止應用的時候,取消計時器功能。因此,這個會話 bean 還需要使用 AppStartUpHome 作為主介面,並實現遠端介面 AppStartUp 的 start() 和 stop() 方法。

具體步驟如下:

  1. 新建一個 EJB 工程―― TimerInvokerEJB
  2. 在 TimerInvokerEJB 專案中,新建一個會話 bean – TimerInvokerBean
  3. 將 AppStartUpHome 指定為會話 bean 的主介面;將 AppStartUp 指定為會話 bean 的遠端介面


圖 10. TimerInvokerBean 的介面
圖 10. TimerInvokerBean 的介面

  1. 修改 TimerInvokerBean,使其實現 TimedObject 介面
  2. 實現 TimedObject 的 ejbTimeout 方法,在該方法中啟動業務流程,程式碼如下:


清單 9. TimedObject 介面的 ejbTimeout 方法實現程式碼:

				 
 public void ejbTimeout(Timer arg0) { 
 // TODO Auto-generated method stub 
 System.out.println("----EJB timer invoked----"); 
 // looking up reference to Business Flow Manager 
 LocalBusinessFlowManager bfm = null; 
 try { 
 Context context = new InitialContext(); 
 Object result = context 
 .lookup("java:comp/env/ejb/LocalBusinessFlowManagerHome"); 
 LocalBusinessFlowManagerHome home = 
 (LocalBusinessFlowManagerHome) javax.rmi.PortableRemoteObject 
 .narrow(result, LocalBusinessFlowManagerHome.class); 
 bfm = home.create(); 
 } catch (Exception e) { 
 System.out.println("----ERROR getting Business Flow Manager reference----"); 
 e.printStackTrace(); 
 return; 
 } 
 if (null == bfm) { 
 System.out.println("----ERROR getting Business Flow Manager reference----"); 
 return; 
 } 
 String whereClause = "PROCESS_TEMPLATE.NAME = 'AutoProc'"; 
 String rderByClause = "PROCESS_TEMPLATE.VALID_FROM DESC"; 
 try { 
 ProcessTemplateData[] templates = bfm.queryProcessTemplates( 
 whereClause, orderByClause, null, null); 
 if (templates != null && templates.length > 0) { 
 ProcessTemplateData template = templates[0]; 
 ClientObjectWrapper cow = 
 bfm.createMessage(template.getID(), template.getInputMessageTypeName()); 
 DataObject input = (DataObject) cow.getObject(); 
 DataObject processRequest = input.createDataObject("input1"); 
 processRequest.setString("field1", "called at " + System.currentTimeMillis()); 
 processRequest.setInt("field2", 10); 
 BOXMLSerializer serializer = null; //!!! reference used in multiple scopes 
 serializer = (BOXMLSerializer) ServiceManager. 
  INSTANCE.locateService("com/ibm/websphere/bo/BOXMLSerializer"); 
 serializer. 
 writeDataObject(processRequest, processRequest.getType().getURI(), "", System.out); 
 ClientObjectWrapper cowOut = bfm.call("AutoProc", cow); 
 DataObject response = (DataObject) cowOut.getObject(); 
 DataObject responseData = response.getDataObject("output1"); 
 serializer
 .writeDataObject(responseData, responseData.getType().getURI(), "", System.out); 
 } 
 } catch (Exception e) { 
 System.out.println("----error getting Scheduler!----"); 
 e.printStackTrace(); 
 } 
 } 

  1. 實現 AppStartUp 介面的 start() 方法,在該方法中,為定時器指定 Timer 物件,從而在應用程式啟動的時候啟動定時器。程式碼如下:


清單 10. AppStartUp 介面的 start() 方法實現程式碼

				 
 public boolean start() { 
 System.out.println("----Startup method called----"); 
 TimerService ts = mySessionCtx.getTimerService(); 
 long interval = 60000; 
 String timerName = "EJBTimer"; 
 ts.createTimer(new Date(), interval, timerName); 
 return true; 
 } 

在這段程式碼中,我們為定時器指定了 Timer 物件:啟動時間為當前系統時間;重複間隔為1分鐘;計時器的名字為 EJBTimer

  1. 實現 AppStartUp 介面的 stop() 方法,在停止應用程式的時候取消計時器,程式碼如下:


清單 11. AppStartUp 介面的 stop() 方法實現程式碼

				 
 public void stop() { 
 System.out.println("----Stop method called----"); 
 try { 
 TimerService ts = mySessionCtx.getTimerService(); 
 Collection timers = ts.getTimers(); 
 Iterator it = timers.iterator(); 
 while (it.hasNext()) { 
 Timer myTimer = (Timer) it.next(); 
 System.out.println("----Timer info: " + myTimer.getInfo() 
 + "----"); 
 myTimer.cancel(); 
 } 
 } catch (Exception e) { 
 System.out.println("Exception after cancelling timer : "
 + e.toString()); 
 } 
 } 

  1. 部署並啟動 TimerInvoker 應用
  2. 檢視控制檯,如果有如下輸出,說明計時器已經啟動,從而達到了定時啟動業務流程的目的


清單 12. 控制檯輸出

				 
 [10-2-24 14:50:26:000 CST] 000002af SystemOut     O ----EJB timer invoked---- 
 [10-2-24 14:50:26:859 CST] 000002af SystemOut     O 
  
  
 called at 1266994226828 
 10 
  
 [10-2-24 14:50:26:921 CST] 000002af SystemOut     O ----Auto process invoked---- 
 [10-2-24 14:50:26:921 CST] 000002af SystemOut    
 O ----Input field1 is: called at 1266994226828---- 
 [10-2-24 14:50:26:921 CST] 000002af SystemOut     O ----Input field2 is: 10---- 
 [10-2-24 14:50:26:921 CST] 000002af SystemOut     
 O ----Output field1 is: return: called at 1266994226828---- 
 [10-2-24 14:50:26:921 CST] 000002af SystemOut     O ----Output field2 is: 10---- 
 [10-2-24 14:50:26:937 CST] 000002af SystemOut     O
   
 p: xsi:type="p:AutoData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> 
 return: called at 1266994226828 
 10 
  

 

對比定時啟動業務流程的兩種機制

以上介紹了定時啟動業務流程的兩種機制:排程程式服務和 EJB 2.1 的計時器功能,下表給出了兩種機制的對比,讀者可以根據自己的需求,選擇合適的機制:


表 1. 兩種機制的對比

排程程式 EJB 計時器
執行無狀態會話 EJB 元件併傳送 JMS 訊息 執行所有 EJB 型別(有狀態會話 bean 除外)
永續性、事務性和高可用性。 永續性、事務性和高可用性。
確保任務僅執行一次 如果計時器 EJB 使用容器管理的全域性事務,計時器確保僅執行一次
使用任何計算規則執行重複任務 使用以毫秒為單位定義的重複時間間隔執行重複任務
使用修改過的固定延遲時間計算來確定重複時間間隔(根據前一個任務的開始時間確定下一次執行時間) 使用定量時間計算來確定重複時間間隔(根據原先計劃的時間確定下一個任務的時間)。
配合使用 NotificationSink 無狀態會話 EJB 的程式化任務監視 無程式化計時器監視
放棄執行後期任務或對時間敏感的任務 放棄執行後期任務或對時間敏感的任務(通過在 javax.ejb.TimedObject 實現中手動檢測來實現)。
管理任何任務生命週期(通過程式或 java 管理擴充套件(JMX)來查詢、暫掛、繼續、取消和清除任務)。 通過程式查詢和取消它的計時器。管理員使用命令列實用程式來查詢和取消計時器。
儲存資料的定量文字,如 Name(外部儲存的任意資料)。 使用計時器儲存任意資料

本文的示例程式碼中包含如下內容:

業務流程模組―― AutoProcessApp

使用排程程式服務定期啟動業務流程的 EJB 工程―― AutoProcessStarter

使用 EJB 2.1 計時器功能定期啟動業務流程的 EJB 工程―― TimerInvoker

下載的檔案是一個 Project Interchange 檔案,讀者可以直接在 WID 6.2 中匯入該檔案,編譯並部署。

本文主要介紹了自動、定期啟動流程的兩種方式:使用排程程式服務和 EJB 2.1 的定時器功能來自動啟動流程。這兩種方式相比較,使用排程程式服務的方式能夠實現更加負責的一些功能,例如,傳送 JMS 訊息,實現程式化任務的監視等。讀者可根據自己的需要選擇合適的機制。

原文連結:http://www.ibm.com/developerworks/cn/websphere/library/techarticles/1005_zhu_wpt/1005_zhu_wpt.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14789789/viewspace-672143/,如需轉載,請註明出處,否則將追究法律責任。

相關文章