Quartz: Cron expression that will never be executed

I know that there is a duplicate here, which is probably exactly my business, although it deserves a better explanation, which I will try to provide here.

I am working with a Java web application using the context of a Spring application. In this context, I have defined scheduled tasks using Quartz. These jobs are started by cron defined in the .properties file.

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

Itโ€™s just perfect and allows you to define different cross-countries in accordance with the environment (development, integration, production, ...).

Now, when I run this application locally on my own computer, I do not want these tasks to be performed. Is there a way to write a cron expression that will never fire?

+70
spring quartz-scheduler
Dec 12 '12 at 7:56
source share
6 answers

TL; DR

In Quartz 1 you can use this cron: 59 59 23 31 12? 2099 59 59 23 31 12? 2099 59 59 23 31 12? 2099 59 59 23 31 12? 2099 (last valid date).
In Quartz 2, can you use this cron: 0 0 0 1 1? 2200 0 0 0 1 1? 2200 0 0 0 1 1? 2200 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 do I do String exp = "# 0 0 0 1 1?"; , the isValid test returns false .

With the example above, the result is as follows:

 true null 

Meaning:

  • expression is valid;
  • There is no upcoming date that matches this expression.

However, in order for the scheduler to accept the cron trigger, the latter must correspond to a date in the future.

I tried for several years and realized that when the year exceeds 2300, Quartz seems to no longer bother (although I did not find mention of the maximum value for the year in the Quartz 2 documentation ). There may be a cleaner way to do this, but it will satisfy my needs at the moment.

So, in the end, the cron offered to me is - 0 0 0 1 1? 2200 0 0 0 1 1? 2200 0 0 0 1 1? 2200 0 0 0 1 1? 2200

Quartz 1 option

Please note that in Quartz 1, 2099 is the last valid year . So you can adapt your cron expression to use the Maciej Matys clause : 59 59 23 31 12? 2099 59 59 23 31 12? 2099 59 59 23 31 12? 2099 59 59 23 31 12? 2099

Alternative: use date in the past

Arno Denoyel suggested something more elegant, which my test confirms above as the correct expression: instead of choosing a date in the distant future, select it in the distant past:

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

This solution does not work though.

hippofluff emphasized that Quartz will detect that an expression in the past will never be executed again, and therefore throws an exception.

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

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

Lessons learned: the test is not reliable, as is

This underscores the weakness of my test: if you want to test CronExpression , remember that it must have nextValidTime 1 . Otherwise, the scheduler to which you pass it will simply reject it with the above exception.

I would advise you to adapt 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 conclusion.




1 This is the part that I forgot when I tested the Arnaud solution, making me a fool and proving that my test was not proof for me.

+60
Dec 12
source share

Technically, the valid values โ€‹โ€‹for the Quartz year field field are 1970-2099, so 2300 is not an expected value. I assume that you really need to do this, and your version of Quartz is trying to apply the actual cron syntax (day 1-31, month 1-12, etc.).

Currently, I am using the following code in the Resque-scheduler for Rails, which accepts schedule information in the confirmed crontab format to create a test job only for manual launch:

 cron: "0 5 31 2 *" 

Work will wait patiently in the early morning of February 31 before launch. For the equivalent in Quartz crontrigger, try this line or its variant:

 0 0 5 31 2 ? 
+36
Dec 18 '12 at 17:12
source share

Try this: 59 59 23 31 12 ? 2099 59 59 23 31 12 ? 2099

+25
Feb 06 '13 at 15:45
source share

I found this while trying to solve a similar problem - disabling the cron expression - but ran into the same problems as requiring the correct schedule date in the future.

I also ran into problems using the syntax of 7 values โ€‹โ€‹- I cannot specify the year in the cron schedule.

So I used this: 0 0 3? 2 Mon No. 5

Next time it will be done:

  1. Monday, February 29, 2044, 3:00 a.m.
  2. Monday 29 February 2072 at 3:00 a.m.
  3. Monday, February 29, 2112 3:00
  4. Monday, February 29, 2140 3:00
  5. Monday, February 29, 2168, 3:00

So, in essence, it is essentially disabled. :)

Oh. Damn it, this will only work for the Quartz scheduler syntax - the Spring CronTrigger syntax does not allow MON # 5 for the fifth Monday.

So, the next best thing is 0 0 3 29 2? which will be performed only at 3 a.m. on February 29 (leap years)

+6
Jan 10 '18 at 8:56
source share

Now, when I run this application on my own computer, I do not want these tasks to be performed. Is there a way to write a cron expression that will never work?

If you want to disable scheduling on your computer, you have several ways to do this.

First, you can move the Quartz configuration to the @Profile -based configuration and not include this profile locally. Quartz will not start at all if the profile is not active.

An alternative is to configure Quartz to start automatically. There is a SchedulerFactoryBean#setAutoStartup() which you can set in the BeanPostProcessor registered in the developer's profile. Although this thread is fairly old, Spring Boot offers an alternative by registering a bean of the SchedulerFactoryBeanCustomizer to do the same.

+2
Aug 08 '18 at 9:42
source share

If you use the expression in the expression @Scheduled(cron="") (technically not using quartz, but rather usual for spring in those days), you cannot use the solution "7 years in the future", but those options:

  • If you use spring 5. 1+ (springBoot 2. 1+) just use "${your.cron.prop:-} and don't set the property to disable - see @Scheduled
  • Disable bean / service with the @Scheduled method of @Scheduled , for example using @ConditionalOnProperty("my.scheduleproperty.active") and not setting the property (or setting it to false )
0
Jul 24 '19 at 9:39
source share



All Articles