Quartz Scheduler: una libreria Open Source per schedulare processi Java

Quartz Scheduler è una libreria Open Source che permette di schedulare Job (processi) scritti in Java, e può essere utilizzata in qualsiasi applicazione Java sia di tipo Enterprise (J2EE) che stand alone (J2SE).

L’esecuzione di un Job avviene quando il Trigger ad esso associato “scatta”. E’ possibile creare dei Trigger che scattino all’accadere delle più disparate combinazioni di eventi:

  • ad una certa ora del giorno;
  • in un certo giorno della settimana, del mese o dell’anno;
  • ripetuto nel tempo;
  • ripetuto fino ad una specifica data;
  • ripetuto con un certo ritardo.

E’ possibile assegnare più Job ad un Trigger, o meglio è possibile organizzarli in Gruppi e farli poi eseguire insieme.

Per scaricare Quartz bisogna recarsi al seguente indirizzo:

http://www.quartz-scheduler.org/downloads/

All’interno del pacchetto scaricato troviamo il file .jar che ha un nome formato dal prefisso quartz-all seguito dalla versione che attualmente si è scaricata, ad esempio quartz-all-1.8.3.jar . Inoltre troviamo una cartella lib con le librerie .jar da includere affinché Quartz possa funzionare.

Le librerie sono:

  • commons-dbcp-1.3.jar;
  • commons-pool-1.5.4.jar;
  • jta-1.1.jar;
  • log4j-1.2.14.jar;
  • slf4j-api-1.5.10.jar;
  • slf4j-log4j12-1.5.10.jar.

Per poter configurare il comportamento di Quartz, basta aggiungere un file quartz.properties all’interno del classpath ed inserire al suo interno  i parametri che vogliamo personalizzare.

Un esempio di quartz.properties è il seguente:

########
#Scheduler configuration
########
org.quartz.scheduler.instanceName = Scheduler
org.quartz.scheduler.instanceId = 1
org.quartz.scheduler.rmi.export = false
org.quartz.scheduler.rmi.proxy = false
########
#ThreadPool configuration
########
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 3
########
#Store configuration
########
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore
########
#Plugin configuration
########
org.quartz.plugin.jobInitializer.class = org.quartz.plugins.xml.XMLSchedulingDataProcessorPlugin
org.quartz.plugin.jobInitializer.fileNames = ./jobs.xml
org.quartz.plugin.jobInitializer.failOnFileNotFound = true

Lo scheduler creato con questi parametri ha queste caratteristiche:

  • org.quartz.scheduler.instanceName : abbiamo denominato l’istanza del nostro Scheduler col nome MyScheduler;
  • org.quartz.scheduler.rmi.export : settando a false questa proprietà rendiamo lo Scheduler locale e non accessibile tramite RMI;
  • org.quartz.threadPool.threadCount : abbiamo settato il numero di Thred a 3, quindi possiamo lanciare 3 Job contemporaneamente in esecuzione;
  • org.quartz.jobStore.class: tutti i dati utilizzati da Quartz per i Job e i Trigger sono conservati in memoria Ram;
  • org.quartz.plugin.jobInitializer.class: con questa proprietà definiamo come inizializzare i nostri Job e Trigger, abbiamo scelto di farlo tramite uno o più  file XML;
  • org.quartz.plugin.jobInitializer.fileNames: indichiamo i file XML da cui caricare i dati per i nostri Job e per i Trigger in questo caso jobs.xml.

Un esempio di file XML che descrive i nostri Job e configura un Trigger è il seguente:

<?xml version="1.0" encoding="UTF-8"?>
<job-scheduling-data xmlns="http://www.quartz-scheduler.org/xml/JobSchedulingData"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.quartz-scheduler.org/xml/JobSchedulingData http://www.quartz-scheduler.org/xml/job_scheduling_data_1_8.xsd"
version="1.8">
<pre-processing-commands>
<delete-jobs-in-group>*</delete-jobs-in-group> <!-- clear all jobs in scheduler -->
<delete-triggers-in-group>*</delete-triggers-in-group> <!-- clear all triggers in scheduler -->
</pre-processing-commands>
<processing-directives>
<!-- if there are any jobs/trigger in scheduler of same name (as in this file), overwrite them -->
<overwrite-existing-data>true</overwrite-existing-data>
<!-- if there are any jobs/trigger in scheduler of same name (as in this file), and over-write is false, ignore them rather then generating an error -->
<ignore-duplicates>false</ignore-duplicates>
</processing-directives>
<schedule>
<job>
<name>MyJob</name>
<job-class>it.appuntisoftware.MyJob</job-class>
</job>
<trigger>
<simple>
<name>TestSimpleTrigger1AtFiveSecondInterval</name>
<job-name>MyJob</job-name>
<repeat-count>-1</repeat-count> <!-- repeat indefinitely -->
<repeat-interval>5000</repeat-interval> <!-- every 5 seconds -->
</simple>
</trigger>
</schedule>
</job-scheduling-data>

Dove abbiamo definito un unico Job dal nome MyJob che viene eseguito ogni 5 secondi ininterrottamente.

Vediamo ora come creare un semplice Job e passarlo al nostro Scheduler:

package it.appuntisoftware;
import java.util.Date;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzTest {
 public static void main(String[] args) {
  try {
    // Otteniamo una istanza dello Scheduler dalla Factory
    Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
    // avviamola
    scheduler.start();
    // Definiamo una istanza del nostro Job che ha come Classe MyJob
    JobDetail job = new JobDetail("job1", "group1", MyJob.class);
    //Definiamo un Trigger che scatta ora
    Trigger trigger = new SimpleTrigger("trigger1", "group1", new Date());
    // Scheduliamo il Job
    scheduler.scheduleJob(job, trigger);
    scheduler.shutdown();
  } catch (SchedulerException se) {
     se.printStackTrace();
  }
 }
}

Per poter funziona questo programma dobbiamo definire la classe MyJob, questa classe dovrà implementare la interfaccia Job definita nella libreria Quartz in questo modo:

package org.quartz;
public interface Job {
    public void execute(JobExecutionContext context)
      throws JobExecutionException;
}

La nostra classe MyJob sarà ad esempio:

package it.appuntisoftware;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
public class MyJob implements Job {
     public void execute(JobExecutionContext jec) throws JobExecutionException {
          System.out.println("Ciao Mondo");
}
}

Stamperà dunque a video il testo “Ciao Mondo!”.

In un prossimo articolo vedremo come integrare Quartz all’interno di una Web Application.

1 Stella2 Stelle3 Stelle4 Stelle5 Stelle (3 voti, media: 4,33 di 5)
Loading...
You can leave a response, or trackback from your own site.

Leave a Reply

*