{"id":7063,"date":"2016-05-16T08:47:12","date_gmt":"2016-05-16T06:47:12","guid":{"rendered":"http:\/\/blog.wenzlaff.de\/?p=7063"},"modified":"2024-04-26T18:11:37","modified_gmt":"2024-04-26T16:11:37","slug":"quartz","status":"publish","type":"post","link":"http:\/\/blog.wenzlaff.de\/?p=7063","title":{"rendered":"Wie kann ein Timer in Java mit Quartz erstellt werden?"},"content":{"rendered":"<p>Manchmal m\u00f6chte man Ereignisse mit Java zeitgesteuert oder wiederholt ausf\u00fchren. Das geht auch mit Java Mitteln. Die bekannte <strong>java.util.Timer<\/strong> Klasse kann schon was. Der Open Source Framework Quartz hat ua. aber diese Vorteile:<\/p>\n<ul>\n<li>persistence mechanismen<\/li>\n<li>flexible Zeitplanung<\/li>\n<li>Thread-Pool<\/li>\n<li>Managment Schemen<\/li>\n<li>flexibel<\/li>\n<li>fehlertolerant, auch nach Systemstart<\/li>\n<\/ul>\n<p><a href=\"https:\/\/www.quartz-scheduler.org\/\">Quartz<\/a> ist ein kleiner Framework der nur quartz-x.y.z.jar im Classpath ben\u00f6gigt (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. <\/p>\n<p>Sie spielen so zusammen:<\/p>\n<p><a href=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2016\/05\/quartz-uebersicht.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2016\/05\/quartz-uebersicht.png\" alt=\"quartz-uebersicht\" width=\"640\" height=\"453\" class=\"aligncenter size-full wp-image-7129\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2016\/05\/quartz-uebersicht.png 640w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2016\/05\/quartz-uebersicht-300x212.png 300w\" sizes=\"auto, (max-width: 640px) 100vw, 640px\" \/><\/a><\/p>\n<p>Wie kann ein Timer in Java mit <a href=\"https:\/\/www.quartz-scheduler.org\/\">Quartz<\/a> erstellt werden?<!--more--><\/p>\n<p>In diesem Beispiel fragen wir alle 5 Minuten eine REST Service ab, der die Anzahl aller Flugzeuge in Hannover lierfert.<\/p>\n<p>Zuerst diese Abh\u00e4ngigkeiten in der <strong>pom.xml<\/strong> eintragen:<\/p>\n<p><script src=\"https:\/\/gist.github.com\/IT-Berater\/474607c413ff3cfdeacc5a908fec1219.js\"><\/script><\/p>\n<p>Wir brauchen nur drei Klassen.<\/p>\n<p>Einen <strong>AbfrageListener.java<\/strong> der den JobListener implementiert.<\/p>\n<pre class=\"lang:java decode:true \" >\r\npackage de.wenzlaff.timer;\r\n\r\nimport org.quartz.JobExecutionContext;\r\nimport org.quartz.JobExecutionException;\r\nimport org.quartz.JobListener;\r\nimport org.slf4j.Logger;\r\nimport org.slf4j.LoggerFactory;\r\n\r\n\/**\r\n * Der Listener f\u00fcr die Abfrage.\r\n *\r\n * @author Thomas Wenzlaff\r\n * @version 0.1\r\n *\/\r\npublic class AbfrageListener implements JobListener {\r\n\r\n\tprivate static final Logger LOG = LoggerFactory.getLogger(AbfrageListener.class);\r\n\r\n\tpublic String getName() {\r\n\t\treturn \"Abfrage Listener\";\r\n\t}\r\n\r\n\tpublic void jobExecutionVetoed(JobExecutionContext context) {\r\n\t\t\/\/ Quartz will invoke this method when the job execution was banned from the trigger.\r\n\t\tLOG.debug(\"jobExecutionVetoed\");\r\n\t}\r\n\r\n\tpublic void jobToBeExecuted(JobExecutionContext context) {\r\n\t\t\/\/ Quartz will invoke this method when the job is going to be executed.\r\n\t\tfinal String jobName = context.getJobDetail().getKey().toString();\r\n\t\tLOG.debug(\"jobToBeExecuted: {} Job startet ...\", jobName);\r\n\t}\r\n\r\n\tpublic void jobWasExecuted(JobExecutionContext context, JobExecutionException jobException) {\r\n\t\t\/\/ Quartz will invoke this method when the job was executed.\r\n\t\tLOG.debug(\"jobWasExecuted\");\r\n\r\n\t\tfinal String jobName = context.getJobDetail().getKey().toString();\r\n\r\n\t\tLOG.debug(\"Job : {} ist beendet\", jobName);\r\n\r\n\t\tif (jobException != null &amp;&amp; jobException.getMessage().equals(\"\")) { \/\/ bei Fehler\r\n\t\t\tLOG.error(\"Exception thrown by: {}\", jobName, jobException);\r\n\t\t}\r\n\t}\r\n\r\n}\r\n<\/pre>\n<p>Eine Job Klasse <strong>AbfrageJob.java<\/strong> die die eigentliche Arbeit macht und den Job implementiert:<\/p>\n<pre class=\"lang:java decode:true \" >\r\npackage de.wenzlaff.timer;\r\n\r\nimport java.io.IOException;\r\nimport java.io.StringReader;\r\n\r\nimport javax.ws.rs.client.ClientBuilder;\r\n\r\nimport org.jdom2.JDOMException;\r\nimport org.jdom2.input.SAXBuilder;\r\nimport org.quartz.Job;\r\nimport org.quartz.JobExecutionContext;\r\nimport org.quartz.JobExecutionException;\r\nimport org.slf4j.Logger;\r\nimport org.slf4j.LoggerFactory;\r\n\r\n\/**\r\n * Der Abfrage Job.\r\n *\r\n * @author Thomas Wenzlaff\r\n * @version 0.1\r\n *\/\r\npublic class AbfrageJob implements Job {\r\n\r\n\tprivate static final Logger LOG = LoggerFactory.getLogger(AbfrageJob.class);\r\n\r\n\t\/\/ URL des Feeds aller Flugzeuge in Hannover von Thomas Wenzlaff. \/\/\r\n\tprivate final static String FLUGZEUG_URL = \"https:\/\/api.thingspeak.com\/channels\/44177\/feeds\/last.xml\";\r\n\r\n\tpublic void execute(JobExecutionContext context) throws JobExecutionException {\r\n\t\tLOG.debug(\"Abfrage context: {}\", context);\r\n\r\n\t\tString result = ClientBuilder.newClient().target(FLUGZEUG_URL).request().get(String.class);\r\n\t\t\/\/ result get sample:\r\n\t\t\/\/ &lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\r\n\t\t\/\/ &lt;feed&gt;\r\n\t\t\/\/ &lt;created-at type=\"dateTime\"&gt;2016-05-13T12:20:01Z&lt;\/created-at&gt;\r\n\t\t\/\/ &lt;entry-id type=\"integer\"&gt;79166&lt;\/entry-id&gt;\r\n\t\t\/\/ &lt;field1&gt;18&lt;\/field1&gt;\r\n\t\t\/\/ &lt;id type=\"integer\" nil=\"true\"\/&gt;\r\n\t\t\/\/ &lt;\/feed&gt;\r\n\r\n\t\tString field1;\r\n\t\ttry {\r\n\t\t\tfield1 = new SAXBuilder().build(new StringReader(result)).getDocument().getRootElement().getChild(\"field1\").getText();\r\n\t\t} catch (JDOMException e) {\r\n\t\t\tthrow new JobExecutionException(e);\r\n\t\t} catch (IOException e) {\r\n\t\t\tthrow new JobExecutionException(e);\r\n\t\t}\r\n\r\n\t\tLOG.info(\"Aktuelle Anzahl Flugzeuge in Langenhagen: {} \", field1);\r\n\r\n\t}\r\n\r\n}\r\n<\/pre>\n<p>Und nun noch eine Klasse <strong>Abfrage.java<\/strong> f\u00fcr die Verbindungen und den Start des Timers:<\/p>\n<pre class=\"lang:java decode:true \" >package de.wenzlaff.rest.client;\r\n\r\nimport org.quartz.CronScheduleBuilder;\r\nimport org.quartz.JobBuilder;\r\nimport org.quartz.JobDetail;\r\nimport org.quartz.JobKey;\r\nimport org.quartz.Scheduler;\r\nimport org.quartz.Trigger;\r\nimport org.quartz.TriggerBuilder;\r\nimport org.quartz.impl.StdSchedulerFactory;\r\nimport org.quartz.impl.matchers.KeyMatcher;\r\nimport org.slf4j.Logger;\r\nimport org.slf4j.LoggerFactory;\r\n\r\nimport de.wenzlaff.timer.AbfrageJob;\r\nimport de.wenzlaff.timer.AbfrageListener;\r\n\r\n\/**\r\n * Beispiel REST Abfrage der Flugzeugdaten aus Hannover.\r\n * \r\n * @author Thomas Wenzlaff\r\n * @version 0.1\r\n *\/\r\npublic class Abfrage {\r\n\r\n\tprivate static final Logger LOG = LoggerFactory.getLogger(Abfrage.class);\r\n\r\n\t\/**\r\n\t * Start Methode.\r\n\t * \r\n\t * @param args\r\n\t *            keine.\r\n\t * @throws Exception\r\n\t *             bei Fehlern\r\n\t *\/\r\n\tpublic static void main(String[] args) throws Exception {\r\n\r\n\t\tLOG.info(\"Starte Flugzeug Abfrage\");\r\n\r\n\t\t\/\/ nun ein Beispiel zum periodischen Abfragen mit Quarz\r\n\t\tfinal JobKey abfrageKey = new JobKey(\"AbfrageNamen\", \"AbfrageGruppe\");\r\n\t\tfinal JobDetail job = JobBuilder.newJob(AbfrageJob.class).withIdentity(abfrageKey).build();\r\n\r\n\t\t\/\/ alle 5 Sekunden\r\n\t\tfinal Trigger trigger = TriggerBuilder.newTrigger().withIdentity(\"AbfrageNamen\", \"AbfrageGruppe\").withSchedule(CronScheduleBuilder.cronSchedule(\"0\/5 * * * * ?\")).build();\r\n\r\n\t\tfinal Scheduler scheduler = new StdSchedulerFactory().getScheduler();\r\n\r\n\t\t\/\/ Listener mit den abfrageKey verbinden\r\n\t\tscheduler.getListenerManager().addJobListener(new AbfrageListener(), KeyMatcher.keyEquals(abfrageKey));\r\n\r\n\t\tscheduler.start();\r\n\t\tscheduler.scheduleJob(job, trigger);\r\n\t}\r\n\r\n}<\/pre>\n<p>Hier die UML \u00dcbersicht.<\/p>\n<p><a href=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2016\/05\/Bildschirmfoto-2016-05-16-um-08.27.36.png\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2016\/05\/Bildschirmfoto-2016-05-16-um-08.27.36.png\" alt=\"Quartz Klassen\" width=\"992\" height=\"400\" class=\"aligncenter size-full wp-image-7067\" srcset=\"http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2016\/05\/Bildschirmfoto-2016-05-16-um-08.27.36.png 992w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2016\/05\/Bildschirmfoto-2016-05-16-um-08.27.36-300x121.png 300w, http:\/\/blog.wenzlaff.de\/wp-content\/uploads\/2016\/05\/Bildschirmfoto-2016-05-16-um-08.27.36-768x310.png 768w\" sizes=\"auto, (max-width: 767px) 89vw, (max-width: 1000px) 54vw, (max-width: 1071px) 543px, 580px\" \/><\/a><\/p>\n<p>Hier die Ausgabe, wenn das Programm gestartet wird:<\/p>\n<pre class=\"lang:default decode:true \" >\r\nINFO  Abfrage - Starte Flugzeug Abfrage\r\nINFO  StdSchedulerFactory - Using default implementation for ThreadExecutor\r\nINFO  SimpleThreadPool - Job execution threads will use class loader of thread: main\r\nINFO  SchedulerSignalerImpl - Initialized Scheduler Signaller of type: class org.quartz.core.SchedulerSignalerImpl\r\nINFO  QuartzScheduler - Quartz Scheduler v.2.2.3 created.\r\nINFO  RAMJobStore - RAMJobStore initialized.\r\nINFO  QuartzScheduler - Scheduler meta-data: Quartz Scheduler (v2.2.3) 'DefaultQuartzScheduler' with instanceId 'NON_CLUSTERED'\r\n  Scheduler class: 'org.quartz.core.QuartzScheduler' - running locally.\r\n  NOT STARTED.\r\n  Currently in standby mode.\r\n  Number of jobs executed: 0\r\n  Using thread pool 'org.quartz.simpl.SimpleThreadPool' - with 10 threads.\r\n  Using job-store 'org.quartz.simpl.RAMJobStore' - which does not support persistence. and is not clustered.\r\n\r\nINFO  StdSchedulerFactory - Quartz scheduler 'DefaultQuartzScheduler' initialized from default resource file in Quartz package: 'quartz.properties'\r\nINFO  StdSchedulerFactory - Quartz scheduler version: 2.2.3\r\nINFO  QuartzScheduler - Scheduler DefaultQuartzScheduler_$_NON_CLUSTERED started.\r\nDEBUG QuartzSchedulerThread - batch acquisition of 0 triggers\r\nDEBUG QuartzSchedulerThread - batch acquisition of 1 triggers\r\nDEBUG PropertySettingJobFactory - Producing instance of Job 'AbfrageGruppe.AbfrageNamen', class=de.wenzlaff.timer.AbfrageJob\r\nDEBUG QuartzSchedulerThread - batch acquisition of 1 triggers\r\nDEBUG JobRunShell - Calling execute on job AbfrageGruppe.AbfrageNamen\r\nINFO  AbfrageJob - Aktuelle Anzahl Flugzeuge in Langenhagen: 13 \r\nDEBUG PropertySettingJobFactory - Producing instance of Job 'AbfrageGruppe.AbfrageNamen', class=de.wenzlaff.timer.AbfrageJob\r\nDEBUG JobRunShell - Calling execute on job AbfrageGruppe.AbfrageNamen\r\nDEBUG QuartzSchedulerThread - batch acquisition of 1 triggers\r\nINFO  AbfrageJob - Aktuelle Anzahl Flugzeuge in Langenhagen: 13 \r\nDEBUG PropertySettingJobFactory - Producing instance of Job 'AbfrageGruppe.AbfrageNamen', class=de.wenzlaff.timer.AbfrageJob\r\nDEBUG JobRunShell - Calling execute on job AbfrageGruppe.AbfrageNamen\r\nDEBUG QuartzSchedulerThread - batch acquisition of 1 triggers\r\nINFO  AbfrageJob - Aktuelle Anzahl Flugzeuge in Langenhagen: 13 \r\n<\/pre>\n<p>Es wird alle 5 Minuten die Anzahl der Flugzeuge ausgegeben. Hier in HAJ werden im Moment nur 13 empfangen.<\/p>\n<p>Das ganze Projekt kann von <a href=\"https:\/\/github.com\/IT-Berater\/TWRestClient\">Github<\/a> geladen werden.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Manchmal m\u00f6chte man Ereignisse mit Java zeitgesteuert oder wiederholt ausf\u00fchren. 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 &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/blog.wenzlaff.de\/?p=7063\" class=\"more-link\"><span class=\"screen-reader-text\">\u201eWie kann ein Timer in Java mit Quartz erstellt werden?\u201c <\/span>weiterlesen<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[220,5],"tags":[112,2178,2510,187],"class_list":["post-7063","post","type-post","status-publish","format-standard","hentry","category-anleitung","category-java","tag-beispiel","tag-java","tag-quartz","tag-timer"],"_links":{"self":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts\/7063","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7063"}],"version-history":[{"count":0,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=\/wp\/v2\/posts\/7063\/revisions"}],"wp:attachment":[{"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7063"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7063"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/blog.wenzlaff.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7063"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}