Выполнение задачи после развертывания приложения 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 или сервлет, который инициализируется при запуске, например. Конечно, это становится намного сложнее, если вы используете несколько развертываний приложения в кластере и хотите, чтобы этот процесс запускался один раз.