Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Quartz: Cron expression that will never execute

I know there is a duplicate here, which probably is exactly my case, though it would deserve some better explanation, which I will try to provide here.

I work with a Java web application using a Spring application context. In this context, I defined scheduled jobs using Quartz. These jobs are triggered by a cron defined in a .properties file.

The Spring context is embedded within the war, while the .properties file is on the application server (Tomcat in this particular case).

This is just fine and allows to define different crons according to the environment (development, integration, production, ...).

Now, when running this application locally on my own computer, I do not wish these jobs to be executed. Is there a way to write a cron expression which will never trigger?

like image 553
Chop Avatar asked Dec 12 '12 07:12

Chop


People also ask

What does 0 * * * * mean in crontab?

0 * * * * -this means the cron will run always when the minutes are 0 (so hourly) 0 1 * * * - this means the cron will run always at 1 o'clock. * 1 * * * - this means the cron will run each minute when the hour is 1.

How do you stop a cron expression?

Stop a cron job You can stop a single cron job by removing its line from the crontab file. To do that, run the crontab -e command and then delete the line for the specific task. Alternatively, you can stop the cron job by commenting it out in the crontab file.

How do I schedule a cron job every 10 minutes?

For example, if you have 1-10/2 in the Minutes field, it means the action will be performed every two minutes in range 1-10, same as specifying 1,3,5,7,9 . Instead of a range of values, you can also use the asterisk operator. To specify a job to be run every 20 minutes, you can use “*/20”.

How do you write a cron expression every 5 minutes?

Execute a cron job every 5 Minutes If you specify */5 in the 1st field, it runs every 5 minutes as shown below. Note: In the same way, use */10 for every 10 minutes, */15 for every 15 minutes, */30 for every 30 minutes, etc.


1 Answers

TL;DR

In Quartz 1, you may use this cron: 59 59 23 31 12 ? 2099 (last valid date).
In Quartz 2, you may use this cron: 0 0 0 1 1 ? 2200

Using an expression far in the future

Made some quick tests using org.quartz.CronExpression.

String exp = "0 0 0 1 1 ? 3000"; boolean valid = CronExpression.isValidExpression(exp); System.out.println(valid); if (valid) {     CronExpression cronExpression = new CronExpression(exp);     System.out.println(cronExpression.getNextValidTimeAfter(new Date())); } 

When I do String exp = "# 0 0 0 1 1 ?";, the isValid test returns false.

With the sample given above yet, the output is the following:

true null 

Meaning:

  • the expression is valid;
  • there is no upcoming date which matches this expression.

For the scheduler to accept a cron trigger, though, the latter must match a date in the future.

I tried several years and figured out that once the year is above 2300, Quartz seems not to bother anymore (though I did not find a mention to a maximal value for the year in Quartz 2's documentation). There might be a cleaner way to do this, but this will satisfy my needs for now.

So, in the end, the cron I propose is 0 0 0 1 1 ? 2200.

Quartz 1 variant

Note that, in Quartz 1, 2099 is the last valid year. You can therefore adapt your cron expression to use Maciej Matys's suggestion: 59 59 23 31 12 ? 2099

Alternative: Using a date in the past

Arnaud Denoyelle suggested something more elegant, which my test above validates as a correct expression: instead of choosing a date in a far future, choose it in a far past:

0 0 0 1 1 ? 1970 (the first valid expression according to Quartz documentation).

This solution does not work though.

hippofluff highlighted that Quartz will detect an expression in past will never be executed again and therefore throw an exception.

org.quartz.SchedulerException: Based on configured schedule, the given trigger will never fire. 

This seems to have been in Quartz for a long time.

Lessons learned: the test is not foolproof as is

This highlights a weakness of my test: in case you want to test a CronExpression, remember it has to have a nextValidTime1. Otherwise, the scheduler you will pass it to will simply reject it with the above mentioned exception.

I would advise adapting the test code as follows:

String exp = "0 0 0 1 1 ? 3000"; boolean valid = CronExpression.isValidExpression(exp); if (valid) {     CronExpression cronExpression = new CronExpression(exp);     valid = cronExpression.getNextValidTimeAfter(new Date()) != null; } System.out.println("Can I use <" + exp + ">? " + (valid ? "Go ahead!" : "This shall fail.")); 

There you go: no need to think, just read the output.


1 This is the part I forgot when testing Arnaud's solution making me the fool and proving my test wasn't me-proof.

like image 166
Chop Avatar answered Sep 22 '22 23:09

Chop