Quartz with couple of jobs but only one running - quartz-scheduler

I have quartz schedule with couple of jobs but only one (1st one) is running. Even if I try to force the second job to run it doesn't.
// The Quartz Scheduler
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
JobDetailImpl jobDetail = new JobDetailImpl();
jobDetail.setJobClass(SchedulerJob.class);
jobDetail.setName("4HR");
jobDetail.setGroup("G");
// Initiate CronTrigger with its name and group name
CronTriggerImpl cronTrigger = new CronTriggerImpl();
cronTrigger.setName("4HR");
cronTrigger.setGroup("G");
// setup CronExpression
String CRON_EXPRESSION = "0 0 0/4 * * ?"; // fire every 4 hours
CronExpression cexp = new CronExpression(CRON_EXPRESSION);
// Assign the CronExpression to CronTrigger
cronTrigger.setCronExpression(cexp);
// schedule a job with JobDetail and Trigger
scheduler.scheduleJob(jobDetail, cronTrigger);
JobDetailImpl oneHRJob = new JobDetailImpl();
oneHRJob.setJobClass(Run1HRSchdule.class);
oneHRJob.setName("Job1HR");
oneHRJob.setGroup("G");
CronTriggerImpl oneHRTrigger = new CronTriggerImpl();
oneHRTrigger.setName("Trigger1HR");
oneHRTrigger.setGroup("G");
// Assign the CronExpression to CronTrigger
String CRON_EXPRESSION_1HR = "0 0 0/1 * * ?"; // fire every 1 hour
oneHRTrigger.setCronExpression( new CronExpression(CRON_EXPRESSION_1HR) );
// schedule a job with JobDetail and Trigger
scheduler.scheduleJob(oneHRJob, oneHRTrigger);
// start the scheduler
System.out.println ("Starting Scheduler");
scheduler.start();
System.out.println ("Scheduler started:" + scheduler.isStarted() );
scheduler.triggerJob( oneHRJob.getKey() );
I have tried changing the cron expression but hasn't helped.
What could I be doing wrong?

Related

Quartz .Net resume after application restart

