I am using quartz to schedule a daily batch process, and it runs the first days, but it had happened that fires the event for 2 days or so, and then, it stops firing the job.
The java version i'm using is:
java version "1.7.0_25"
Quartz version (in POM):
org.quartz-scheduler
quartz
2.2.1
Here is my code:
Main function for the batch:
public static void main(String[] args) {
try {
SimpleDateFormat sd=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
JobDetail job = JobBuilder.newJob(MyJobClass.class).withIdentity("MyJobClass", "group1").build();
Trigger trigger = TriggerBuilder
.newTrigger()
.withIdentity("MyTrigger", "group1")
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInHours(24).repeatForever())
.startAt(sd.parse("2015-01-12 07:30:00"))
.build();
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);
String strLog="Batch initiated on " + new Date();
System.out.println(strLog);
log.info(strLog);
} catch (Exception e) {
//log error
}
}
And here is my execute method in the job:
public void execute(JobExecutionContext arg0) throws JobExecutionException {
generateBatchProcess();
}
public void generateBatchProcess(){
try{
//do lots of interesting stuff, calling MyBatis Daos, generating excel files and sending an email
}catch (Exception e){
//log error
}
}
Does someone have an idea of why this happens? Is it the garbage collector something to do with this?
I'm ashamed to admit it was only a "BadProgrammerException" because I had a call to a database connection outside the try...catch block that i hadn't seen before, so the problem was that I was not reaching the database and I couldn't figure it out with the log information (the database connection was intermitent). After I found this out, I corrected the database issue and quartz worked ok.
Related
i have a class where i perform some activities, and i want to create a job that will handle this operation automatically, scheduled every x minutes for example.
I am using Quartz, this class implements Job, and in my driver class i'm creating my jobdetail, scheduler and trigger and then starting it. However, the job isn't being executed, log info :
NOT STARTED.
Currently in standby mode.
Number of jobs executed: 0
The code for the scheduler in my driver class:
try {
JobDetail job = JobBuilder.newJob(TestMkFPMJob.class).withIdentity("TestMkFPMJob").build();
Trigger trigger = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(Integer.parseInt(strTimeSched)).repeatForever()).build();
SchedulerFactory schFactory = new StdSchedulerFactory();
Scheduler sch = schFactory.getScheduler();
sch.start();
sch.scheduleJob(job, trigger);
}
catch (SchedulerException e)
{
e.printStackTrace();
System.out.println("Scheduler Error");
}
With "TestMkFPMJob" being the job class where my operations are handled, and strTimeSched is already fetched and set as 120 fetched from
I've been looking for a similar issue but can't seem to find any tip to move forward, appreciate any.
Please note that this is my first time using Quartz/Job scheduling.
The log entry with NOT STARTED is misleading, as it is shown whenever a QuartzScheduler instance is created. It does not mean that the jobs are not running. It is written after the line Scheduler sch = schFactory.getScheduler(); is executed and the scheduler is started in the next line.
If I take your example and run it on my pc, it is working as designed:
public class Quartz {
public static void main(String[] args) {
try {
JobDetail job = JobBuilder.newJob(MyJob.class).withIdentity("myJob").build();
Trigger trigger = TriggerBuilder.newTrigger().withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(Integer.parseInt("10")).repeatForever()).build();
SchedulerFactory schFactory = new StdSchedulerFactory();
Scheduler sch = schFactory.getScheduler();
sch.start();
sch.scheduleJob(job, trigger);
}
catch (SchedulerException e)
{
e.printStackTrace();
System.out.println("Scheduler Error");
}
}
public static class MyJob implements Job {
#Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
System.out.println("runnning job");
}
}
}
I have a web application in which I am running some jobs periodically so for that I am using quartz framework here. Below is how I am starting all my jobs:
As soon as the server gets started up, it calls postInit method autmatically. And then I start all my jobs and it works fine:
#PostConstruct
public void postInit() {
logger.logInfo("Starting all jobs");
StdSchedulerFactory factory = new StdSchedulerFactory();
try {
factory.initialize(App.class.getClassLoader().getResourceAsStream("quartz.properties"));
Scheduler scheduler = factory.getScheduler();
// starts all our jobs using quartz_config.xml file
scheduler.start();
} catch (SchedulerException ex) {
logger.logError("error while starting scheduler= ", ExceptionUtils.getStackTrace(ex));
}
}
#PreDestroy
public void shutdown() {
logger.logInfo("Shutting down all jobs");
}
Now I want to stop all the jobs that are running as soon as we try to shutdown the app server. So whenever we try to shutdown the app server, it will call shutdown method automatically. Now I need some way where we can shutdown all the jobs as soon as shutdown method is called. What is the best way by which I can shutdown all the jobs as soon as shutdown method is called?
Below is my "quartz.properties" file. Do I really need "quartz.properties" file since I guess I am using default values anyways I think?
#------------------------- Threads ---------------------------------#
# how many jobs we should run at the same time?
org.quartz.threadPool.threadCount=15
# ----------------------------- Plugins --------------------------- #
# class from where we should load the configuration data for each job and trigger.
org.quartz.plugin.jobInitializer.class=org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames = quartz_config.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound = true
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
You can use Scheduler.shutdown() method as below and it is a good idea to externalize the quartz configuration even if you use the default parameters. This will make your code flexible.
private Scheduler scheduler;
#PostConstruct
public void postInit() {
logger.logInfo("Starting all jobs");
StdSchedulerFactory factory = new StdSchedulerFactory();
try {
factory.initialize(App.class.getClassLoader().getResourceAsStream("quartz.properties"));
scheduler = factory.getScheduler();
// starts all our jobs using quartz_config.xml file
scheduler.start();
} catch (SchedulerException ex) {
logger.logError("error while starting scheduler= ", ExceptionUtils.getStackTrace(ex));
}
}
#PreDestroy
public void shutdown() throws SchedulerException {
logger.logInfo("Shutting down all jobs");
scheduler.shutdown();
}
I am new to java and trying to learn quartz. I have main method
public static void main(String[] args) throws SchedulerException {
try {
JobDetail job1 = JobBuilder.newJob(Job1.class).withIdentity("job1", "group1").build();
Trigger trigger1 = TriggerBuilder.newTrigger().withIdentity("cronTrigger1", "group1")
.withSchedule(CronScheduleBuilder.weeklyOnDayAndHourAndMinute(3, 12, 38)).build();
Scheduler scheduler1 = new StdSchedulerFactory().getScheduler();
scheduler1.start();
scheduler1.scheduleJob(job1, trigger1);
scheduler1.shutdown();
}
catch (Exception e) {
e.printStackTrace();
}
Which works fine. It prints to the console on 3rd day of the week at 12:38 pm.
Now, what I want to do is to reschedule the trigger, so that it deletes the previous stored trigger and creates a new trigger with new schedule.
I read a lot of things at a lot of places but I just can't seem to understand clearly what I actually have to do, for ex:
public void execute(JobExecutionContext context) throws JobExecutionException {
Trigger newTigger = what ever you want;
Trigger oldTrigger = context.getTrigger()
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.rescheduleJob(oldTrigger.getKey(), newTrigger);
}
and also this:
// Define a new Trigger
Trigger trigger = newTrigger()
.withIdentity("newTrigger", "group1")
.startNow()
.build();
// tell the scheduler to remove the old trigger with the given key, and
// put the new one in its place
sched.rescheduleJob(triggerKey("oldTrigger", "group1"), trigger);
but I can't understand the approach(I do understand what is happening in the code though). Thanks in advance.
I have an application with a few different, long running quartz jobs. Every job is triggered by a kind of event (for example user action) and it is intended to run only once per such an event. In the environment where the application works the following scenario happens...
Application is running,
Long running job is triggered,
During the execution of the job application shutdown occurs,
Application is starded again.
Is it possible to cause that quartz will automatically refire the job started and not finished previously (in the previous session of the application)? I mean using jdbc job store, which works well for misfired jobs - but is it possible to refire not finished job.
This is the best approach I've found:
Configure quartz scheduler with:
org.quartz.scheduler.interruptJobsOnShutdownWithWait=true
Make your recoverable jobs implementing InterruptableJob, and manually trigger the current job as part of interrupt logic (example below).
Write your own ShutdownHook to call Scheduler.shutdown(true) or use quartz ShutdownHookPlugin
This way, when an ordered shutdown is detected by the VM (hard shutdowns bust be handled by RequestRecovery: quartz jobDetail requestRecovery), jobs implementing InterruptableJob will be interrupted and re-triggered. This trigger will not occur until next start.
There is a quick example of how to implement:
public static class TriggerOnInterruptJob implements InterruptableJob {
private boolean interrupt = false;
#Override
public void execute(JobExecutionContext context) throws JobExecutionException {
LOGGER.debug("START");
synchronized (mutex) {
mutex.notifyAll();
}
executionCount.incrementAndGet();
try {
while (!interrupt)
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
context.getScheduler().triggerJob(context.getJobDetail().getKey());
} catch (SchedulerException e) {
e.printStackTrace();
}
}
#Override
public void interrupt() throws UnableToInterruptJobException {
interrupt = true;
}
}
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.
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.