Чтобы создать таймер программно, EJB необходимо получить доступ к интерфейсу javax.ejb.TimerService с использованием либо внедрения зависимостей, либо SessionContext (SessionContext.getTimerService(), см. раздел «Внедрение зависимостей» главы 7) или с помощью поиска JNDI. Как показано в табл. 8.5, API TimerService имеет несколько методов, которые позволяют создавать множество разнообразных таймеров и получать от них информацию.
Аннотация | Описание |
---|---|
createTimer | Создает таймер на основе дат, промежутков времени или продолжительности. Эти методы не используют выражения на основе календаря |
createSingleActionTimer | Создает таймер одного действия, который истекает в заданный момент времени или через заданный промежуток времени. Контейнер удаляет таймер после того, как метод обратного вызова был успешно вызван |
createIntervalTimer | Создает таймер на основе промежутка времени, первое его срабатывание происходит в заданный момент, а все последующие — после заданного интервала |
createCalendarTimer | Создает таймер, использующий выражение на основе календаря, с помощью вспомогательного класса ScheduleExpression |
getAllTimers | Возвращает список всех доступных таймеров (интерфейс javax.ejb.Timer) |
Вспомогательный класс ScheduleExpression позволяет создать выражения на основе календаря программно. Вы найдете методы, относящиеся к атрибутам, определенным в табл. 8.2, и сможете запрограммировать все примеры, которые видели в табл. 8.4. Ниже приведено несколько строк кода, чтобы вы имели представление об этом:
new ScheduleExpression(). dayOfMonth("Mon"). month("Jan");
new ScheduleExpression(). second("10,30,50"). minute("*/5"). hour("10–14");
new ScheduleExpression(). dayOfWeek("1,5"). timezone("Europe/Lisbon");
new ScheduleExpression(). dayOfMonth(customer.getBirthDay())
Все методы службы TimerService (createSingleActionTimer, createCalendarTimer и т. д.) возвращают объект типа javax.ejb.Timer, который содержит информацию о созданном таймере (когда он был создан, является ли постоянным и т. д.). Объект класса Timer также позволяет EJB отменить таймер до его истечения. По истечении времени контейнер вызывает соответствующий метод @javax.ejb.Timeout компонента, передавая объект класса Timer. Компонент может иметь не более одного метода, аннотированного @Timeout.
Когда CustomerEJB (см. листинг 8.4) создает новый клиент в системе (метод createCustomer()), он создает таймер по календарю на основе даты рождения заказчика. Таким образом, с каждым годом контейнер вызовет компонент для создания и отправки заказчику электронного письма, содержащего поздравление с днем рождения. Для того чтобы сделать это, компонент, не сохраняющий состояние, сначала должен внедрить ссылку на службу таймера (с помощью @Resource). Метод CreateCustomer() сохраняет клиента в базе данных и использует день и месяц рождения для создания ScheduleExpression. Календарный таймер создается и, основываясь на объектах классов ScheduleExpression и customer, использует метод TimerConfig. Метод new TimerConfig(customer, true) настраивает устойчивый таймер (что указано параметром true), который передает объект типа customer.
@Stateless
public class CustomerEJB {
··@Resource
··TimerService t imerService;
··@PersistenceContext(unitName = "chapter08PU")
··private EntityManager em;
··public void createCustomer(Customer customer) {
····em.persist(customer);
····ScheduleExpression birthDay = new ScheduleExpression().
······dayOfMonth(customer.getBirthDay()). month(customer.getBirthMonth());