Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scheduled processes running twice simultaneously in Openbravo (using Quartz)

I'm not quite sure whether this is more of an Openbravo issue or more of a Quartz issue, but we have some manual processes that run on schedules via Openbravo ProcessRequest objects (OB v2.50MP24), but it seems that the processes are running twice, at the exact same time. Openbravo extends the Quartz platform for their scheduling. I've tried to resolve this issue on my own by ensuring that my process classes extend this class:

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);

}

This worked fine when I tested by requesting the process to run immediately twice at the same time. One of them cancelled. However, it's not working on the scheduled processes. I have S.o.p's set up to log when the processes start, and looking at the logs shows each line of the output twice, each line one right after the other.

I have a sneaking suspicion that it's because the processes are either running in two completely different threads that don't know about each others' processes, however, I'm not sure how to verify my suspicions or, if I am correct, what to do about it. I've already verified that there is only one instance of each of the ProcessRequest objects stored in the database.

Has anyone else experienced this, know why they might be running twice, or know what I can do to prevent them from simultaneously running?

like image 254
Anthony Atkinson Avatar asked Aug 14 '12 17:08

Anthony Atkinson


People also ask

How does Quartz Scheduler work internally?

Quartz scheduler allows an enterprise to schedule a job at a specified date and time. It allows us to perform the operations to schedule or unschedule the jobs. It provides operations to start or stop or pause the scheduler. It also provides reminder services.

How do I initialize Quartz scheduler?

You can initialize the scheduler with predefined jobs and triggers using the XMLSchedulingDataProcessorPlugin (which, with the 1.8 release, replaced the older JobInitializationPlugin). An example is provided in the Quartz distribution in the directory examples/example10.


2 Answers

The most common reasons for a double Job execution are the following:

EDITED:

  • Your application is deployed in a clustered environment and you have not configured Quartz to run in a cluster environment.
  • Your application is deployed more than once. There are many cases where the application is deployed twice especially in Tomcat server. As a consequence the QuartzInitializerListener is invoked twice and the Jobs are executed twice. In case you use Tomcat server and you are defining contexts explicitly in server.xml, you should turn off automatic application deployment or specify deployIgnore. Both the autoDeploy set to true and the context element existence in server.xml, have as a consequence the twice deployment of the application. Set autoDeploy to false or remove the context element from the server.xml.
  • Your application has been redeployed without unscheduling the current processes.

I hope this helps you.

like image 93
Apostolos Emmanouilidis Avatar answered Oct 18 '22 20:10

Apostolos Emmanouilidis


Quartz uses a thread pool for the jobs execution. So as you suspect, the RBDDalProcess will probably have separate instances a in separate thread and the counter check will fail.

One thing you can do is list the jobs registered in the Scheduler (you can get the Scheduler using the OB API as: 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);
    }
}

If you see the same job added twice, check out org.quartz.spi.JobFactory and the org.quartz.Scheduler.setJobFactory method for controlling jobs instantiations.

Also make sure you have only one entry for this process in the 'Report and Process' table in Openbravo.

I have used DalBaseProcess in Openbravo 3.0 and I cannot confirm this behavior you're describing. Having this in mind it would be probably a good idea to checkout the reported bugs for Openbravov2.50MP24 and Quartz or post a thread in Openbravo Forge forums with your problem.

like image 22
hovanessyan Avatar answered Oct 18 '22 20:10

hovanessyan