Quartz es un programador de tareas Open Source que puede ser integrado en desarrollos Java. Está distribuido bajo licencia Apache 2.0.
En esta entrada, se describe la configuración de Quartz 1.8.6 con las siguientes características:
- Integración con Spring Framework.
- Gestión Maven
- Persistencia en base de datos PostgreSQL y JTA.
Las necesidades que se cubren:
- Programar tareas que se ejecuten en el arranque o reinicio del servidor.
- Persistencia de las tareas programadas en caso de reinicio.
- Programar y cancelar tareas dinámicamente.
Algunos Conceptos
Scheduler: Es el planificador, el encargado de registrar jobs, triggers y de lanzarlos cuando corresponda (quien lo hace).
Jobs: Son los procesos que se quieren ejecutar (que se hace).
Triggers: Son los disparadores, indican cuando debe ejecutarse un job determinado (cuando se hace).
Configuración
Dependencias Maven
<dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>1.8.6</version> </dependency>
Configuración de Quartz
Se añade en el fichero de configuración de la aplicación (web.xml), una referencia al fichero que crearemos para la configuración de Quartz (en nuestro caso quartz.xml):
<context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:/applicationContext.xml classpath:/quartz.xml </param-value> </context-param>
Y a continuación crearemos el fichero de configuración (quartz.xml):
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd default-lazy-init="true"> <!-- Definimos el planificador que se ejecutará al inicio (nuestroScheduler) --> <bean id="nuestroScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="autoStartup" value="true"/> <property name="applicationContextSchedulerContextKey" value="applicationContext"/> <property name="waitForJobsToCompleteOnShutdown" value="true"/> <property name="overwriteExistingJobs" value="true"/> <!-- Persistencia en la base de datos --> <property name="dataSource"> <ref bean="dataSource"/> </property> <!-- Se especifica el Driver para PostgreSQL --> <property name="quartzProperties"> <props> <prop key="org.quartz.jobStore.driverDelegateClass">org.quartz.impl.jdbcjobstore.PostgreSQLDelegate</prop> </props> </property> <!-- Uso de transacciones del sistema --> <property name="transactionManager"> <ref bean="transactionManager"/> </property> <!-- Jobs definidos en el planificador --> <property name="jobDetails"> <list> <ref bean="quartzExampleJobDetail" /> </list> </property> <!-- Triggers fijos --> <property name="triggers"> <list> <ref bean="quartzExampleTrigger" /> </list> </property> <!-- Se añaden los services al contexto del scheduler para inyectar dependencias (necesario para llamar a los servicios desde el Job) --> <property name="schedulerContextAsMap"> <map> <entry key="nuestroService" value-ref="nuestroService" /> </map> </property> </bean> <!-- Definición de beans que necesitamos inyectar en el contexto del planificador --> <bean name="nuestroService" class="org.empresa.nuestroServiceImpl" /> <!-- Quartz Jobs (Lo que se va a hacer) --> <!--job: ejemplo --> <bean name="quartzExampleJobDetail" class="org.springframework.scheduling.quartz.JobDetailBean"> <property name="jobClass" value="org.empresa.jobs.QuartzExample"/> <property name="description" value="Ejemplo de Job Quartz" /> <property name="volatility" value="false" /> <property name="durability" value="true" /> </bean> <!-- Quartz Triggers (Cuando se va a hacer) --> <!--trigger: ejemplo --> <bean id="quartzExampleTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="quartzExampleJobDetail" /> <property name="volatility" value="false" /> <property name="description" value="Ejecuta el ejemplo cada 20 minutos" /> <property name="cronExpression" value="0 0/20 * 1/1 * ? *" /> </bean> </beans><code class="xml plain"></code>
Aclaraciones:
- Las propiedades DataSource nos permite usar la configuración de base de datos definida en Spring. Al usar PostgreSQL, hay que indicar que use el driver específico. Por defecto usa un driver genérico que en el caso de PostgreSQL no funciona correctamente.
- La propiedad transactionManager indica que use el gestor de transacciones definido en Spring.
- La propiedad applicationContextSchedulerContextKey, nos permite definir el contexto en el que se ejecutará el Scheduler. Esto nos permite inyectar dependencias de los servicios de nuestra aplicación para que se puedan usar desde los Jobs. Esto es necesario porque el Scheduler se ejecuta en un contexto distinto del de Spring.
- Junto con la propiedad anterior, en el schedulerContextAsMap se inlcuirán los servicios para los que se quieren inyectar las dependencias.
- Los Jobs se pueden definir en este fichero. Lo normal es que lo que se quiera definir dinámicamente sean los triggers.
- Los Triggers fijos también se pueden definir en este fichero.
- Hay que tener cuidado de no mezclar librerías, existen librerías específicas de Quartz para Spring que son las que deben usarse. Muchos problemas pueden venir de usar librerías nativas de Quartz en lugar de las de Spring para definir Jobs, triggers, etc.
Con esto estaría configurado nuestro sistema para programar y ejecutar jobs. En el siguiente post veremos como implementarlos.
Un comentario en “Quartz con Spring I: Configuración”