Skip to content

Scheduler

Background jobs run inside the same JVM as your web app, no separate Quartz XML or system cron daemon required. Annotate any public method without parameters with @Run and a schedule expression (the application refuses to start otherwise), and Classgraph discovers those methods at startup as long as scheduler.enable is true, which it is by default.

Use fixed-delay expressions such as Every 3m or Every 1d for recurring work like cleanup tasks, cache warming, or report generation. Jobs share Guice injection with the rest of the application, so you can inject services and Datastore exactly like you would in a controller.

Fixed delay

import io.mangoo.annotations.Run;

public class InfoJob {
    @Run(at = "Every 3m")
    public void execute() {
        // task
    }
}

Units after Every:

  • s seconds (Every 5s)
  • m minutes (Every 15m)
  • h hours (Every 4h)
  • d days (Every 1d)

The Every prefix is case-insensitive, so every and Every both work.

The interval is the delay between the end of one run and the start of the next. Runs of the same job do not overlap, and the first run waits for the full interval. It does not fire at startup. Cron jobs follow the same rule: the next slot is scheduled after the current run finishes. Cron uses the JVM default zone. application.timezone is applied when the Guice module is constructed, so read the zone after that, not from a static initializer that ran earlier.

Cron

Use a 5-field UNIX cron expression: minute, hour, day-of-month, month, day-of-week.

public class NightlyJob {
    @Run(at = "0 2 * * *")
    public void execute() {
        // 02:00 every day
    }
}

This is not Quartz cron; notably, there is no seconds field.

Each run is submitted to a new platform thread. The timer that waits out the delay is a single thread. There is no bounded pool. Disable scheduling entirely with:

scheduler:
  enable: false