简体   繁体   中英

Java Quartz - cron expression

I have a report creator program made in Java that needs to run every Monday and I used Quartz for my scheduling part. The trick is, the amount of reports needed to be generated varies; depending if the Monday is the first of the month, or the succeeding Mondays.

To achieve this, what i did is create a trigger for each Monday of the month with the first Monday pointing to a specific job class while the rest of the Mondays(triggers) point to another job class.

        .withIdentity("trigger1", "group1")
        .withSchedule(cronSchedule("0 1 0 ? 1/1 MON#1 *"))
        .build();

        .withIdentity("trigger2", "group1")
        .withSchedule(cronSchedule("0 1 0 ? 1/1 MON#2 *"))
        .build();

and so on until i reach

        .withIdentity("trigger5", "group1")
        .withSchedule(cronSchedule("0 1 0 ? 1/1 MON#5 *"))
        .build();

It reached MON#5 because there could be 5 Mondays in a month; like this October. This is fine, it works (I think), but my question is this. Is there a way to combine my cron schedule so that I will only need one trigger for the succeeding mondays? Something like;

        .withSchedule(cronSchedule("0 1 0 ? 1/1 MON#2,MON#3,MON#4,MON#5 *"))

If there is, please kindly enlighten me. If I'm just missing something, something in my programming, or if there exists an unknown page in the labyrinth which is the web that leads me to the truth, then kindly point me to the right direction.

Your kind words are greatly appreciated. Thanks

ps: I included a cron tag even though it says it's for UNIX computers. I believe there is little or no difference between Quartz cron and Unix cron. If there is, then please do tell.

The usual unix workaround to having cron run something on the first X-day of the month is to have cron trigger a script on the form:

#! /usr/bin/bash
day=$( date +%d )
if ( ( day <= 7 ) ) ; then
    exec firstdayofthemonthshellscript.sh
fi

with a crontab entry on the form

0 0 * * 1 wrapperscript.sh

(for eg. monday).

To summarize, I don't think your goal is easily achievable using Quartz cron either, but perhaps you can work with the trick above in your implementation.

Cheers,

It looks like there is no formal solution for your problem.

Here is a quote from Quartz 2.0 documentation :

The '#' character is allowed for the day-of-week field. This character is used to specify "the nth" XXX day of the month. For example, the value of "6#3" in the day-of-week field means the third Friday of the month (day 6 = Friday and "#3" = the 3rd one in the month). Other examples: "2#1" = the first Monday of the month and "4#5" = the fifth Wednesday of the month. Note that if you specify "#5" and there is not 5 of the given day-of-week in the month, then no firing will occur that month.

There is also an open bug on this.

Personally, I would put this kind of logic in Java instead of within the Quartz configuration. Make Quartz always execute a Java job dispatcher which then determines which reports to run depending on the date.

As stated by Tomer, Quartz does not support this use case. But if Quartz is not a constraint, a valid expression can be created at cron-utils . Below an example:

String multicron = "0 1 0 ? 1/1 MON#2|MON#3|MON#4|MON#5 *";
CronDefinition definition = CronDefinitionBuilder.instanceDefinitionFor(CronType.QUARTZ);
CronParser parser = new CronParser(definition);
Cron cron = parser.parse(multicron);

cron-utils currently does not provide means to execute jobs, but will provide you next/previous execution times for any given date.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM