Wie kann ein Timer in Java mit Quartz erstellt werden?

Manchmal möchte man Ereignisse mit Java zeitgesteuert oder wiederholt ausführen. Das geht auch mit Java Mitteln. Die bekannte java.util.Timer Klasse kann schon was. Der Open Source Framework Quartz hat ua. aber diese Vorteile:

  • persistence mechanismen
  • flexible Zeitplanung
  • Thread-Pool
  • Managment Schemen
  • flexibel
  • fehlertolerant, auch nach Systemstart

Quartz ist ein kleiner Framework der nur quartz-x.y.z.jar im Classpath benögigt (inkl. log sl4j-api.jar, und c3p0.jar). Er kann Standalone oder im Server als J2EE Anwendung verwendet werden. Die wichtigsten drei Klassen sind Task/Job, Trigger und der Listener. Sie spielen so zusammen:
quartz-übersicht

Wie kann ein Timer in Java mit Quartz erstellt werden?

In diesem Beispiel fragen wir alle 5 Minuten eine REST Service ab, der die Anzahl aller Flugzeuge in Hannover lierfert.

Zuerst diese Abhängigkeiten in der pom.xml eintragen:

Wir brauchen nur drei Klassen.

Einen AbfrageListener.java der den JobListener implementiert.

package de.wenzlaff.timer;

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Der Listener für die Abfrage.
 *
 * @author Thomas Wenzlaff
 * @version 0.1
 */
public class AbfrageListener implements JobListener {

	private static final Logger LOG = LoggerFactory.getLogger(AbfrageListener.class);

	public String getName() {
		return "Abfrage Listener";
	}

	public void jobExecutionVetoed(JobExecutionContext context) {
		// Quartz will invoke this method when the job execution was banned from the trigger.
		LOG.debug("jobExecutionVetoed");
	}

	public void jobToBeExecuted(JobExecutionContext context) {
		// Quartz will invoke this method when the job is going to be executed.
		final String jobName = context.getJobDetail().getKey().toString();
		LOG.debug("jobToBeExecuted: {} Job startet ...", jobName);
	}

	public void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {
		// Quartz will invoke this method when the job was executed.
		LOG.debug("jobWasExecuted");

		final String jobName = context.getJobDetail().getKey().toString();

		LOG.debug("Job : {} ist beendet", jobName);

		if (jobException != null & jobException.getMessage().equals("")) { // bei Fehler
			LOG.error("Exception thrown by: {}", jobName, jobException);
		}
	}

}

Eine Job Klasse AbfrageJob.java die die eigentliche Arbeit macht und den Job implementiert:

package de.wenzlaff.timer;

import java.io.IOException;
import java.io.StringReader;

import javax.ws.rs.client.ClientBuilder;

import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Der Abfrage Job.
 *
 * @author Thomas Wenzlaff
 * @version 0.1
 */
public class AbfrageJob implements Job {

	private static final Logger LOG = LoggerFactory.getLogger(AbfrageJob.class);

	// URL des Feeds aller Flugzeuge in Hannover von Thomas Wenzlaff. //
	private final static String FLUGZEUG_URL = "https://api.thingspeak.com/channels/44177/feeds/last.xml";

	public void execute(JobExecutionContext context) throws JobExecutionException {
		LOG.debug("Abfrage context: {}", context);

		String result = ClientBuilder.newClient().target(FLUGZEUG_URL).request().get(String.class);
		// result get sample:
		// <?xml version="1.0" encoding="UTF-8"?>
		// <feed>
		// <created-at type="dateTime">2016-05-13T12:20:01Z</created-at>
		// <entry-id type="integer">79166</entry-id>
		// <field1>18</field1>
		// <id type="integer" nil="true"/>
		// </feed>

		String field1;
		try {
			field1 = new SAXBuilder().build(new StringReader(result)).getDocument().getRootElement().getChild("field1").getText();
		} catch (JDOMException e) {
			throw new JobExecutionException(e);
		} catch (IOException e) {
			throw new JobExecutionException(e);
		}

		LOG.info("Aktuelle Anzahl Flugzeuge in Langenhagen: {} ", field1);

	}

}

Und nun noch eine Klasse Abfrage.java für die Verbindungen und den Start des Timers:

package de.wenzlaff.rest.client;

import org.quartz.CronScheduleBuilder;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.KeyMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.wenzlaff.timer.AbfrageJob;
import de.wenzlaff.timer.AbfrageListener;

/**
 * Beispiel REST Abfrage der Flugzeugdaten aus Hannover.
 * 
 * @author Thomas Wenzlaff
 * @version 0.1
 */
