martes, 22 de octubre de 2013

Planificador de tareas a través de EJB

En ciertas ocaciones necesitamos que ciertas tareas se ejeuten cada cierto tiempo o en monentos determinados.

Supongamos por ejemplo que tenemos que guardar la imagen de la base de datos del stock de un almacén todas las noches. En este caso lo que haríamos es tener una aplicación que se ejecute de modo automático todas las noches.

En EJB tenemos dos modos de realizar esto:
Usando las anotaciones @Schedule y @Schedulers. 

En este caso se añade la anotación @Shedules a cada función que se quiera añadir al planificador, dentro de esta anotación se añade una o mas anotaciones del tipo @Shedule. Cada anotación Shedule va a permitir  que la tarea se ejecute en los momentos indicados pudiéndose indica las siguientes opciones:
  • second. Indica en que segunda se ejecutará el proceso.
  • minute. Indica el minuto dentro de la hora.
  • hour. Hora de ejecución.
  • dayOfMonth. Día dentro del mes en que se ejecutará el proceso. Aquí se permiten los siguientes valores:
    • Un número del 0 al 31
    • Un valor negativo entre -1 y -7. En este caso le estamos diciendo que se ejecute -n días antes del último día del mes.
    • Last. Para indicar el último día del mes.
    • {"1st", "2nd", "3rd", "4th", "5th", "Last"} {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat". Para indicar si se quiere que se ejecute el primer lunes o martes, etc del mes.
  • month. Indica uno o varios meses. Sus posibles bvalores son un número de 1 a 12 o los textos: "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", Dec".
  •  dayOfWeek. Que día de la semana se realizará la ejecución. Los posibles valores son un valor numérico de 0 a 7 o los textos: "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat".
  • year. Un año indicado con cuatro dígitos.
A continuación os pongo un ejemplo en el que se ejecuta una tarea todos los días de la semana de Lunes a Viernes a las 17:30 horas.

package com.blogspot.ejb;

import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.Schedule;
import javax.ejb.Schedules;
import javax.ejb.Singleton;

@Singleton
@Lock(LockType.READ)
public class ScheduleEJB
{
     @Schedules({
         @Schedule(dayOfWeek = "Mon, Tue, Wed, Thu, Fri", hour = "17", minute = "30" , second = "0")
     })   
     private void guardarStock()
     {
         // Tarea a realizar
     }
}

Creando una ScheduleExpressiony usando TimerService.


En el siguiente ejemplo lo que hacemos es crear una SchedulerExpresion prácticamente lo que se hace es inicializar la clase con las mismas opciones de la anotación @Schedule. La diferencia es que en este caso estamos inicializando la expresión programaticamente en la función que se ejecutará tras la creación de una instancia de la clase (de ahí el uso de la anotación @PostConstruct).



package com.blogspot.ejb;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Lock;
import javax.ejb.LockType;
import javax.ejb.ScheduleExpression;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;

/**
 *
 * @author <a href="mailto:ljlosadag@gmail.com">LJLG</a>
 */
@Singleton
@Lock(LockType.READ)
@Startup
public class ScheduleExpresionEJB {

    @Resource
    private TimerService timerService;
   
    @PostConstruct
    private void construct() {
        final TimerConfig guardarStock = new TimerConfig("guardarStock", false);
        timerService.createCalendarTimer(new ScheduleExpression().dayOfWeek("Mon, Tue, Wed, Thu, Fri")
                .hour("17").minute("30").second("0"),
                guardarStock);
    }
   
    @Timeout
    public void timeout(Timer timer)
    {
        guardarStock();
    }
   
     private void guardarStock()
     {
         // Tarea a realizar
     }
   }

Antes de decidirnos por que método usar se deben tener en cuenta las diferencias entre ambos:

@Shedule:
  • Son configurados de modo estático.
  • Es posible definir multiples metodos cada uno con su propio sheduler.
  • No es posible pasar ningún tipo de argumento.
  • No puede ser cancelado.
ScheduleExpression:
  • Es creado dinamicamente. Esto nos permite cambios, por ejemplo podrían tomarse los valores de un fichero de propiedades, de modo que no se necesitarían cambios en el código para cambiar el momento de ejecución.
  • Todas las expresiones que se definan dentro del ejb deben ser tratadas por una única función, aquella que se encuentra anotada con @Timeout.
  •  Es posible pasar argumentos. El constructor de TimerConfig permite pasar un objeto que sea serializable. Este objeto puede ser recuperado del Timer con la función Timer.getInfo().
  • La ejecución puede ser cancelada.

No hay comentarios:

Publicar un comentario