Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use Quartz Scheduler to fire every other month on the 30th day but if month has no 30th day, fire on the last day?

Can I use Quartz Scheduler library to create schedule with following settings?:

  • Starting from Dec, 30, 2014
  • Execute each 30th day
  • Every 2nd month consequently
  • If month doesn't have 30th day, action should occur on the last day of month.

So, the resulting schedule will be:

  • Dec 30, 2014
  • Feb 28, 2015
  • Apr 30, 2015
  • ... and so on

From what I've learned:

  1. CronTrigger doesn't allow to do so (it could be set up only to be triggered on specific months and not on intervals),
  2. CalendarIntervalTrigger will skip months that don't have 30th day (trigger created by following code)

    try {
        SchedulerFactory schedulerFactory = new StdSchedulerFactory();
        Scheduler scheduler = schedulerFactory.getScheduler();
        scheduler.start();
    
        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class)
                .withIdentity("HelloJob_CalendarIntervaled", "calendarIntervaled")
                .build();
    
        Calendar decemberThirty = Calendar.getInstance();
        decemberThirty.set(Calendar.YEAR, 2014);
        decemberThirty.set(Calendar.MONTH, Calendar.DECEMBER);
        decemberThirty.set(Calendar.DAY_OF_MONTH, 30);
    
        CalendarIntervalTrigger calendarIntervalTrigger = newTrigger()
                .withIdentity("calendarIntervalTrigger", "calendarIntervaled")
                .withSchedule(CalendarIntervalScheduleBuilder.calendarIntervalSchedule()
                        .withIntervalInMonths(2))
                .startAt(decemberThirty.getTime())
                .forJob(jobDetail)
                .build();
    
        scheduler.scheduleJob(jobDetail, calendarIntervalTrigger);
    
        System.out.println(calendarIntervalTrigger.getNextFireTime());
    } catch (SchedulerException e) {
        e.printStackTrace();
    }
    

If no, are there any alternatives (it should work on JBoss eap 6.2.0)?

like image 471
n1k1ch Avatar asked Sep 24 '14 13:09

n1k1ch


People also ask

Is quartz scheduler capable of running jobs at 9 and 10 am?

However the scheduler was not capable of running jobs at 9 and 10 AM and it discovered that fact at 10:15 AM, i.e. 2 firings misfired. This is a more general situation compared to simple trigger running fixed number of times. CRON triggers are the most popular ones amongst Quartz users.

What happens when quartz can’t fire a trigger?

The situation when Quartz was incapable of firing given trigger is called misfire. Do you know what Quartz is doing when it happens? Turns out there are various strategies (called misfire instructions) Quartz can take and also there are some defaults if you haven’t thought about it.

What is quartz scheduler in Java?

Quartz is distributed as a small java library (.jar file) that contains all of the core Quartz functionality. The main interface (API) to this functionality is the Scheduler interface. It provides simple operations such as scheduling/unscheduling jobs, starting/stopping/pausing the scheduler.

Why doesn't the scheduler Fire my triggers?

The most common reason for this is not having called Scheduler.Start () , which tells the scheduler to start firing triggers. The second most common reason is that the trigger or trigger group has been paused. CronTrigger and SimpleTrigger each handle daylight savings time in their own way - each in the way that is intuitive to the trigger type.


1 Answers

You can achieve this in Quartz but you got to twist the normal behaviour by using a CalendarIntervalTrigger to trigger a Job that calculate when your 'real' Job should be scheduled.

You schedule a trigger that fire every 1st of your scheduling months :

[...]
JobDetail jobDetail = newJob(SchedulingCalculationJob.class)
        .withIdentity("SchedulingCalculation_CalendarIntervaled", "calendarIntervaled")
        .build();

CalendarIntervalTrigger calendarIntervalTrigger = newTrigger()
        .withIdentity("calendarIntervalCalculationTrigger", "calendarIntervaled")
        .withSchedule(calendarIntervalSchedule()
                .withIntervalInMonths(2))
        .startAt(decemberFirst.getTime())
        .forJob(jobDetail)
        .build();

scheduler.scheduleJob(jobDetail, calendarIntervalTrigger);

And in the SchedulingCalculationJob Job, you calculate your 'real' Job scheduling day :

public class SchedulingCalculationJob implements Job {

    public void execute(JobExecutionContext context)
            throws JobExecutionException {

        Calendar calendar = calculateJobFiringDate();

        // Create and schedule a dedicated trigger
        Trigger calculateFiring = calculateFiring = newTrigger()
               .withSchedule(SimpleSchedulerBuilder.simpleScheduler())
               .startAt(calendar.getTime())
               .forJob(yourRealJobDetail)
               .build();

        scheduler.scheduleJob(yourRealJobDetail, calculateFiring);
    }

    public static Calendar calculateJobFiringDate() {
        Calendar result = Calendar.getInstance();

        // Set up the scheduling day
        if (isThereThirtyDaysInCurrentMonth()) {
            // the 30th of the current month
            calendar.set(Calendar.DAY_OF_MONTH, 30);
        } else {
            // the last day of the current month
            calendar.add(Calendar.MONTH, 1);
            calendar.add(Calendar.DATE, -1);
        }

        // Set up time of day
        calendar.set(Calendar.HOUR, ...);
        calendar.set(Calendar.MINUTE, ...);
        calendar.set(Calendar.SECOND, ...);

        return result;
    }

    public static boolean isThereThirtyDaysInCurrentMonth() {
        Calendar thirtydaysInCurrentMonthCalendar = Calendar.getInstance();

        Integer currentMonth = thirtydaysInCurrentMonthCalendar.get(Calendar.MONTH);
        thirtydaysInCurrentMonthCalendar.add(Calendar.DATE, 29);

        return (currentMonth == thirtydaysInCurrentMonthCalendar.get(Calendar.MONTH);
    }
}

It's a bit sioux but I already use it and i works fine.

like image 64
Kraiss Avatar answered Oct 02 '22 14:10

Kraiss