How could I validate cron expressions that are prepared for use of CronSequenceGenerator?
I mean, I cannot wait until the cron executes automatically as I'm defining like monthly intervals.
Is the following correct? How can I be sure?
monthly at midnight: `0 0 0 1 * *`
monthly at 1 am: `0 0 1 1 * *`
weekly, on sunday at midnight: `0 0 0 * * SUN`
The Spring's CronSequenceGenerator
class has a method
isValidExpression(String expression)
which takes the cron expression and returns a boolean.
I guess if you are ok with quartz api then you should use org.quartz.CronExpression.isValidExpression(String s)
Api ref http://quartz-scheduler.org/api/2.2.0/org/quartz/CronExpression.html
Actually I prefer to directly use "new CronSequenceGenerator(cronExpression)" instead of the static method isValidExpression.
Doing the new directly gives you a java.lang.IllegalArgumentExpression with a message telling you where the problem lies.
Unfortunately "isValidExpression" chokes the exception and simply returns false.
Related
I have a requirement to schedule a job in AWS CloudWatch events to be run once in every two days. I am using the below expression but getting a error Parameter ScheduleExpression is not valid
cron(0 0 */2 * ? *)
The below is the java code,
String cronExpression = "cron(0 0 */2 * ? *)"
PutRuleRequest request = new PutRuleRequest();
request
.withName(eventName)
.withRoleArn("arn:aws:iam::****")
.withScheduleExpression(cronExpression)
.withState(RuleState.ENABLED);
PutRuleResult result = cloudwatchConfig.cloudwatch().putRule(request);
cron(0 0 1/2 * ? *)
You can verify here.
If you put your syntax into cloudwatch, it too will report the same error you are seeing in the terraform,but fix it simple
cron(0 0 1-31/2 * ? *)
The explanation for each field is here: https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/ScheduledEvents.html
1-31 covers all the possible number of days in a month
i have spring boot and java application. at particular time of the day it should execute a method. so in the production server we have kept 4 dyno's and because of 4 dyno's it is executing 4 times per day. so i have used cache and getting the date . based on the date i try to execute the method only once .still it is executing 4 times.
#Scheduled(zone = "${scheduler.zone}", cron = "${scheduler.cron.job}")
public void processScheduled() {
synchronized(this) {
LocalDate localDate = redisTemplate.getValue("DATE");
if (localDate == null || LocalDate.now().isAfter(localDate)) {
log.info("Entered process in SchedulerConfig");
redisTemplate.putValue("DATE", LocalDate.now());
schedulerService.processScheduled();
}
}
}
the above code is written in a config java class.
the schedulerService.processScheduled(); should be triggered only once a day irrespective of no of the dyno's.
can anyone help me on this ?
I am assuming you are using Heroku Dynos, so there are 4 separate instances of your app running in production. Since there are 4 separate instances, your use of synchronized will be of little use here. All 4 of your instances are getting invoked at the same time, so there is a chance that, all of them will get the value of redisTemplate.getValue("DATE") as not null. You need an atomic operation with an centralized entity. Redis does serve as an centralized entity, but redisTemplate.getValue("DATE") and then redisTemplate.putValue("DATE", LocalDate.now()) is not an atomic operation. So it is very possible that 4 instances call redisTemplate.getValue("DATE") and get the real date. Since all 4 of them are not null, they will all update the value and then process your operation.
You should try using redisTemplate.delete(key). It is an atomic operation which returns true if the key is deleted else returns false. So your code may look like this.
#Scheduled(zone = "${scheduler.zone}", cron = "${scheduler.cron.job}")
public void processScheduled() {
boolean isDeleted= redisTemplate.delete("DATE"); // only one will get true, other will get false.
if (isDeleted) {
log.info("Entered process in SchedulerConfig");
schedulerService.processScheduled();
// sleep for some time and then update the date value
redisTemplate.putValue("DATE", LocalDate.now());
}
}
Or you can update the Date value after some time of the invocation with #Scheduled
#Scheduled(zone = "${scheduler.zone}", cron = "${scheduler.flag.update.job}")
public void updateDateFlag() {
redisTemplate.putValue("DATE", LocalDate.now());
}
I needing to use Quartz to execute a job. and when I try create a trigger on this mode :
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(identityTRIGGER, "grupo 01") .withSchedule(CronScheduleBuilder.atHourAndMinuteOnGivenDaysOfWeek(11, 20, DateBuilder.THURSDAY)).build();
don´t fired at 11:20 on thursday.
I´ve tried to do (with cron expression):
Trigger trigger = TriggerBuilder.newTrigger().withIdentity(identityTRIGGER, "grupo 01").withSchedule(CronScheduleBuilder.cronSchedule("0 20 11 * * 5 *") ).build();
and don't work eigther- shows the following message:
Caused by: java.text.ParseException: Support for specifying both a day-of-week AND a day-of-month parameter is not implemented
**OBS: If I use another chron expression (like "0/10 * * * * ?") this work **
what´s wrong with my trigger ?
tnx advanced
To prevent exception "ParseException: Support for specifying both a day-of-week AND a day-of-month parameter is not implemented" do not use the * (all) value for day-of-month, but you could use ? (any) instead.
This is the strange implementation limitation of quartz.
So, you could use expression
0 20 11 ? * 5 *
I am using cron-utils jar for generating cron expression
0 0 8 ? 1/1 5#3 *
3rd Thursday of every month at 8 o' clock
Below is my code for above expression:
CronBuilder withMonth = CronBuilder.cron(
CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ)
).withYear(always()).withDoM(QuestionMark.questionMark())
.withMonth(on(3, SpecialChar.HASH));
withMonth.withDoW(on(5)).withHour(on(8)).withMinute(on(0)).withSecond(on(0));
Cron instance = withMonth.instance();
System.out.println(instance.asString());
But I'm getting the following exception:
value missing for a#b cron expression
finally found solution
.withDoW(on(NUM_DAY_WEEK,SpecialChar.HASH, NUM_DAY_MONTH);
it will generate like 5#3
Im trying to manage scheduled tasks using spring boot. I want to execute my job only one time at a particular date ( specified by the user ).
Here is my Job :
#Component
public class JobScheduler{
#Autowired
JobController controller;
// Retrieving the Date entered by the user
controller.getDateForExecution(); // 2016/05/24 10:00 for example
#Scheduled(???)
public void performJob() throws Exception {
controller.doSomething();
}
There are multiple options for Scheduled annotation such as fixedDelay, fixedRate, initialDelay, cron ... but none of these can accept a Date.
So, how can i execute my method at the specified Date dynamically ( ie depending on the Date insered ) ?
Ps : The method can be executed more than once if the user enter two or more Dates ..
Spring has the TaskScheduler abstraction that you can use: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/scheduling.html#scheduling-task-scheduler
It has a method to schedule execution of a Runnable at a certain Date:
ScheduledFuture schedule(Runnable task, Date startTime);
A little off-topic maybe: If JobController is a Spring Controller (or RestController), I would not autowire it into the JobScheduler. I would inverse it and inject the JobScheduler into the JobController.
Ok I know this is a very old questions but for future references, here's the answer:
You can use cron property, which gives much more control over the scheduling of a task. It lets us define the seconds, minutes ,and hours the task runs at but can go even further and specify even the years that a task will run in.
Below is a breakdown of the components that build a cron expression.
Seconds can have values 0-59 or the special characters , - * / .
Minutes can have values 0-59 or the special characters , - * / .
Hours can have values 0-59 or the special characters , - * / .
Day of month can have values 1-31 or the special characters , - * ? / L W C .
Month can have values 1-12, JAN-DEC or the special characters , - * / .
Day of week can have values 1-7, SUN-SAT or the special characters , - * ? / L C # .
Year can be empty, have values 1970-2099 or the special characters , - * / .
Just for some extra clarity, I have combined the breakdown into an expression consisting of the field labels.
#Scheduled(cron = "[Seconds] [Minutes] [Hours] [Day of month] [Month] [Day of week] [Year]")
For more you can follow this article: https://dzone.com/articles/running-on-time-with-springs-scheduled-tasks