Quartz : 절대 실행되지 않는 Cron 표현식
나는 여기 에 중복이 있다는 것을 알고 있는데 , 아마도 정확히 나의 경우 일 것이다. 비록 더 나은 설명이 필요하지만 여기에서 제공하려고 노력할 것이다.
Spring 애플리케이션 컨텍스트를 사용하여 Java 웹 애플리케이션으로 작업합니다. 이 맥락에서 저는 Quartz를 사용하여 예정된 작업을 정의했습니다. 이러한 작업은 .properties 파일에 정의 된 cron에 의해 트리거됩니다.
Spring 컨텍스트는 war 내에 임베드되고 .properties 파일은 애플리케이션 서버 (이 특정 경우에는 Tomcat)에 있습니다.
이것은 괜찮으며 환경 (개발, 통합, 생산 등)에 따라 다른 크론을 정의 할 수 있습니다.
이제이 응용 프로그램을 내 컴퓨터에서 로컬로 실행할 때 이러한 작업이 실행되는 것을 원하지 않습니다. 트리거하지 않는 cron 표현식을 작성하는 방법이 있습니까?
TL; DR
Quartz 1에서는이 cron : 59 59 23 31 12 ? 2099(마지막 유효 날짜)를 사용할 수 있습니다 .
Quartz 2에서는 다음 크론을 사용할 수 있습니다.0 0 0 1 1 ? 2200
먼 미래의 표현 사용
.NET을 사용하여 몇 가지 빠른 테스트를 수행했습니다 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()));
}
그렇게 String exp = "# 0 0 0 1 1 ?";하면 isValid테스트가 반환 false됩니다.
위에 제공된 샘플을 사용하면 출력은 다음과 같습니다.
true
null
의미:
- 표현식이 유효합니다.
- 이 표현과 일치하는 예정된 날짜가 없습니다.
하지만 스케줄러가 cron 트리거를 수락하려면 후자 가 미래의 날짜와 일치 해야합니다 .
나는 몇 년을 시도하고 일년이 2300을 넘으면 Quartz가 더 이상 귀찮게 보이지 않는다는 것을 알아 냈습니다 ( Quartz 2의 문서에서 올해 최대 값에 대한 언급을 찾지 못했지만 ). 이 작업을 수행하는 더 깨끗한 방법이있을 수 있지만 지금은 내 요구를 충족시킬 것입니다.
그래서 결국 내가 제안하는 cron은 0 0 0 1 1 ? 2200.
Quartz 1 변형
Quartz 1에서 2099 년은 마지막 유효 연도 입니다. 따라서 Maciej Matys의 제안 을 사용하도록 cron 표현식을 조정할 수 있습니다 .59 59 23 31 12 ? 2099
대안 : 과거 날짜 사용
Arnaud Denoyelle 은 더 우아한 것을 제안했는데, 위의 테스트에서 올바른 표현으로 검증했습니다. 먼 미래의 날짜를 선택하는 대신 먼 과거의 날짜를 선택하십시오.
0 0 0 1 1 ? 1970 (Quartz 문서에 따른 첫 번째 유효한 표현식).
이 솔루션은 작동하지 않습니다.
hippofluff 는 Quartz가 과거에 표현식을 감지 할 것이므로 다시는 실행되지 않으므로 예외가 발생 한다고 강조했습니다.
org.quartz.SchedulerException: Based on configured schedule, the given trigger will never fire.
배운 교훈 : 테스트는 그대로 완벽하지 않습니다.
이것은 내 테스트의 약점을 강조합니다. a를 테스트 하려면 1 이 있어야한다는CronExpression 것을 기억 하십시오nextValidTime . 그렇지 않으면 전달할 스케줄러가 위에서 언급 한 예외와 함께이를 거부합니다.
다음과 같이 테스트 코드를 수정하는 것이 좋습니다.
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."));
이제 생각할 필요없이 출력을 읽으십시오.
1 This is the part I forgot when testing Arnaud's solution making me the fool and proving my test wasn't me-proof.
Technically, valid values for the optional Quartz year field are 1970-2099, so 2300 isn't an expected value. I'm assuming you really need to do this and your version of Quartz attempts to enforce valid cron syntax (day 1-31, month 1-12, and so on).
I'm currently using the following code in Resque-scheduler for Rails, which accepts schedule info in validated crontab format, to create a manual-run-only test job:
cron: "0 5 31 2 *"
The job will wait patiently for early morning February 31st before running. For an equivalent in Quartz crontrigger, try this line or some variant thereof:
0 0 5 31 2 ?
Give a try to this one: 59 59 23 31 12 ? 2099
I found this whilst trying to solve a similar problem - disabling a cron expression - but ran into the same problems of requiring a valid future schedule date.
I also hit problems using the 7 value syntax - cannot specify a year in the cron schedule.
So I used this: 0 0 3 ? 2 MON#5
The next times this will execute are:
- Monday, February 29, 2044 3:00 AM
- Monday, February 29, 2072 3:00 AM
- Monday, February 29, 2112 3:00 AM
- Monday, February 29, 2140 3:00 AM
- Monday, February 29, 2168 3:00 AM
So, essentially, to all intents and purposes, it's disabled. :)
Ah. Curses, this will only work for Quartz scheduler syntax - Spring CronTrigger syntax doesn't allow MON#5 for the fifth monday
So the next best thing is 0 0 3 29 2 ? which will only execute at 3am on the 29th Feb (leap years)
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?
If you want to disable scheduling on your computer, you have several ways to make that happen.
First you could move the configuration of Quartz to a @Profile-based configuration and not enable this profile locally. Quartz wouldn't start at all if the profile is not active.
An alternative is to configure Quartz to not start automatically. There is a SchedulerFactoryBean#setAutoStartup() that you can set in BeanPostProcessor registered in a dev profile. While this thread is quite old, Spring Boot offers an alternative by registering a SchedulerFactoryBeanCustomizer bean to do the same thing.
If you're using the expression in a @Scheduled(cron="") expression (technically not using quartz, but rather common with spring those days) you can not use the 7-field year-in-the-future solution but those options:
- If you're using spring 5.1+ (springBoot 2.1+) simply use
"${your.cron.prop:-}and don't set the property to disable - see @Scheduled - Disable the bean/service with the
@Scheduledmethod altogether, for example by using a@ConditionalOnProperty("my.scheduleproperty.active")annotation and not setting the property (or setting it tofalse)
참고URL : https://stackoverflow.com/questions/13835221/quartz-cron-expression-that-will-never-execute
'IT박스' 카테고리의 다른 글
| Haml에서 어떻게 동적 ID를 만드나요? (0) | 2020.10.24 |
|---|---|
| 선택기 객체가 유효하지 않은 경우 jQuery가 폭탄을 터뜨리지 않는 이유는 무엇입니까? (0) | 2020.10.24 |
| CSS에서 회전하는 지구본 (0) | 2020.10.24 |
| TestFlight 용 iTunes Connect에 빌드를 어떻게 업로드합니까? (0) | 2020.10.24 |
| Mercurial "서버" (0) | 2020.10.24 |