Batch Job RE-scheduling using Java , CronExpression - java

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..

Related

How can I change di job CRON expression in order to run my Spring Batch job twice a week?

in a Spring Batch application on which I am working on I scheduled a job in this way:
#Scheduled(cron = "0 30 01 * * 7")
public void runUpdateNotaryListInfoJob() {
LOGGER.info("SCHEDULED run of updateNotaryListInfoJob STARTED");
Map<String, JobParameter> confMap = new HashMap<>();
confMap.put("time", new JobParameter(System.currentTimeMillis()));
JobParameters jobParameters = new JobParameters(confMap);
try {
jobLauncher.run(updateNotaryListInfoJob, jobParameters);
}catch (Exception ex){
LOGGER.error(ex.getMessage());
}
}
This works fine and my job is runned every Sunday (day 7) at 01:30 of the night. Ok it is fine but now my client ask me to run it twice in a week (same time but in two different days). Is it possible to change the previous CRON expression so that my job is performed at 01:30 of every Wednesday and every Sunday?
A schedule like cron = "0 30 01 * * 3,7" triggers every 3rd and 7th day of the week.

How to correctly schedule this 5 minutes Spring Batch Job? Why is it starting immediatly instead of waiting for the set time?

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).

cron library for java

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));

Add multiple triggers to single quartz job

I want to dynamically add triggers to a job, but can't find any helpful methods off of Scheduler
I though i would just be able to call the scheduleJob method an repetitively, but this gives me tthe ObjectAlreadyExists Exception "because one already exists with this identification".
How can i do this?
EDIT
private boolean scheduleLoadJob( XfuScheduleTimeInfo time )
{
LoadScheduleJob job = new LoadScheduleJob( time );
JobDetail detail;
Integer id = Integer.valueOf( time.getScheduleId() );
if( _hashMap.containsKey( id ) )
{
detail = _hashMap.get( Integer.valueOf( time.getScheduleId() ) );
}
else
{
detail = job.getDetail();
_hashMap.put( id, detail );
}
try
{
Trigger newTrigger = job.getTrigger();
_log.debug( "------" + newTrigger.getKey() );
_quartzScheduler.scheduleJob( detail, newTrigger );
return true;
}
catch( ParseException e )
{
_log.error( "Unable to parse cron expression for " + job.getInfo() );
return false;
}
catch( SchedulerException e )
{
_log.error( "Job scheduling failed for " + job.getInfo() );
return false;
}
}
With Console Output
------ LoadJobs.Trigger-44
batch acquisition of 1 triggers
Producing instance of Job 'LoadJobs.Job-42', class=com.scheduling.LoadScheduleJob
Calling execute on job LoadJobs.Job-42
batch acquisition of 1 triggers
Job called for: 42 : 44
------ LoadJobs.Trigger-45
Job scheduling failed for 42 : 45 - 1/5 * * ? * *
This post gives a hint, but the conclusion ( schedulerInstance.add(trigger) ) is not valid as of Quartz 2.01.
Instead use the following, after assinging the job to the trigger ( one way is using the TriggerBuilder's forJob method )
schedulerInstance.scheduleJob( newTrigger )
CronTrigger trigger=null;
CronTrigger trigger1=null;
CronTrigger trigger2=null;
JobDetail job = new JobDetail();
job.setName("dummyJobName");
job.setJobClass(ExampleJob.class);
trigger = new CronTrigger();
trigger.setName("AppTrigger");
trigger.setGroup(job.getGroup());
trigger.setJobName(job.getName());
trigger.setJobGroup(job.getGroup());
trigger.setCronExpression("*/2 * * * * ?");
trigger1 = new CronTrigger();
trigger1.setName("AppTrigger1");
trigger1.setGroup(job.getGroup());
trigger1.setJobName(job.getName());
trigger1.setJobGroup(job.getGroup());
trigger1.setCronExpression("*/2 * * * * ?");
trigger2 = new CronTrigger();
trigger2.setName("AppTrigger2");
trigger2.setGroup(job.getGroup());
trigger2.setJobName(job.getName());
trigger2.setJobGroup(job.getGroup());
trigger2.setCronExpression("*/2 * * * * ?");
Scheduler scheduler = new StdSchedulerFactory().getScheduler();
scheduler.start();
scheduler.addJob(job, true);
scheduler.scheduleJob(trigger);
scheduler.scheduleJob(trigger1);
scheduler.scheduleJob(trigger2);
You can call scheduleJob repeatedly. Just make sure that you give each Trigger a unique name/group.
See TriggerBuilder.withIdentity: http://www.quartz-scheduler.org/docs/api/2.0.0/index.html

Running two jobs with Quartz in Java

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.

Categories