I have Quartz coded as follows and the first job runs perfectly:
JobDetail jd = null;
CronTrigger ct = null;
jd = new JobDetail("Job1", "Group1", Job1.class);
ct = new CronTrigger("cronTrigger1","Group1","0/5 * * * * ?");
scheduler.scheduleJob(jd, ct);
jd = new JobDetail("Job2", "Group2", Job2.class);
ct = new CronTrigger("cronTrigger2","Group2","0/20 * * * * ?");
scheduler.scheduleJob(jd, ct);
But I'm finding that Job2, which is a completely separate job to Job1, will not execute.
The scheduler is started using a listener in Java. I've also tried using scheduler.addJob(jd, true); but nothing changes. I'm running Java through a JVM on windows 7.
How do you know the job does not run? If you substitute Job1.class for Job2.class, does it still fail? When you swap order in which they're added to scheduler, or only leave Job2? Or if you strip down Job2 to only print a message to console?
I suspect Job2 execution dies with an exception.
Related
I am working on a Spring Batch application and I am finding some difficulties trying to correctly schedule a job.
I have this class where my job was scheduled:
/**
* This bean schedules and runs our Spring Batch job.
*/
#Component
#Profile("!test")
public class SpringBatchExampleJobLauncher {
private static final Logger LOGGER = LoggerFactory.getLogger(SpringBatchExampleJobLauncher.class);
#Autowired
#Qualifier("launcher")
private JobLauncher jobLauncher;
#Autowired
#Qualifier("updateNotaryDistrictsJob")
private Job updateNotaryDistrictsJob;
#Autowired
#Qualifier("updateNotaryListInfoJob")
private Job updateNotaryListInfoJob;
#Scheduled(cron = "0 */5 * * * *")
public void runUpdateNotaryDistrictsJob() {
LOGGER.info("SCHEDULED run of updateNotaryDistrictsJob STARTED");
Map<String, JobParameter> confMap = new HashMap<>();
confMap.put("time", new JobParameter(System.currentTimeMillis()));
JobParameters jobParameters = new JobParameters(confMap);
try {
jobLauncher.run(updateNotaryDistrictsJob, jobParameters);
}catch (Exception ex){
LOGGER.error(ex.getMessage());
}
}
}
As you can see on my runUpdateNotaryDistrictsJob() method I set this Spring CRON expression:
#Scheduled(cron = "0 */5 * * * *")
in order to start my updateNotaryDistrictsJob every 5 minutes.
The problem is that when I run my application in debug mode I can see that the job is immediately performed (it stop on the first breakpoint). It seems that it is not waiting the 5 minutes set by the cron expression.
What is wrong? How can I try to solve this issue?
The cron expression 0 */5 * * * * does not read as you expect. "It seems that it is not waiting the 5 minutes set by the cron expression.", this is not what the cron expression defines. The cron expression will run at second 0, every 5 minutes starting at minute 0, of every hour, which means that it will never wait 5 minutes after the service has started. As an example, if you started it at 10:22, it will run at 10:25.
If you really need it to wait 5 minutes after service has started, you should consider using #Scheduled(fixedRate = 5000, initialDelay = 5000).
I have a job running which runs on a particular time every day.
I have to update the CronExpression of the Job using some logic, problem is once the CronExpression is update I have to reStart the server to run that job with new time.
How can I restart the job without re-starting my server.
I have searched through other problem but not able to find my solution.
My job to update the cronExpression for another job is as:
public void reSchedulerNotofocationjob(){
List<Slots> slots=config.getActiveConfiguration().getSlotDetils();
int size=slots.size();
LocalTime slotTime;
LocalTime currenttime=new LocalTime();
String cronExp;
BatchJobs batchJobs= mongoOperations.findById("5b1f69c21f74e5ecc0c607ea", BatchJobs.class);
logger.debug("batch job id and job name "+batchJobs.getId()+" and "+batchJobs.getJobName());
for(int i=0; i<size;i++){
slotTime= LocalTime.parse(slots.get(i).getSlotTime());
if(currenttime.isBefore(slotTime)){
cronExp=slotTime.getSecondOfMinute()+" "+slotTime.getMinuteOfHour()+" "+slotTime.getHourOfDay()+" * * ? *";
mongoOperations.findAndModify(new Query(Criteria.where("_id").is("5b1f69c21f74e5ecc0c607ea")), new Update().set("cronExpression", cronExp), BatchJobs.class);
break;
}else{
if(i+1<size){
slotTime= LocalTime.parse(slots.get(i+1).getSlotTime());
if(currenttime.isBefore(slotTime)){
cronExp=slotTime.getSecondOfMinute()+" "+slotTime.getMinuteOfHour()+" "+slotTime.getHourOfDay()+" * * ? *";
mongoOperations.findAndModify(new Query(Criteria.where("_id").is("5b1f69c21f74e5ecc0c607ea")), new Update().set("cronExpression", cronExp), BatchJobs.class);
break;
}
}else{
slotTime= LocalTime.parse(slots.get(0).getSlotTime());
cronExp=slotTime.getSecondOfMinute()+" "+slotTime.getMinuteOfHour()+" "+slotTime.getHourOfDay()+" * * ? *";
mongoOperations.findAndModify(new Query(Criteria.where("_id").is("5b1f69c21f74e5ecc0c607ea")), new Update().set("cronExpression", cronExp), BatchJobs.class);
break;
}
}
}
}
How to restart the batch job..
I am looking for a cron expression library in java. Something that can parse cron expressions and return me future fire times for the trigger.
API on the lines of.
CronExpression cronExpression = new CronExpression("0 30 4 * * *");
List<Date> fireTimes = cronExpression.getFireTimes(todaysDate, nextWeekDate);
I don't want to use something as complicated as quartz. The purpose is to basically use cron like a regex for timings. That's all. I do not want a background scheduler.
I tried googling but wasn't able to find anything very helpful. Any suggestions would be appreciated.
Regards,
Pulkit
P.S - I looked at using the CronExpression class out of quartz. Wasn't very helpful - failing some tests.
You can definitely make use of cron4j for cron expessions and scheduling.
also you might find this post from chirag interesting,
cronTrigger.getExpressionSummary()
Example:
CronTrigger t = new CronTrigger();
t.setCronExpression("0 30 10-13 ? * WED,FRI");
System.out.println(""+t.getExpressionSummary());
Output:
seconds: 0
minutes: 30
hours: 10,11,12,13
daysOfMonth: ?
months: *
daysOfWeek: 4,6
lastdayOfWeek: false
nearestWeekday: false
NthDayOfWeek: 0
lastdayOfMonth: false
years: *
Sounds like cron-utils may be useful to you. Is not a scheduler. Provides methods to handle a cron definition and return last/next execution given a DateTime.
Here a snippet from the docs:
CronDefinition cronDefinition = CronDefinitionBuilder.instanceDefinitionFor(QUARTZ);
CronParser parser = new CronParser(cronDefinition);
//Get date for last execution
DateTime now = DateTime.now();
ExecutionTime executionTime = ExecutionTime.forCron(parser.parse("* * * * * * *"));
DateTime lastExecution = executionTime.lastExecution(now));
//Get date for next execution
DateTime nextExecution = executionTime.nextExecution(now));
//Time from last execution
Duration timeFromLastExecution = executionTime.timeFromLastExecution(now);
//Time to next execution
Duration timeToNextExecution = executionTime.timeToNextExecution(now);
I was able to solve the problem using dummy triggers on quartz. I didn't schedule and jobs etc, simply used the trigger api to compute all the times the job should fire based on a cron expression.
Best,
Pulkit
OperableTrigger trigger = (OperableTrigger)TriggerBuilder
.newTrigger()
.withIdentity("trigger1", "group1")
.withSchedule(
SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(5).repeatForever()
)
.build();
Date startDate = new Date(); Date endDate = new Date(startDate.getTime() + 1000000);
List<Date> dateList = TriggerUtils.computeFireTimesBetween(trigger, new BaseCalendar(), startDate, endDate);
System.out.println("******Times**********");
for(Date date : dateList) {
System.out.println(date.toString());
}
System.out.println("*********************");
In case this is helpful to others too, I tried the other options but wasn't satisfied with any and ended up writing my own very small library just for that purpose, crony. It's available on maven-central.
The code you wanted would be, with crony:
Cron cronExpression = Cron.parseCronString("0 30 4 * * *").get();
Stream<ZonedDateTime> fireTimes = CronExecution
.getNextExecutionDates(cron, todaysDate)
.takeUntil(d -> d.isAfter(nextWeekDate));
I have an application that only implement Map function.
I'm creating 1000 jobs, each with a unique PrefixFilter.
Example:
public void startNewScan(String prefix, long endTime)
Job job = new Job(conf, "MyJob");
job.setNumReduceTasks(0);
Scan scan = new Scan();
scan.setTimeRange(0, endTime);
scan.addColumn(Bytes.toBytes("col"), Bytes.toBytes("Value"));
scan.setFilter(new PrefixFilter(prefix.getBytes()));
TableMapReduceUtil.initTableMapperJob(tableName, scan, ExtractMapper.class, ImmutableBytesWritable.class, Result.class, job);
job.waitForCompletion(true);
}
Now - I don't want to wait for completion, because executing 1000 jobs would take me forever. Creating a thread for each job is also not an option.
Is there anything built in for this usage?
Something like JobsPool that accepts all the jobs and has its own waitForCompletion for all the jobs.
Use:
job.submit();
"Submit the job to the cluster and return immediately."
I am using Quartz as followed:
schedulerFactory = new StdSchedulerFactory();
scheduler = schedulerFactory.getScheduler();
JobDetail startECMSJob = new JobDetail("startECMSJob", "group1", StartECMSJob.class);
Trigger trigger = TriggerUtils.makeMinutelyTrigger(30);
trigger.setName("TriggersGroup1");
trigger.setGroup("group1");
scheduler.scheduleJob(startECMSJob, trigger);
scheduler.start();
Problem is that Quartz starting straight away on deploy. I do want it to start only 30 mins after deploy.
same thign when I rescehduale it. I dont want it to start straight away as it rescheduale.
rescheduale code:
//JobDetail startECMSJob = new JobDetail("startECMSJob", "group1", StartECMSJob.class);
JobDetail jobDetail=jobContext.getJobDetail();
Trigger trigger = TriggerUtils.makeSecondlyTrigger(30);
trigger.setName("aa");
trigger.setGroup("group1");
trigger.setJobName(jobContext.getJobDetail().getName());
trigger.setJobGroup(jobContext.getJobDetail().getGroup());
Scheduler scheduler = jobContext.getScheduler();
scheduler.rescheduleJob("TriggersGroup1", "group1", trigger);
any idea how can i choose the first trigger?
thanks,
ray.
trigger.setStartTime(new Date(System.currentTimeMillis() + 30 * 60 * 1000));