Cronwize
Guide · Quartz

Monitor a Quartz job

Paste the trigger's cron expression as written, including ?, L, W and #, then ping from the job.

1. Create the monitor from the trigger

Quartz cron has six or seven fields, seconds first and an optional year last. Paste the expression as written. ?, L, W and # all work, and days of the week count from Sunday = 1, as they do in Quartz. Pick the zone the trigger uses.

TriggerBuilder.newTrigger()
    .withSchedule(CronScheduleBuilder.cronSchedule("0 0 12 L * ?")
        .inTimeZone(TimeZone.getTimeZone("Europe/Belgrade")))
    .build();
Faster than once a minute is rejectedCronwize checks once a minute, so a schedule that fires more often is refused with an explanation.

2. Ping from the job

public class MonthEndReport implements Job {
  private static final String PING = "https://ping.cronwize.com/YOUR-KEY";
  private static final HttpClient HTTP = HttpClient.newHttpClient();

  @Override
  public void execute(JobExecutionContext context) throws JobExecutionException {
    ping("/start", "");
    try {
      buildReport();
      ping("", "");
    } catch (RuntimeException e) {
      ping("/fail", String.valueOf(e.getMessage()));
      throw new JobExecutionException(e);
    }
  }

  // Fire and forget: a slow or failed ping never blocks the job.
  private void ping(String signal, String body) {
    HttpRequest req = HttpRequest.newBuilder(URI.create(PING + signal))
        .timeout(Duration.ofSeconds(10))
        .POST(HttpRequest.BodyPublishers.ofString(body))
        .build();
    HTTP.sendAsync(req, HttpResponse.BodyHandlers.discarding());
  }
}

The body of a /fail ping, up to 10 KB, is kept in the ping log and the first 500 characters go into the alert. Do not send secrets.

3. Check the first ping

Trigger the job once. The monitor turns from new to up.

When a schedule ends

A Quartz expression whose year field ends has no next run. Its monitor never goes down by deadline and is shown as finished.