public class Abfrage {

	private static final Logger LOG = LoggerFactory.getLogger(Abfrage.class);

	/**
	 * Start Methode.
	 * 
	 * @param args
	 *            keine.
	 * @throws Exception
	 *             bei Fehlern
	 */
	public static void main(String[] args) throws Exception {

		LOG.info("Starte Flugzeug Abfrage");

		// nun ein Beispiel zum periodischen Abfragen mit Quarz
		final JobKey abfrageKey = new JobKey("AbfrageNamen", "AbfrageGruppe");
		final JobDetail job = JobBuilder.newJob(AbfrageJob.class).withIdentity(abfrageKey).build();

		// alle 5 Sekunden
		final Trigger trigger = TriggerBuilder.newTrigger().withIdentity("AbfrageNamen", "AbfrageGruppe").withSchedule(CronScheduleBuilder.cronSchedule("0/5 * * * * ?")).build();

		final Scheduler scheduler = new StdSchedulerFactory().getScheduler();

		// Listener mit den abfrageKey verbinden
		scheduler.getListenerManager().addJobListener(new AbfrageListener(), KeyMatcher.keyEquals(abfrageKey));

		scheduler.start();
		scheduler.scheduleJob(job, trigger);
	}

}

Hier die UML Übersicht.

Quartz Klassen

Hier die Ausgabe, wenn das Programm gestartet wird:

INFO  Abfrage - Starte Flugzeug Abfrage
INFO  StdSchedulerFactory - Using default implementation for ThreadExecutor
INFO  SimpleThreadPool - Job execution threads will use class loader of thread: main
INFO  SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl
INFO  QuartzScheduler - Quartz Scheduler v.2.2.3 created.
INFO  RAMJobStore - RAMJobStore initialized.
INFO  QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.2.3) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'
  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.
  NOT STARTED.
  Currently in standby mode.
  Number of jobs executed: 0
  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.
  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.

INFO  StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'
INFO  StdSchedulerFactory - Quartz scheduler version: 2.2.3
INFO  QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.
DEBUG QuartzSchedulerThread - batch acquisition of 0 triggers
DEBUG QuartzSchedulerThread - batch acquisition of 1 triggers
DEBUG PropertySettingJobFactory - Producing instance of Job 'AbfrageGruppe.AbfrageNamen', class=de.wenzlaff.timer.AbfrageJob
DEBUG QuartzSchedulerThread - batch acquisition of 1 triggers
DEBUG JobRunShell - Calling execute on job AbfrageGruppe.AbfrageNamen
INFO  AbfrageJob - Aktuelle Anzahl Flugzeuge in Langenhagen: 13 
DEBUG PropertySettingJobFactory - Producing instance of Job 'AbfrageGruppe.AbfrageNamen', class=de.wenzlaff.timer.AbfrageJob
DEBUG JobRunShell - Calling execute on job AbfrageGruppe.AbfrageNamen
DEBUG QuartzSchedulerThread - batch acquisition of 1 triggers
INFO  AbfrageJob - Aktuelle Anzahl Flugzeuge in Langenhagen: 13 
DEBUG PropertySettingJobFactory - Producing instance of Job 'AbfrageGruppe.AbfrageNamen', class=de.wenzlaff.timer.AbfrageJob
DEBUG JobRunShell - Calling execute on job AbfrageGruppe.AbfrageNamen
DEBUG QuartzSchedulerThread - batch acquisition of 1 triggers
INFO  AbfrageJob - Aktuelle Anzahl Flugzeuge in Langenhagen: 13

Es wird alle 5 Minuten die Anzahl der Flugzeuge ausgegeben. Hier in HAJ werden im Moment nur 13 empfangen.

Das ganze Projekt kann von Github geladen werden.

Ähnliche Artikel:

  1. Wie kann mit der neuen Java 1.8 Time Api einmal am Tag um Mitternacht ein Ereignis erzeugt werden?
  2. Wie kann mit dem Mac OS X unter Eclipse ein JavaFX Programm erstellt werden, da Swing in Java 8 deprecated ist?
  3. Java Rätsel des Monats

wallpaper-1019588
[Comic] Batman: City of Madness
wallpaper-1019588
Hyakushō Kizoku: Anime erhält eine dritte Staffel
wallpaper-1019588
Arcanadea: Figuren-Franchise erhält einen TV-Anime
wallpaper-1019588
Gintama: Neuer Teaser zum Spin-Off-Anime veröffentlicht