7.27.2015

Timer EJB & Wildfly.



Если вам нужно запускать через определенный промежуток времени, какой-либо код, допустим, собирать статистику или проверить обновление какого либо сервиса, который предоставляет последние значения котировок валют или акций, то вам в этом деле может помочь  timer service EJB. Timer EJB  описывается аннотацией @Timeout, применяемой к методу, который будет выполнен после интервала времени ожидания таймера. Описывать таймер можно  с любыми типами EJB, кроме Stateful бина, обычно хватает одного экземпляра, для этого используется аннотация @Singleton. Применяя эту аннотацию, EJB  начинает вести себя как  java паттерн singleton. Давайте напишем простой timer, это аналог stateless EJB, он ведет себя подобным образом,  у него такой же жизненный цикл, так же могут существовать методы помеченные аннотациями  @PostConstruct и @PreDestroy, которые обычно используются для создания и уничтожения таймера. И так, во первых, нам нужно создать timer, затем установить период работы таймера, по истечению периода работы таймера, будет вызываться метод помеченный аннотацией @Timeout. Обычно в методе, помеченном аннотацией @PostConstruct, создают таймер и устанавливают время работы таймера. Таймер срабатывает с определенной периодичностью и  что бы его остановить,  нужно  вызвать метод  на таймере .cancel(); Во вторых, когда уничтожается EJB,  таймер тоже нужно остановить, это выполняется в методе помеченной аннотацией @PreDestroy. И еще одна важная вещь для того что бы EJB  таймер сервис заработал нужно выполнить метод помеченный аннотацией @PostConstruct, значит нужно запросить экземпляр где-то в коде. Или воспользоваться аннотацией @Startup которая автоматически создает экземпляр EJB для нас и соответственно запустит метод помеченной аннотацией  @PostConstruct. При создании таймера удобно пользоваться классом ScheduleExpression, который позволяет гибко настроить время срабатывания таймера. И так напишем EJB, смотрим на код:

package com.vit;

import org.jboss.logging.Logger;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.ejb.*;
import java.text.SimpleDateFormat;
import java.util.Date;

@Singleton
@Startup
public class TimeoutEJB {
    private final static Logger log = Logger.getLogger(TimeoutEJB.class.getName());

    @Resource
    private TimerService tm;

    @Timeout
    public void doTimeout() {
        Date currentTime = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
        log.info("TimeoutEJB.doTimeout() invoked at " + simpleDateFormat.format(currentTime));
    }

    @PostConstruct
    public void doStartup(){
        ScheduleExpression se = new ScheduleExpression();
        se.hour("*").minute("*").second("*/2");//через каждые 2 секунды будет выполнятся метод doTimeout()
        tm.createCalendarTimer(se, new TimerConfig("Hello TimerService",true));//создание таймера.
    }

    @PreDestroy
    public void doDestroy(){
        for (Timer timer: tm.getTimers()) {
            log.info("timer destroy"+timer.getInfo());
            timer.cancel();//уничножение таймера
        }
    }

}

Осталось только развернуть приложение, скопируйте его в каталог JBOSS_HOME/Standalone/deployments, после деплоя,  в логах сервера wildfly  появятся строчки примерно такого вида:

2015-07-26 21:23:08,054 INFO  [com.vit.TimeoutEJB] (EJB default - 9) TimeoutEJB.doTimeout() invoked at 2015.07.26  at 21:23:08 GMT+03:00

Для того что бы создать timer, можно поступить проще, объявить метод с аннотацией @Schedule и задать период, этот метод будет выполняться по истечению интервала таймера. И так смотрим на код:

package com.vit;

import org.jboss.logging.Logger;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
import java.text.SimpleDateFormat;
import java.util.Date;

@Singleton
public class ScheduleEJB {
    private static Logger log = Logger.getLogger(ScheduleEJB.class.getName());

    @Schedule(second = "*/3", minute = "*", hour="*")
    public void goSchedule() {
        Date currentTime = new Date();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
        log.info("ScheduleEJB.goSchedule() invoked at " + simpleDateFormat.format(currentTime));
    }
}

 В логах будет такой вывод:

2015-07-26 21:23:08,069 INFO  [com.vit.ScheduleEJB] (EJB default - 3) ScheduleEJB.goSchedule() invoked at 2015.07.26  at 21:23:08 GMT+03:00

Комментариев нет:

Отправить комментарий