Выполнение задачи после развертывания приложения Java EE
У меня есть приложение Java EE, которое должно запускать процесс синхронизации с внешней системой один раз после его развертывания.
Как я могу реализовать это требование?
Ответы
Ответ 1
Я протестировал предложенное решение, которое использует аннотации @Startup
и @PostConstruct
. Оказалось, что Glassfish не завершает развертывание приложения до тех пор, пока все методы, аннотированные с помощью @PostConstruct
, не закончатся. Поэтому в моем случае развертывание займет от нескольких минут до часа.
Но я понял другой способ добиться того, чего хочу. Лучшим решением является метод обратного вызова таймера, который отменяет его таймер после его выполнения.
@Stateless
public class SynchronisationService {
@Schedule(hour = "*", minute = "*", persistent = false)
protected void init(Timer timer)
{
doTheSync();
timer.cancel();
}
}
Использование непостоянного таймера позволяет повторить создание таймера, если сервер приложений перезагружен.
Ответ 2
Ниже перечислены несколько популярных методов получения обратных вызовов жизненного цикла в приложениях JavaEE.
Создать реализацию javax.servlet.ServletContextListener
Если у вас есть веб-компонент для вашего .ear файла (embedded.war), или ваше развертывание - это .war, вы можете добавить ServletContextListener
на ваш web.xml
и получить обратный вызов при запуске или завершении работы сервера.
Пример:
package com.stackoverflow.question
import javax.servlet.ServletContextListener;
import javax.servlet.ServletContextEvent;
public class MyServletContextListener implements ServletContextListener{
@Override
public void contextInitialized(ServletContextEvent contextEvent) {
/* Do Startup stuff. */
}
@Override
public void contextDestroyed(ServletContextEvent contextEvent) {
/* Do Shutdown stuff. */
}
}
а затем добавьте эту конфигурацию в дескриптор развертывания web.xml
.
$WAR_ROOT/WEB-INF/web.xml
.
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee">
<listener>
<listener-class>com.stackoverflow.question.MyServletContextListener</listener-class>
</listener>
</web-app>
Создать EJB 3.1 @Startup Bean
Этот метод использует одноэлементный EJB 3.1 для получения обратного вызова запуска и завершения работы с сервера.
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Startup;
import javax.ejb.Singleton;
@Singleton
@Startup
public class LifecycleBean {
@PostConstruct
public void init() {
/* Startup stuff here. */
}
@PreDestroy
public void destroy() {
/* Shutdown stuff here */
}
}
Ответ 3
Вы можете использовать аннотации @Startup
и @PostConstruct
для выполнения задач при запуске приложения.
Ответ 4
Используя ServletContextListener
или сервлет, который инициализируется при запуске, например. Конечно, это становится намного сложнее, если вы используете несколько развертываний приложения в кластере и хотите, чтобы этот процесс запускался один раз.