In questo articolo vedremo come integrare Quartz Scheduler all'interno di una Web Application Java, utilizzando per questo scopo l'IDE Eclipse.Otteniamo così un Job che è tenuto attivo dall'Application Server sul quale abbiamo fatto il deploy della Web Application (ad esempio Tomcat o JBoss) il quale ci consente di svolgere determinate operazioni in background o quando una applicazione non è utilizzata dagli utenti. Ad esempio possiamo prevedere un Job che parta di notte, elabori dei report con delle estrazioni da DB e li invii all'utente via Email, pronti per essere consultati il mattino seguente.
In questo articolo vedremo come integrare Quartz Scheduler all’interno di una Web Application Java, utilizzando per questo scopo l’IDE Eclipse.
Possiamo ottenere così facendo un Job che è tenuto attivo dal Container dell’Application Server sul quale abbiamo fatto il deploy della Web Application (ad esempio Tomcat o JBoss), Job che ci consente di svolgere determinate operazioni in background o quando una applicazione non è utilizzata dagli utenti. Ad esempio possiamo prevedere un Job che parta di notte, elabori dei report con delle estrazioni da DB e li invii all’utente via Email, pronti per essere consultati il mattino seguente.
Per iniziare creiamo un Progetto Web, in Eclipse clicchiamo su New -> Dynamic Web Project:
Assegniamo un nome al nostro progetto e lasciamo il resto come da default:
La prima cosa da fare è inserire le librerie .jar di Quartz all’interno della cartella WebContent/WEB-INF/lib, le possiamo copiare e incollare direttamente da Eclipse:
L’applicazione riuscirà a “vedere” queste librerie perchè vengono incluse nel Build Path del nostro progetto:
Aggiungiamo al file web.xml il seguente snippet di codice:
<servlet>
<servlet-name>QuartzInitializer</servlet-name>
<servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
<init-param>
<param-name>shutdown-on-unload</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>start-scheduler-on-load</param-name>
<param-value>true</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Stiamo dicendo al nostro Servlet Container (Tomcat o JBoss) di caricare la Servlet QuartzInitializerServlet allo startup della nostra applicazione.
Aggiungiamo nella cartella src un file quartz.properties con questi parametri (per il significato vedere questo articolo):
########
#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
La parte importante è la sezione Plugin configuration dove indichiamo da che fonte (in questo caso un file xml di nome jobs.xml) caricare i nostri Job ed i Trigger associati. Un esempio di file xml è il seguente (per un commento dettagliato dei campi si rimanda a questo articolo):
<?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> <!-- ripeti indefinitivamente -->
<repeat-interval>5000</repeat-interval> <!-- ogni 5 secondi -->
</simple>
</trigger>
</schedule>
</job-scheduling-data>
In questo file indichiamo allo Scheduler di Quartz di schedulare un Job di nome MyJob implementato dalla classe it.appuntisoftware.MyJob avviandolo allo scattare di un Trigger di nome TestSimpleTrigger1AtFiveSecondInterval, il quale si ripete indefinitivamente ogni 5 secondi.
Infine occorre creare la classe che implementi l’interfaccia Job e che svolga il compito che vogliamo. Nel nostro esempio semplicemente stampa a video un messaggio:
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 sono un Job!");
}
}
A questo punto non ci resta che pubblicare la nostra Web Application su di un Application Server, in Eclipse clicchiamo col tasto destro sul nostro progetto e poi su Run as -> Run on Server.
Otteniamo questo output sulla console:
...
INFO: QuartzInitializer: Quartz Initializer Servlet loaded, initializing Scheduler...
log4j:WARN No appenders could be found for logger (org.quartz.core.SchedulerSignalerImpl).
log4j:WARN Please initialize the log4j system properly.
18-nov-2010 17.13.58 org.apache.catalina.core.ApplicationContext log
INFO: QuartzInitializer: Scheduler has been started...
18-nov-2010 17.13.58 org.apache.catalina.core.ApplicationContext log
INFO: QuartzInitializer: Storing the Quartz Scheduler Factory in the servlet context at key: org.quartz.impl.StdSchedulerFactory.KEY
18-nov-2010 17.13.58 org.apache.coyote.http11.Http11Protocol start
INFO: Starting Coyote HTTP/1.1 on http-8080
18-nov-2010 17.13.58 org.apache.jk.common.ChannelSocket init
INFO: JK: ajp13 listening on /0.0.0.0:8009
18-nov-2010 17.13.58 org.apache.jk.server.JkMain start
INFO: Jk running ID=0 time=0/47 config=null
18-nov-2010 17.13.58 org.apache.catalina.startup.Catalina start
INFO: Server startup in 1734 ms
Ciao sono un Job!
Ciao sono un Job!
Ciao sono un Job!
Ciao sono un Job!
...
Dopo l’inizializzazione di Quartz inizierà ad essere stampato a video il messaggio del nostro Job ogni 5 secondi!
COMMENTS
Thanks for putting together (Italiano) Quartz Scheduler: integrazione con una Web Application | Appunti Software I am enjoying your posts. Would you do a guest post on a site I help run? Do you think that you could contribute? You can see our post styles at http://timwicks.com.au and certainly we would be interested in having you post an article or two on our blog, what do you think? If you are interested let me know through the contacts page on our site.(Italiano) Quartz Scheduler: integrazione con una Web Application | Appunti Software is an interesting name for a blog, keep up the great work , thanks, from Tim Wicks
bravo
Ho eseguito tutte le indicazioni (non uso Eclipse ma scrivo direttamente sulla cartella webapps di Tomcat sia le JSP che i .class compilati a parte) ma allo startup di Tomcat non carica la servlet QuartzInitializerServlet.
La struttura definitiva della mia web application è: (ometto la parte web che non è influente)
[WEB-INF]
[classes]
[jobs]
MyJob.class
job.xml
quartz.properties
[lib]
c3p0-0.9.1.1.jar
log4j-1.2.16.jar
quartz-all-2.1.1.jar
sl4j-api-1.6.1.jar
sl4j-log4j12-1.6.1.jar
web.xml (a cui ho aggiunto lo snippet di cui sopra)
Mi sono accorto che anche togliendo lo snippet non cambia il prompt di Tomcat segno che lo sta ignorando.
Dove sbaglio?
Grazie
[Errata corrige di precedente post]
Ho eseguito tutte le indicazioni (non uso Eclipse ma scrivo direttamente sulla cartella webapps di Tomcat sia le JSP che i .class compilati a parte) ma allo startup di Tomcat non carica la servlet QuartzInitializerServlet.
La struttura definitiva della mia web application è: (ometto la parte web che non è influente)
[WEB-INF]
-> [classes]
-> -> [jobs]
-> -> -> MyJob.class
-> -> job.xml
-> -> quartz.properties
-> [lib]
-> -> c3p0-0.9.1.1.jar
-> -> log4j-1.2.16.jar
-> -> quartz-all-2.1.1.jar
-> -> sl4j-api-1.6.1.jar
-> -> sl4j-log4j12-1.6.1.jar
-> web.xml (a cui ho aggiunto lo snippet di cui sopra)
Mi sono accorto che anche togliendo lo snippet non cambia il prompt di Tomcat segno che lo sta ignorando.
Dove sbaglio?
Grazie
Ciao,
puoi spiegarmi come posso da l mio job di quartz leggere e modificare un oggetto salvato in ServletContext? Grazie!!!