quartz job data-store persistence issue - java

I have the following question.
I have quartz scheduler 2.2.1
I have jdbc datastore
I have marked the job as Persistent
I can see the trigger and the job info saved into the db.
Yet, it seems my job datamap information does not survive an application restart.
When I restart the application the data I saved into the datamap seem to disappear and the datamap is empty when the application is restarted.
context.getJobDetail().getJobDataMap().putAsString(LAST_EXEC, curTimeMilliSecs);
I have the following in the jobs.xml
<job>
<name>check-new-events-job</name>
<group>EVENTS_GROUP</group>
<description>Check new events in the db</description>
<job-class>jobs.CheckNewEventsJob</job-class>
<durability>true</durability>
<recover>true</recover>
</job>
<trigger>
<cron>
<name>check-new-events-trigger</name>
<group>EVENTSTRIGGER_GROUP</group>
<job-name>check-new-events-job</job-name>
<job-group>EVENTS_GROUP</job-group>
<cron-expression>0 0/1 * * * ?</cron-expression>
</cron>
</trigger>
My job is configured to be
#PersistJobDataAfterExecution
#DisallowConcurrentExecution
public class CheckNewEventsJob implements Job {
The goal of this job is to survive application restarts and keep track of all the last executions.
Any ideas where to look ?
Thanks a lot!

Related

Schedule Quartz job and run in startup

I defined a job with Quartz that calls a web service. I have a trigger with Cron expression which run every 50 minutes as 0 0/50 * ? * * * .
I have a requirement that execute the job in startup application and after that every 50 minutes.
the job factory is:
Trigger trigger = newTrigger().withIdentity(name, "our.trigger")
.withSchedule(CronScheduleBuilder.cronSchedule("0
0/50 * ? * * *")).startNow().build();
JobDetail jobDetail = newJob(jobClass).withIdentity(name, "our.job").build();
Set<Trigger> triggers = new HashSet<>();
triggers.add(trigger);
stdScheduler.scheduleJob(jobDetail, triggers, true);
stdScheduler.start();
How do I solve this issue?
I solved the problem with the following code:
Trigger startupTrigger = newTrigger().withIdentity(name+".startup", "trigger")
.withSchedule(SimpleScheduleBuilder.repeatSecondlyForTotalCount(1)).startNow().build();
Thanks for #biiyamn

Quartz trigger does not fire immediately

I'd like to execute the job ~immediately with quartz scheduler using jdbc datastore. However I have like 20-30 seconds delay between the scheduling and trigger fire even though I schedule with now() or calling triggerJob.
I tried to execute the job with a simple trigger:
JobKey key = //...
JobDetail jobDetail = newJob(jobBean.getClass())
.withIdentity(key)
.usingJobData(new JobDataMap(jobParams))
.storeDurably()
.build();
Trigger trigger = newTrigger()
.withIdentity(key.getName(), key.getGroup())
.startNow()
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withMisfireHandlingInstructionFireNow()
.withRepeatCount(0))
.build();
scheduler.scheduleJob(jobDetail, trigger);
And I also tried to trigger with scheduler:
JobKey key = // ...
JobDetail jobDetail = newJob(jobBean.getClass())
.withIdentity(key)
.storeDurably()
.build();
scheduler.addJob(jobDetail, true);
scheduler.triggerJob(key, new JobDataMap(jobParams));
Here are the listener logs that shows the delay.
2019-05-15 13:59:52,066Z INFO [nio-8081-exec-2] c.m.f.s.logger.SchedulingListener : Job added: newsJobTemplate:1557928791965
2019-05-15 13:59:52,066Z INFO [nio-8081-exec-2] c.m.f.s.logger.SchedulingListener : Job scheduled: newsJobTemplate:1557928791965
2019-05-15 14:00:18,660Z INFO [eduler_Worker-1] c.m.f.s.logger.TriggerStateListener : Trigger fired: QUARTZ_JOBS.newsJobTemplate:1557928791965 {}
2019-05-15 14:00:18,703Z INFO [eduler_Worker-1] c.m.f.s.logger.JobExecutionListener : Job will be executed: QUARTZ_JOBS.newsJobTemplate:1557928791965
2019-05-15 14:00:19,284Z INFO [eduler_Worker-1] c.m.f.s.logger.JobExecutionListener : Job was executed: QUARTZ_JOBS.newsJobTemplate:1557928791965
I found crumbs here and there that suggested that the problem is transaction related.
So I removed #Transactional from the service method and voila it worked.
Looks like when you call trigger the scheduler thread asyncronously tries to look up schedules and triggers from the DB but the transaction is not committed at that time. Later the scheduler thread looks up the db again and it finds it finally.
zolee's answer describes the problem perfectly, but there are also a few things one can do to solve it.
One imperfect solution is to reduce org.quartz.scheduler.idleWaitTime. In fact, the problem itself is described, though somewhat obliquely, in the quartz configuration doc, org.quartz.scheduler.idleWaitTime section.
Normally you should not have to ‘tune’ this parameter, unless you’re
using XA transactions, and are having problems with delayed firings of
triggers that should fire immediately.
That will allow you to reduce 30-second delay to 5 seconds or even less.
A full solution is to extend QuartzScheduler to add transaction support. Exact implementation will depend on what library/code you're using for transaction support, but it worked for us perfectly.
class TransactionAwareScheduler extends QuartzScheduler {
#Override
protected void notifySchedulerThread(long candidateNewNextFireTime) {
if (insideTransaction) {
transaction.addCommitHook(() -> {
super.notifySchedulerThread(candidateNewNextFireTime);
});
}
} else {
super.notifySchedulerThread(candidateNewNextFireTime);
}
}

start the job immediately using quartz framework?

I am running some jobs periodically using quartz framework. I have a below quartz_config xml file which contains all the jobs I am running and at what interval.
<job-scheduling-data
xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_2_0.xsd"
version="1.8">
<schedule>
<job>
<name>ParserApp</name>
<job-class>com.process.task.ParserApp</job-class>
</job>
<trigger>
<cron>
<name>ParserApp</name>
<job-name>ParserApp</job-name>
<cron-expression>0 0 0/3 1/1 * ? *</cron-expression>
</cron>
</trigger>
</schedule>
</job-scheduling-data>
I am running ParserApp job every 3 hours. Now what I have noticed is - whenever I start my application, it doesn't start ParserApp job immediately. What it does instead is, it starts ParserApp jobs after 3 hours only which is fine as per cron expression. Is there any way by which I can start ParserApp job immediately whenever application is started up and then next run should happened after 3 hours only just like java ScheduledExecutorService does?
In the below code, as soon as you start executorService, it will call parserApp immediately and then it will call parserApp again after 3 hours periodically. Is there any way to do the same thing using quartz-scheduler?
executorService.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
parserApp();
}
}, 0, 3, TimeUnit.HOURS);
Below is how I am starting all the jobs using quartz scheduler:
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));
}

