Planificación de tareas en Java mediante Quartz

9
82276

Planificación de tareas en Java mediante Quartz

Introducción

Normalmente los negocios requieren que en determinados momentos se ejecuten tareas de forma automática, por ejemplo:
«todos los viernes a las 15:00 enviar informes a clientes».

Crear un sistema robusto y completo que de soporte a la ejecución de esas tareas, además de no ser una tarea fácil,
sería como reinventar la rueda pues ya disponemos de frameworks maduros de libre uso como el que vamos a presentar en este tutorial.

Quartz es un framework open source, con licencia Apache 2.0 para la planificación y gestión de tareas.

Es usado activamente en conocidos proyectos y organizaciones como JBoss, Cocoon, Apache Jakarta,… ver más

Características principales

  1. Válido para aplicaciones tanto J2EE como J2SE.
  2. Planificación flexible de tareas, por ejemplo: el primer lunes de Enero de cada año a las 17:45.
  3. Mantenimiento del estado de las tareas incluso en caso de fallos y reinicios de máquinas.
  4. Posibilidad de participar en transacciones JTA.
  5. Posibilidad de trabajar en modo Clúster.
  6. Proporciona un completo API, con muchas clases de utilidad y muchos tipos Listener (JobListener, TriggerListener y SchedulerListener).

Principales clases e interfaces

A continuación describimos los componentes que lo compomen: Job, JobDetail, Trigger, JobStore, Scheduler.

org.quartz.Job

Definir una tarea es tan sencillo como implementar la interface org.quartz.Job cuya definición se muestra a continuación:

Como podéis observar, simplemente debemos implementar un método y lanzar una excepción en caso de error para que Quarz reintente su ejecución o no, en función de la configuración que especifiquemos.

org.quartz.JobDetail

Es una clase que almacena propiedades de una determinada tarea.

Las tareas se clasifican en grupos de tareas y cada tarea tiene un nombre único dentro del grupo. JobDetail define estás y otras propiedades.

Gracias a esta clasificación podemos pausar, iniciar, detener, etc. tareas o grupos de tareas de manera independiente al resto.

org.quartz.Trigger

Es una clase abstracta que define los instantes en que la tarea debe ser ejecutada, por ejemplo todos los lunes a las 16:00 de la tarde.

Existen varias implementaciones de esta clase pero las más usadas son:

org.quartz.SimpleTrigger

Permite especificar ejecuciones de tareas teniendo en cuenta los siguientes parámetros: fecha, hora, nº de repeticiones e intervalo entre repeticiones.

Por ejemplo, ejecutar la tarea X 3 veces el día 13/12/1976 a las 13:30 con 40 minutos entre cada ejecución.

Para que se haga una idea, la firma de uno de sus constructores es:

org.quartz.CronTrigger

Es el más utilizado, pues permite especificar mediante expresiones más complejas los instantes en los que deben ejecutarse las tareas.

Por ejemplo, todos los días 14 que caigan en jueves cada 5 minutos desde las 14:00 hasta las 18:00.

Aunque existe mucha funcionalidad de utilidad que permiten hacernos la vida más fácil a la hora de crear el CronTrigger, yo suelo usar
un constructor que acepta una cadena de texto representando una expresión de tipo Cron de Unix: segundos, minutos, horas, días del mes, meses, días de la semana, [año]
(observe que todos son obligatorios a excepción de el año).

«0 0 23 * * ?» La tarea será ejecutada todos los días a las 23:00
«0 20 15 * * 1 2007» La tarea será ejecutada todos los domingos del año 2007 a las 15:20

Para más información acerca de CronTrigger haga clic aquí.

org.quartz.JobStore

Interface para manejar el almacenamiento y recuperación de la información de planificación (tareas, triggers, etc).

Implementaciones de org.quartz.JobStore:
org.quartz.simpl.RAMJobStore Es la implementación de por defecto, almacena la información en memoria RAM por lo que cuando la aplicación finaliza no se guarda el estado.
org.quartz.impl.jdbcjobstore.JobStoreTX Implementación que almacena la información en una dase de datos a través de JDBC. Diseñado para entornos no transaccionales.
org.quartz.impl.jdbcjobstore.JobStoreCMP Implementación que almacena la información en una dase de datos a través de JDBC. Diseñado para entornos transaccionales.

La elección del JobStore se define a través de la propiedad org.quartz.jobStore.class de el archivo de propiedades de Quartz quartz.properties, por ejemplo.
org.quartz.jobStore.class = org.quartz.simpl.RAMJobStore

org.quartz.Scheduler

Su funcionalidad es almacenar y planificar las tareas (Job) en base a los Triggers, recuperar tareas fallidas, realizar reintentos y gestionar el estado del sistema de planificación.

Ejemplo. Planificación de tareas en modo programático.

A continuación y a modo de ejemplo vamos a crear una aplicación que lance una tarea cada 5 segundos.
Aunque la tarea podría realizar cualquier operación compleja, en este caso simplemente mostrará un mensaje por pantalla.

com.autentia.tutoriales.quartz.StatusMonitorJob.java

Implementación de la tarea:

