MAS
MAS

Reputation: 11

how to stop/interrupt quartz scheduler job manually

I am running a simple quartz job in main class which runs every 30 secs.

public class Start {
 public static void main(String[] args) throws Exception {    
      SchedulerFactory sf = new StdSchedulerFactory();
      Scheduler sched = sf.getScheduler();
       JobDetail job = newJob(MyJob.class).withIdentity("myJob","XXX").build();
   Trigger trigger = TriggerBuilder.newTrigger()
         .withSchedule(
             SimpleScheduleBuilder.simpleSchedule()
                 .withIntervalInSeconds(30)
             .repeatForever())
                               .build();
    sched.scheduleJob(job, trigger);
     sched.start();
  } 
}

Here i am implementing InterruptableJob like

 public class MyJob implements InterruptableJob {

private volatile boolean isJobInterrupted = false;

private JobKey jobKey = null;

private volatile Thread thisThread;

public MyJob() {
}

@Override
public void interrupt() throws UnableToInterruptJobException {
    // TODO Auto-generated method stub
    System.err.println("calling interrupt:"+thisThread+"==>"+jobKey);
    isJobInterrupted = true;
    if (thisThread != null) {
        // this call causes the ClosedByInterruptException to happen
        thisThread.interrupt();
    }

}

@Override
public void execute(JobExecutionContext context) throws JobExecutionException {
    // TODO Auto-generated method stub
    thisThread = Thread.currentThread();

    jobKey = context.getJobDetail().getKey();

    System.err.println("calling execute:"+thisThread+"==>"+jobKey);
}
}

Now i tried to stop the job using another main class like in every possible way with no luck

public class Stop {
 public static void main(String[] args) throws Exception {

     SchedulerFactory sf = new StdSchedulerFactory();
        Scheduler sched = sf.getScheduler();

        // get a "nice round" time a few seconds in the future...
        Date startTime = nextGivenSecondDate(null, 1);

        JobDetail job = newJob(MyJob.class).withIdentity("myJob", "XXX").build();

        Trigger trigger = TriggerBuilder.newTrigger()
        .withSchedule(
                 SimpleScheduleBuilder.simpleSchedule()
                     .withIntervalInSeconds(30)
                 .repeatForever())
                                   .build();

        sched.scheduleJob(job, trigger);

        sched.start();


            try {
                  // if you want to see the job to finish successfully, sleep for about 40 seconds
                Thread.sleep(60000) ;
                  // tell the scheduler to interrupt our job
                  sched.interrupt(job.getKey());
                  Thread.sleep(3 * 1000L);
                } catch (Exception e) {
                  e.printStackTrace();
                }
                System.err.println("------- Shutting Down --------");

                TriggerKey tk=TriggerKey.triggerKey("myJob","group1");
                System.err.println("tk"+tk+":"+job.getKey());
                sched.unscheduleJob(tk);
                sched.interrupt(job.getKey());
                sched.interrupt("myJob");
                sched.deleteJob(job.getKey());
                sched.shutdown();
                System.err.println("------- Shutting Down ");

                sched.shutdown(false);

                System.err.println("------- Shutdown Complete ");

            System.err.println("------- Shutdown Complete ");

    }
}

Can anyone please tell me the correct way to stop the job? Thanks a lot.

Upvotes: 1

Views: 28901

Answers (2)

Pavel Verhoturov
Pavel Verhoturov

Reputation: 51

thisThread.interrupt() will work and interrupt thread, if in execute method there is some nethod that throws InterruptedException, for example, add Thread.sleep(100000) in execute method and then scheduler.interrupt(...) will stop job thread. However if in execute method, for example, inifinity loop without interrupt, job thread will be still in progress. So, you need add Thread.sleep in execute, or as said in documentation, just switch flag in interrupt method, and check this flag in code of execute method for correct finish job.

Upvotes: 0

Alex
Alex

Reputation: 8313

This question seems to answer the exact problem you're describing:

You need to write a your job as an implementation of InterruptableJob. To interrupt this job, you need handle to Scheduler, and call interrupt(jobKey<<job name & job group>>)

As-per the InterruptableJob documentation:

The interface to be implemented by Jobs that provide a mechanism for having their execution interrupted. It is NOT a requirement for jobs to implement this interface - in fact, for most people, none of their jobs will.

Interrupting a Job is very analogous in concept and challenge to normal interruption of a Thread in Java.

The means of actually interrupting the Job must be implemented within the Job itself (the interrupt() method of this interface is simply a means for the scheduler to inform the Job that a request has been made for it to be interrupted). The mechanism that your jobs use to interrupt themselves might vary between implementations. However the principle idea in any implementation should be to have the body of the job's execute(..) periodically check some flag to see if an interruption has been requested, and if the flag is set, somehow abort the performance of the rest of the job's work.

Emphasis mine. It is analogous but not the same. You're not expected to use Threads (but indeed you could if that's what your Job does...).

An example of interrupting a job can be found in the java source for the class org.quartz.examples.DumbInterruptableJob. It is legal to use some combination of wait() and notify() synchronization within interrupt() and execute(..) in order to have the interrupt() method block until the execute(..) signals that it has noticed the set flag.

So I recommend reading the documentation and inspecting examples in the full download.

Upvotes: 7

Related Questions