Spring terminates context when Quartz jobs are running - java

I create Quartz job and start scheduler
JobDetail job = newJob(InfoCrawlerJob.class)
.withIdentity("job id", "group")
.usingJobData(jobData)
.build()
SimpleTrigger trigger = newTrigger()
.withIdentity("trigger id", "trigger-group")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInSeconds(100)
.withRepeatCount(10))
.build()
scheduler.scheduleJob(job, trigger)
scheduler.start()
Quartz jobs are working correclty. The main problem is Spring doesn't wait jobs to be finished. How can I fix it?

Have a look at Spring Quartz Support
Spring Reference Chapter 25.6 Using the OpenSymphony Quartz Scheduler
Class org.springframework.scheduling.quartz.SchedulerFactoryBean
This class has a method: setWaitForJobsToCompleteOnShutdown(boolean) , I would expect that this is what you need.

Related

Spring boot and Quartz - Job not executing immediately

I am configuring Quartz job with Spring boot. The requirement is to execute the job immediately without attaching any schedule.
Here is what my code looks like
JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
String jobName = jobName(taskContext);
factoryBean.setJobClass(MyJobClass.class);
factoryBean.setDurability(true);
factoryBean.setApplicationContext(applicationContext);
factoryBean.setName("Hello job");
factoryBean.setGroup("Hello job group");
JobDataMap jobData = new JobDataMap(new HashMap<>());
factoryBean.setJobDataMap(jobData);
factoryBean.afterPropertiesSet();
JobDetail job = factoryBean.getObject();
Scheduler scheduler = schedulerFactoryBean.getScheduler();
scheduler.addJob(job, replace);
scheduler.triggerJob(job.getKey());
And here is how quartz.properties looks like
org.quartz.scheduler.instanceName=springBootQuartzApp
org.quartz.scheduler.instanceId=AUTO
org.quartz.threadPool.threadCount=10
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.useProperties=true
org.quartz.jobStore.misfireThreshold=2000
org.quartz.jobStore.tablePrefix=qrtz_
org.quartz.jobStore.isClustered=false
org.quartz.plugin.shutdownHook.class=org.quartz.plugins.management.ShutdownHookPlugin
org.quartz.plugin.shutdownHook.cleanShutdown=TRUE
The problem is that the job is not firing immediately and is getting picked up as misfire instruction. It is executed right exactly after the misfireThreshold.
Please let me know, if I have missed something in the configuration or didn't call any appropriate API.
I got the same issue.
If your quartz is using a data source with transaction: #EnableTransactionManagement.
Please add #Transactional to the method of your code, then the transaction is committed immediately.
Later the scheduler thread looks up the db again and fire it finally.

Spring with quartz and jpa transactions

Reading http://www.quartz-scheduler.org/documentation/quartz-2.x/configuration/ConfigJobStoreCMT.html it says that JTA transactions are supported with JobStoreCMT
Is it possible to configure quartz to run with JPA transaction manager? If not I assume Atomikos or Bitronix should be used with spring to enable JTA?
Basically I want quartz scheduler to roll back if the exception is thrown e.g.
#Transactional
public void scheduleJob(QuartzJobData quartzJobData) throws Exception {
SimpleTrigger trigger = (SimpleTrigger) newTrigger()
.withIdentity(name, group)
...
.build();
scheduler.scheduleJob(trigger);
throw new Exception("my exception");
// after exception I'd expect quartz to roll back
}
Note that I don't have any problems with running transactions in quartz jobs themselves. I only have problems with quartz scheduler not rolling back as shown in code example above.

Scheduler Quartz start but not it's running more time

In my web-app (Tomcat 6) I define a Quartz Scheduler in a class extending HttpServlet: this class is called to init.
The scheduler runs immediately and it has an interval of 1 minute, but after the first step it's not running.
When I change the parameter of scheduler by webpage, the scheduler is running correctly with the same code.
This is the code:
JobDetail job = newJob(ClassOfTask.class).withIdentity(NAME_JOB_MAIL, NAME_JOB_THREAD).build();
//various code
String cronExpression = buildCronExpression();
Trigger trigger = newTrigger().withIdentity(NAME_TRIGGER).startAt(startJob).endAt(endJob).forJob(job.getKey()).withSchedule(cronSchedule(cronExpression)).build();
scheduler.addJob(jobDetail, true);
scheduler.scheduleJob(trigger);
I tried to insert
scheduler.start();
but the problem remains.
When I modify the scheduled task in web page, I use this method
scheduler.rescheduleJob(oldTrigger.getKey(), trigger);
and in this case it works.
What's it the problem?

How to cancel a scheduled Quartz job in Spring

I'm using Spring to inject a Quartz scheduler (abstracted with Spring's TaskScheduler interface) into my app that loads jobs configured from a database at startup.
It adds each job in the scheduler something like this:
TaskScheduler taskScheduler = ...;//injected
Runnable runableThing = ...;
String cronExpression = ...; //from DB
taskScheduler.schedule(runableThing, new CronTrigger(cronExpression));
my question is this: Is it possible to specify something like a job_id that can subsequently be used to cancel the job/trigger - say in response to a user selecting the job to be cancelled in the web interface?
I've looked at the Spring docs and can't see a way to do this.
Any ideas gratefully received.
Unscheduling a Particular Trigger of Job
scheduler.unscheduleJob(triggerName, triggerGroup);
Deleting a Job and Unscheduling All of Its Triggers
scheduler.deleteJob(jobName, jobGroup);
Ref: http://www.opensymphony.com/quartz/wikidocs/UnscheduleJob.html
ScheduledFuture<V> job = taskSchedule.schedule(runableThing, new CronTrigger(cronExpression))
job.cancel(true);

What's the best way to initialize Quartz?

I'm not really sure what is the best way to initialize Quartz to schedule a cron job.
My environment is Tomcat. I have one job that needs to be triggered every day.
Should I create a separate Servlet to initialize Quartz and schedule my job?
I'm thinking of creating a Servlet and on the init() schedule my job something like this:
SchedulerFactory sf=new StdSchedulerFactory();
Scheduler sched=sf.getScheduler();
JobDetail jd=new JobDetail("job1","group1",CronJob.class);
CronTrigger ct=new CronTrigger("cronTrigger","group2","0 0/1 * * * ?");
sched.scheduleJob(jd,ct);
sched.start();
I'm new to Quartz but I guess I always need to keep a reference to the SchedulerFactory in order for Quartz to be running, therefore having that on a Servlet will be best option?
You might want to take a look at the Cookbook section on the Quartz site.
There are two easy built-in methods for starting a Quartz Scheduler within a servlet environment, using either a <listener> or <servlet> in the app's web.xml.

Categories

Resources