I have quartz working with MS SQL, it stores all the job detail in sql but I don't know how to set it up to resume all the jobs after application restart.
can anyone please let me know how setup quartz to resume jobs after application restart.
This is what I do to schedule a job on api call
File.AppendAllText(#"C:\Temp\test.txt",$"Starting sechd at {DateTime.Now.ToString("ddMMyyyyHHmmss")}");
ISchedulerFactory sf = new StdSchedulerFactory();
IScheduler sc = sf.GetScheduler();
sc.Start();
IJobDetail emailJob = JobBuilder.Create<EmailJob>()
.WithIdentity("reportemail", "reportgroup")
.Build();
string dom = js.DayOfMonth.ToString();
if (js.DayOfWeek > 0)
dom = "?";
string dow = (js.DayOfWeek < 1) ? "*" : js.DayOfWeek.ToString();
string y = (js.Year > 0) ? js.Year.ToString() : "*";
string m = (js.Month > 0) ? js.Month.ToString() : "*";
string crn = $"{js.Second.ToString()} {js.Minute.ToString()} {js.Hour.ToString()} {dom} {m} {dow} {y}";
ITrigger trigger = TriggerBuilder.Create()
.ForJob(emailJob)
.WithIdentity("reporttrigger","reportgroup")
.WithCronSchedule("0 0/3 * ? * *")
.StartNow()
.Build();
sc.ScheduleJob(emailJob, trigger);
Thanks
Im currently using Quartz.Net in my MVC application, and what I have done is in my JobScheducler.cs I have a method called "Start" where I have placed all the code, for the schedules I want to be run on application start.
In Global.asax I have instantiated the JobScheduler and I then call the start method, which in turn. Starts all of the schedules I've set up to be run.

How can I run crone Trigger immediately using crone expression in java?

Below is my code, I want to run my job every ten minutes by crone expression.
I want the first time my job run immediately after that it should run on 10 minutes interval.I am using quartz-2.1.2
JobKey jobKeyA = new JobKey("abc", "abc");
JobDetail jobA = JobBuilder.newJob(ContiniousJob.class)
.withIdentity(jobKeyA).build();
Trigger trigger3 = TriggerBuilder
.newTrigger()
.withIdentity("abc", "abc")
.startNow()
.withSchedule(CronScheduleBuilder.cronSchedule("0 0/10 * * * ?"))
.build();
Thanks.
You don't need CronTrigger if you just want 10 minutes interval, you can just use SimpleTrigger:
Trigger trigger3 = TriggerBuilder
.newTrigger()
.withIdentity("abc", "abc")
.startNow()
.withSchedule(simpleSchedule()
.withIntervalInMinutes(10)
.repeatForever())
.build();
If you still need to use CronTrigger for any reason, this should work:
// Trigger to run immediately
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("abc", "abc")
.startNow()
.build();
Set<Trigger> triggers = new HashSet<>();
triggers.add(trigger);
// Your CronTrigger
Date delayedStart = DateUtils.addMinutes(new Date(), 10);
Trigger cronTrigger = TriggerBuilder
.newTrigger()
.withIdentity("abc", "abc")
.startAt(delayedStart)
.withSchedule(CronScheduleBuilder.cronSchedule("0 0/10 * * * ?"))
.build();
triggers.add(cronTrigger);
// Schedule job with multiple triggers
scheduler.scheduleJob(job, triggers, false);
One trigger to run immediately, another one to be your CronTrigger.
Unfortunately, there is no chances to fire cron rightaway.I have suggestion to schedule task right after when it needs to be launched with a some short delay period (current time + 1 minute).
Try to test your expression here.

Prevent Quartz job recovery from starting on long-runnng tasks

I'm building Quartz jobs with the RequestRecovery flag set, because I have multiple server instances running and if one fails while running a job, I'd like another instance to pick up that job and restart it.
IJobDetail job = JobBuilder.Create<SystemMaintenance>()
.WithIdentity("SystemMaintenance", "SystemMaintenance")
.RequestRecovery(true)
.WithDescription("System task that runs every 6 hours")
.Build();
However, what I've noticed is that if the job is running for a very long time (say over 10 minutes), the other instances will start running the job because they assume that it has failed, even though it is running fine.
Is there any way that I can periodically ping Quartz, perhaps through JobExecutionContext, to let it know that a specific instance is still running and processing a job, to prevent others from assuming failure and starting it?
EDIT:
My configuration looks like this:
NameValueCollection properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = "Scheduler";
properties["quartz.scheduler.instanceId"] = "AUTO";
properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
properties["quartz.threadPool.threadCount"] = "5";
properties["quartz.threadPool.threadPriority"] = "Normal";
properties["quartz.jobStore.misfireThreshold"] = "60000";
properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
properties["quartz.jobStore.useProperties"] = "true";
properties["quartz.jobStore.dataSource"] = "default";
properties["quartz.jobStore.tablePrefix"] = "QRTZ_";
properties["quartz.jobStore.clustered"] = "true";
properties["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz";
properties["quartz.dataSource.default.connectionString"] = ConnectionStringService.DatabaseConnectionString;
properties["quartz.dataSource.default.provider"] = "SqlServer-20";

Schedule task to run everyday at specific time with Quartz.NET

I am using Quartz.NET for doing a task everyday at specific hour and this is my code:
public class TestSchedule : ISchedule
{
public void Run()
{
DateTimeOffset startTime = DateBuilder.FutureDate(2, IntervalUnit.Second);
IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity("job1")
.Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1")
.StartAt(startTime)
.WithDailyTimeIntervalSchedule(x => x.OnEveryDay().StartingDailyAt(new TimeOfDay(7, 0)).WithRepeatCount(0))
.Build();
ISchedulerFactory sf = new StdSchedulerFactory();
IScheduler sc = sf.GetScheduler();
sc.ScheduleJob(job, trigger);
sc.Start();
}
}
my code is working, but problem is that works only once(it seems that , it's because WithRepeatCount(0) )
now, how can say that run everyday at 7 o'clock?
PS : I don't want use CronTrigger to do that.
DailyTimeIntervalTriggerImpl only support repeatCount.
This trigger also supports "repeatCount" feature to end the trigger
fire time after a certain number of count is reached. Just as the
SimpleTrigger, setting repeatCount=0 means trigger will fire once
only! Setting any positive count then the trigger will repeat count +
1 times. Unlike SimpleTrigger, the default value of repeatCount of
this trigger is set to REPEAT_INDEFINITELY instead of 0 though.
Cron expressions are beautiful and there's loads of tools which can help you to achieve what you're looking for.
Another alternative would be to use a SimpleTriggerImpl and set the interval every 24 hours:
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1")
.StartAt(startTime)
.WithSimpleSchedule(x => x.RepeatForever().WithIntervalInHours(24))
.Build();

quartz cron trigger first fire time

Is there any way setting crontrigger to begin after a specific date .That is crontrigger going to fire after a specific date using its cron expression.I try using crontrigger starttime and firstfire time but not worked.I can do this with using another trigger but i think there should be another way.
this is cron expression
0 0/5 * * * ?
i.e. at minutes (5,10,15,...00) not at now+5
this is log program writes
Trigger should start at Fri May 27 21:03:31 EEST 2011 // i expect it run on this time
Job start at Fri May 27 20:55:00 EEST 2011 //it ignore start time
Job start at Fri May 27 21:00:00 EEST 2011
Job start at Fri May 27 21:05:00 EEST 2011
public CronTrigger scheduleJob(RemoteJob job, String cronExpression,Date firstFireTime) throws SchedulerException, ParseException {
JobDetail jobDetail = new JobDetail(job.getDescription(), job.getName(), job.getClass());
CronTrigger crTrigger = new CronTrigger(
"cronTrigger", job.getName(), cronExpression);
scheduler.scheduleJob(jobDetail, crTrigger);
try{
Calendar c=Calendar.getInstance();
c.add(Calendar.MINUTE, 10);
firstFireTime=c.getTime();
FileWriter writer=new FileWriter("/opt/scheduler.cron",true);
writer.write("Trigger should start at " +c.getTime().toString()+"\n\n");
writer.close();
}catch(Exception e){
}
crTrigger.setStartTime(firstFireTime);
crTrigger.setMisfireInstruction(CronTrigger.MISFIRE_INSTRUCTION_DO_NOTHING);
return crTrigger;
}
this is job executed by trigger .
public class ExternalJob extends RemoteJob {
private static final Logger _logger = Logger.getLogger(ExternalJob.class.getName());
private static ExternalStorageProcessor processor = new ExternalStorageProcessor();
private ExternalTask task;
private static final String tempPath = "/opt/itaptemp/";
private String name;
private String description;
private static final long MARK=1L;
public ExternalJob(String name, String description) {
public void execute(JobExecutionContext context) throws JobExecutionException {
try{
Calendar c=Calendar.getInstance();
FileWriter writer=new FileWriter("/opt/scheduler.cron",true);
writer.write("Job start at " +c.getTime().toString()+"\n");
writer.close();
}catch(Exception e){
}
The problem is that you are using a cron which fires a every even minute beginng a 0 minute (0 0/5 * * * ? ).
You should set the start date alse to even minutes. Therefore you can use DateBuilder.EvenMinuteDateBefore(StartTime).
So if your startime was... Fri May 27 20:55:31 ... the method DateBuilder.EvenMinuteDateBefore(StartTime) will convert it to ...
Fri May 27 20:55:00.
Then your schedule will look like:
Job start at Fri May 27 20:55:00 EEST 2011
Job start at Fri May 27 21:00:00 EEST 2011
Job start at Fri May 27 21:05:00 EEST 2011
Set the startTime property to the future Date at which you want the schedule (expression) to start applying.
I see you say that you tried that and it didn't work, but it certainly should, so please try again.
CronTrigger ct = new CronTrigger("foo", "goo", "0 0/10 * * * ?"); // fire every ten minutes, all day every day
// construct a date of March 17, 2012 10:03:00
Calendar futureDate = Calendar.getInstance();
futureDate.set(Calendar.YEAR, 2012);
futureDate.set(Calendar.MONTH, GregorianCalendar.MARCH);
futureDate.set(Calendar.DAY_OF_MONTH, 17);
futureDate.set(Calendar.HOUR_OF_DAY, 10);
futureDate.set(Calendar.MINUTE, 3);
futureDate.set(Calendar.SECOND, 0);
futureDate.set(Calendar.MILLISECOND, 0);
// use the date as the startTime
ct.setStartTime(futureDate.getTime());
// check what time the trigger will first fire
List fireTimes = TriggerUtils.computeFireTimes(ct, null, 1);
Date firstFireTime = (Date) fireTimes.iterator().next();
System.out.println("First fire time: " + firstFireTime);
This results in:
First fire time: Sat Mar 17 10:10:00 MDT 2012