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.
Related
I want to read data for last 30 days from database for each day..
ItemReader - Read data for each day
ItemProcessor - Process data for each day
ItemWriter - Write the processed data into database.
I want to repeat this process till date..
public boolean processTicketStatistics() {
LocalDate startDate = LocalDate.now().minus(Period.ofDays(30));
LocalDate endDate = LocalDate.now().plus(Period.ofDays(1));
for (LocalDate d = startDate; d.isBefore(endDate); d = d.plusDays(1)) {
TicketStatistics statistics = new TicketStatistics();
statistics.setDate(localDateTimeToDate(d.atStartOfDay()));
statistics.setTickets(ticketRepository.count(TicketSpecification.ticketHasDateRange(
localDateTimeToDate(d.atStartOfDay()),
localDateTimeToDate(d.atTime(LocalTime.MAX)))));
ticketStatisticsRepository.save(statistics);
}
return true;
}
Can you please help me how to achieve this in Spring batch?
I would create a job that processes the data of a given day (ie the day is an identifying job parameter) and launch a job instance per day, for example:
LocalDate startDate = LocalDate.now().minus(Period.ofDays(30));
LocalDate endDate = LocalDate.now().plus(Period.ofDays(1));
for (LocalDate d = startDate; d.isBefore(endDate); d = d.plusDays(1)) {
JobParameters jobParameters = new JobParametersBuilder()
.addDate("date", toDate(d)) // TODO implement toDate to convert LocalDate to Date
.toJobParameters();
jobLauncher.run(job, jobParameters);
}
If the processing of each day is independent from other days (which I guess is the case), you can launch all job instances in parallel by configuring an asynchronous TaskExecutor (like a ThreadPoolTaskExecutor with a pool of 30 threads) in your JobLauncher.
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.
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";
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();
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?