com.autentia.tutoriales.quartz.StatusMonitor.java

Aplicación de escritorio que realiza la planificación de la tarea:

Ejemplo. Planificación de tareas en modo declarativo.

Por defecto, en la configuración de Quartz puede especificar tareas externamente a la aplicación en un archivo de nombre quartz_jobs.xml

Este método le ofrece una gran flexibilidad, ya que podrá añadir o eliminar tareas sin realizar la gestión de planificación dentro de la aplicación… simplemente deberá copiar las clases en el CLASSPATH de la máquina virtual Java.

quartz_jobs.xml

Aplicación Web para gestionar nuestras tareas (modo declarativo)

En el siguiente enlace http://prdownloads.sourceforge.net/quartz/quartz-web-app.zip puede obtener una útil aplicación Web para gestionar las tareas a través de una completa aplicación Web. Su uso queda fuera del alcance de este tutorial….

Los datos de acceso de por defecto son quartz tanto para el nombre de usuario como para la contraseña.

Direcciones de interés (en inglés)

Conclusiones

Quartz es un FrameWork maduro y muy extendido, que nos proporciona ampliar la funcionalidad de nuestros proyectos que basan en tareas de una forma fácil y flexible.

Sin lugar a dudas, Quartz es una opción a tener en cuenta en estos casos… Para más información diríjase a la documentación del proyecto.

Carlos García Pérez. Creador de MobileTest, un complemento educativo para los profesores y sus alumnos.

cgpcosmad@gmail.com

9 Comentarios

  1. QUe tal Carlos oye una pregunta, necesito programar más de una tarea en una Planificación de tareas en modo declarativo. pero sin utilizar spring, tienes alguna idea de como poder realizar esto..?

  2. RuLas, en este tutorial no uso Spring.

    Quartz no necesita para nada de Spring para cumplir su función, otra cosa es que Spring tenga clases de utilidades o facilite su integración por madio de la IoD.

  3. Que tal Carlos … creo que no fué muy clara mi pregunta…:D Es verdad que no usas spring, mi pregunta realmente era Bajo éste mismo ejemplo, ¿Cómo agrego otra tarea totalmente distinta dentro del mismo archivo de condiguración quartz_jobs.xml? ó solamente se puede configurar para una sola tarea.

    Saludos Charly!! de antemano muchas Gracias

  4. Hola: Muy bueno el artículo!!!
    Estoy comenzando a utilizar Quartz en un proyecto ya creado con anterioridad y me surge un problema:
    Necesito pasarle a un Job un JobData de un tipo complejo (Ej: .usingJobData(PROPIEDAD1, batch), donde batch es de tipo Batch), pues como no puedo hacer un constructor con parámetros para la clase que implementa Job…
    Si tienes alguna idea de cómo pudiera simular algo así, sería muy bienvenida. O alguna sugerencia de otro framework Java (puro) que permita planificación en el orden de los segundos. Muchas gracias de antemano. Saludos

  5. Hola carlos, alguna idea de este error:

    QuartzScheduler:305 – Scheduler meta-data: Quartz Scheduler (v2.2.1) ‘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.

    saludos espero me pueda orientar.

  6. Ola como estan tengo una consulta es como crear una tarea programada en un servidor Tomcat.
    Me refiero el uso de quartz en el codigo me queda claro actualmente envio mail diarios desde una apilcacion web coin quartz,pero ahora solo quiero programar la tarea sin interface ni nada, solo codigo que realize algo, «mi duda es que tipo de proyecto crear ?? y si solamnete es ponerlo en el tomcat» yo manejo la ide eclipse, Gracias

  7. Es una excelente herramienta para planificar las tareas, soy programador sin mucha experiencia en este tema por ello para programar un sistema de pruebas automáticas a un sistema ERP me ayudare de esta impresionante herramienta de Java.

  8. Buenos días. Una consulta tengo una app web que gestiona canjes de puntos a nuestros clientes, cada tanto se lanza promociones, los dias de no promocion la relacion de puntos es 1 pto = 0,5 pesos, y cuadno se lanzan promociones por ejemplo de 2 dias la relacion es de1 pto = 4 pesos, la idea es parametrizar esa relacion, entonces habiamos pensado un planificador de tareas, vi este post y pareciera que resuelve mi problema, lo unico malo es que veo que este job deberá correr todos los dias fijandose si hay una promocion y actualizar el parametro (relacion ptos por pesos) . En gral las promciones duran 2 a 3 dias y empiezan a las 00 am hrs y terminan a las 11:59 pm. mi dua es : puedo hacerlo con quartz ?, mi componente es un .ear, el servidor de aplicaciones es un jonas/tomcat , y la duda q me surge es la ejecucion de este job es una tarea interna ? o el servidor de app tiene conocimiento de este proceso que ejecuta todos los dias ?, no se si mi explicación es clara, pero lo que queremos es que este job corra internamente y que sea trasparente para el sefgvidor de applicaciones y no afecte a mi funionalidad principal. O que alternativa podria usar ?

    muchas gracias

Dejar respuesta

Please enter your comment!
Please enter your name here