Multiple Jobs in Quartz Scheduler not running according to the triggers

I have configured a quartz scheduler with 4 different jobs, each triggering every 1 minute. The schedule I have configured is as follows:-
<schedule>
<job>
<name>LockMonitor</name>
<job-class>background.jobs.LockMonitor</job-class>
</job>
<trigger>
<simple>
<name>LockJobTrigger</name>
<job-name>LockMonitor</job-name>
<repeat-count>-1</repeat-count>
<repeat-interval>60000</repeat-interval>
</simple>
</trigger>
<job>
<name>LogMonitor</name>
<job-class>background.jobs.LogMonitorJob</job-class>
</job>
<trigger>
<simple>
<name>LogMonitorTrigger</name>
<job-name>LogMonitor</job-name>
<repeat-count>-1</repeat-count>
<repeat-interval>60000</repeat-interval>
</simple>
</trigger>
<job>
<name>ProcessMonitor</name>
<job-class>background.jobs.ProcessMonitor</job-class>
</job>
<trigger>
<simple>
<name>ProcessMonitorTrigger</name>
<job-name>ProcessMonitor</job-name>
<repeat-count>-1</repeat-count>
<repeat-interval>60000</repeat-interval>
</simple>
</trigger>
<job>
<name>HealthCheck</name>
<job-class>background.jobs.HealthCheck</job-class>
</job>
<trigger>
<simple>
<name>HealthCheckTrigger</name>
<job-name>HealthCheck</job-name>
<repeat-count>-1</repeat-count>
<repeat-interval>60000</repeat-interval>
</simple>
</trigger>
</schedule>
The problem that I am encountering is that only the 1st and 2nd jobs are getting executed most of the time. The 3rd and 4th jobs - namely ProcessMonitor and HealthCheck are getting executed only once in a while. Can someone help me with this? Is this because I have configured the same time interval for all the jobs? Is there any means by which I can ensure that all the 4 jobs are executed before starting the next set of execution?
I have configured all the jobs as implements StatefulJob
How many threads did you configure? When I keep the number of thread == number of jobs registered to run in the Quartz framework, everything seems to run as expected.

How to use quartz scheduler in java?

I need to schedule a task that will run everyday on 7:00 p.m. in java using quartz. Can someone point out a good tutorial on how to use quartz scheduler in java?
Take a look at quartz API documentation.
Edit:
Working URL for quartz API Documentation
To run everyday at 7pm, configure in your quartz.xml. Here "name" is whatever you want it to be, "job-name" should be same as the job-name you mentioned in between job tags.
<job>
<name>Scheduletracer</name>
<job-class>//here goes package name.program name</job-class>
</job>
<trigger>
<cron>
<name>server1</name>
<job-name>ScheduleTracer</job-name>
<cron-expression>0 0 19 * * ?</cron-expression>
</cron>
</trigger>

Categories

Resources