2012-08-14 61 views
8

我不太確定這是更多的Openbravo問題還是更多的Quartz問題,但我們有一些手動進程通過Openbravo ProcessRequest對象( OB v2.50MP24),但似乎這些進程在同一時間運行兩次。 Openbravo擴展了Quartz平臺的時間安排。我試着通過確保我的工藝類擴展這個類來解決我自己這個問題:計劃進程在Openbravo中同時運行兩次(使用Quartz)

import java.util.List; 

import org.openbravo.dal.service.OBDal; 
import org.openbravo.model.ad.ui.ProcessRequest; 
import org.openbravo.scheduling.ProcessBundle; 
import org.openbravo.service.db.DalBaseProcess; 

public abstract class RBDDalProcess extends DalBaseProcess { 

    @Override 
    protected void doExecute(ProcessBundle bundle) throws Exception { 
     org.quartz.Scheduler sched = org.openbravo.scheduling.OBScheduler 
       .getInstance().getScheduler(); 
     int runCount = 0; 
     synchronized (sched) { 
      List<org.quartz.JobExecutionContext> currentlyExecutingJobs = (List<org.quartz.JobExecutionContext>) sched 
        .getCurrentlyExecutingJobs(); 
      for (org.quartz.JobExecutionContext jec : currentlyExecutingJobs) { 
       ProcessRequest processRequest = OBDal.getInstance().get(
         ProcessRequest.class, jec.getJobDetail().getName()); 
       if (processRequest == null) 
        continue; 
       String processClass = processRequest.getProcess() 
         .getJavaClassName(); 
       if (bundle.getProcessClass().getCanonicalName() 
         .equals(processClass)) { 
        runCount++; 
       } 
      } 
     } 

     if (runCount > 1) { 
      System.out.println("Process " 
        + bundle.getProcessClass().getSimpleName() 
        + " is already running. Cancelling."); 
      return; 
     } 

     doRun(bundle); 
    } 

    protected abstract void doRun(ProcessBundle bundle); 

} 

這工作得很好,當我測試通過請求的過程中,同時立即運行兩次。其中一人被取消。但是,它不適用於計劃的流程。當進程啓動時,我將S.o.p設置爲日誌記錄,並且查看日誌會顯示輸出的每一行兩次,每行一行接一行。

我有一個偷偷摸摸的懷疑,這是因爲這些進程要麼在兩個完全不同的線程中運行,不知道彼此的進程,但是,我不知道如何驗證我的懷疑,或者如果我是正確的,該怎麼辦。我已經驗證數據庫中存儲的每個ProcessRequest對象只有一個實例。

有沒有其他人經歷過這一點,知道他們爲什麼可能會跑兩次,或知道我能做些什麼來防止他們同時運行?

+0

您是否嘗試在調試時檢查線程轉儲(我是指哪些線程正在運行)? – kamaci 2012-08-18 21:00:27

+0

kamaci,我會嘗試它,但同樣的情況不會發生在我的開發機器上;它只發生在生產服務器上,由於只存在命令行訪問,所以我不知道如何調試線程(所以我不能使用類似VisualVM的東西)。 – 2012-08-20 13:05:55

+0

我建議你使用日誌記錄並將其寫入日誌文件。也許它可以告訴我們什麼?另一方面,如果它是另一臺機器而不是其他開發人員使用它,請注意沒有人在到達該機器並在測試時進行測試。 – kamaci 2012-08-20 15:08:30

回答

6

的雙重作業執行的最常見的原因有以下幾種:

編輯:

  • 您的應用程序部署在集羣環境中,並且您還沒有配置Quartz來運行一個集羣環境。
  • 您的應用程序不止一次部署。在很多情況下,特別是在Tomcat服務器中部署應用程序兩次。因此,QuartzInitializerListener被調用兩次,並且作業被執行兩次。如果您使用Tomcat服務器並且您正在server.xml中明確定義上下文,則應關閉自動應用程序部署或指定deployIgnore。 autoDeploy設置爲true,並且server.xml中的上下文元素存在,因此應用程序的兩次部署都是如此。將autoDeploy設置爲false或從server.xml中刪除上下文元素。
  • 您的應用程序已被重新部署,但未修改當前進程。

我希望這可以幫助你。

+0

不幸的是,上下文沒有在server.xml中明確定義,我們也不在集羣環境中。 – 2012-08-23 19:41:46

+0

好吧,所以它看起來似乎是探索不*部署*的問題,但是*重新部署*在構建後導致我發現調度程序以某種方式變得「不可靠」並且正在運行預定過程兩次,但是如果我不調度過程並重新安排它們,這些進程只運行一次。這對我來說似乎是一種「便宜」,但它現在必須要做,而且由於你的回答讓我發現了這個發現,Tolis,我會繼續爲你提供賞金。 :) – 2012-08-23 20:21:56

+0

謝謝安東尼:) – 2012-08-23 22:59:05

1

Quartz使用線程池執行作業。因此,如您所懷疑的那樣,RBDDalProcess可能會在單獨的線程中分開實例,並且計數器檢查將失敗。

一兩件事你可以做的是列出調度登記的任務(:OBScheduler.getScheduler()可以使用OB API爲獲得調度程序):

// enumerate each job group 
for(String group: sched.getJobGroupNames()) { 
    // enumerate each job in group 
    for(JobKey jobKey : sched.getJobKeys(groupEquals(group))) { 
     System.out.println("Found job identified by: " + jobKey); 
    } 
} 

如果你看到同樣的工作添加兩次,退房org.quartz.spi.JobFactoryorg.quartz.Scheduler.setJobFactory用於控制作業實例化的方法。

此外,請確保您在Openbravo的「報告和過程」表中只有一個條目。

我在Openbravo 3.0中使用DalBaseProcess,我無法證實你描述的這種行爲。考慮到這一點,檢查Openbravov2.50MP24和Quartz報告的錯誤或在Openbravo Forge論壇中發佈與您的問題相關的主題可能是一個好主意。

相關問題