我不太确定这是更多的Openbravo问题还是更多的Quartz问题,但我们有一些手动流程通过Openbravo ProcessRequest
对象(OB v2.50MP24)按计划运行,但是似乎进程在同一时间运行了两次。 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 :(得分:6)
执行双重作业的最常见原因如下:
<强>编辑:强>
- 您的应用程序部署在集群环境中,并且您尚未将Quartz配置为在集群环境中运行。
- 您的应用程序不止一次部署。在许多情况下,应用程序部署两次,特别是在Tomcat服务器中。因此,QuartzInitializerListener被调用两次,Jobs被执行两次。如果您使用Tomcat服务器并且在server.xml中显式定义上下文,则应关闭自动应用程序部署或指定deployIgnore。 autoDeploy设置为true且server.xml中存在context元素,因此应用程序的两次部署。将autoDeploy设置为false或从server.xml中删除context元素。
- 您的应用程序已重新部署,但未取消当前流程的安排。
我希望这会对你有所帮助。
答案 1 :(得分:1)
Quartz使用线程池来执行作业。因此,正如您所怀疑的那样,RBDDalProcess
可能在单独的线程中具有单独的实例,并且计数器检查将失败。
您可以做的一件事是列出在Scheduler中注册的作业(您可以使用OB API获取Scheduler:OBScheduler.getScheduler()
):
// 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.JobFactory和org.quartz.Scheduler.setJobFactory方法来控制作业实例化。
还要确保在Openbravo的“报告和处理”表中只有一个此流程条目。
我在Openbravo 3.0中使用过DalBaseProcess
,我无法确认您所描述的这种行为。考虑到这一点,检查Openbravov2.50MP24和Quartz报告的错误或在Openbravo Forge论坛中发布一个问题可能是个好主意。