部署Java EE应用程序后执行任务

部署Java EE应用程序后执行任务,java,jakarta-ee,timer,Java,Jakarta Ee,Timer,我有一个JavaEE应用程序,它应该在部署后启动一次与外部系统的同步过程 如何实现这一要求?下面列出了在JavaEE应用程序中获取生命周期回调的几种常用方法 创建javax.servlet.ServletContextListener实现 如果您的.ear文件(embedded.war)中有一个web组件,或者您的部署本身就是一个.war,那么您可以在web.xml中添加一个组件,并在服务器启动或关闭时获得回调 例如: package com.stackoverflow.question im

我有一个JavaEE应用程序,它应该在部署后启动一次与外部系统的同步过程


如何实现这一要求?

下面列出了在JavaEE应用程序中获取生命周期回调的几种常用方法

创建javax.servlet.ServletContextListener实现

如果您的.ear文件(embedded.war)中有一个web组件,或者您的部署本身就是一个.war,那么您可以在
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\u 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>

例如,使用或在启动时初始化的servlet。当然,如果在一个集群中有多个应用程序部署,这将变得更加困难,并且只希望此过程运行一次。

您可以使用
@Startup
@PostConstruct
注释在应用程序启动时执行任务。

我测试了使用
@Startup
@PostConstruct
注释的建议解决方案。事实证明,Glassfish在所有用
@PostConstruct
注释的方法完成之前,不会完成应用程序的部署。因此,在我的情况下,部署将需要几分钟到一个小时

但是我想出了一个不同的方法来实现我想要的。最好的解决方案似乎是计时器回调方法,它在计时器执行后取消计时器

@无状态
公共类同步服务{
@时间表(小时=*,分钟=*,持续=假)
受保护的void init(计时器)
{
doTheSync();
timer.cancel();
}
}

如果应用程序服务器重新启动,使用非持久性计时器可以重新创建计时器。

您真的希望在“部署”(即新的EAR)或启动(JEE服务器重新启动)时启动该进程吗,这可能是你的意思。我只是想确保同步过程将在部署后或服务器启动时启动。该包是错误的。为什么没有
@WebListener
?你在用谷歌搜索OP的答案吗?@BalusC我不知道
@WebListener
我总是使用
web.xml
配置
ServletContextListeners
。我不太清楚它是如何工作的,所以我不想给出错误的建议。“我还弄错了哪个包裹?”巴卢斯克找到了。我不知道我怎么会错过那个错误的包裹名称。感谢您指出。
需要
结束标记根据我的经验,
@PostConstruct
注释应仅用于只需要几分钟的初始化任务。与外部系统的同步需要更长的时间。因此,同步不应绑定到bean本身的初始化。为什么您使用无状态bean而不是单例,我使用单例,它可以工作,但在作业运行时,我每分钟都有时间重试。。。这会抛出一个错误。
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 */
  }

}