【问题标题】:Payara 5 - Method with [observer @Initialized(ApplicationScoped.class) ServletContext init] is not invoked inside Jar filesPayara 5 - 使用 [observer @Initialized(ApplicationScoped.class) ServletContext init] 的方法不会在 Jar 文件中调用
【发布时间】:2022-10-09 05:41:01
【问题描述】:

我试图从 payara/micro:4.181 迁移到 payara/micro:5.2022.3,我注意到在 Jar 文件中没有调用带有观察者 [@initialized(ApplicationScoped.class) ServletContext init] 的初始化方法。

public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext init)

但是,在使用 payara/micro:4.181 时会正确调用它。

要重现所描述的行为:

  1. github_link_to_illustration_files 下载附件reproduce_observer_issue.zip
  2. 解压文件到“current_dir” 解压后的文件包含一个 Dockerfile,内容如下:
    #FROM payara/micro:5.2022.3
    FROM payara/micro:4.181
    COPY app.war $DEPLOY_DIR
    

    取消注释与您要运行应用程序的 payara/micro 版本相对应的行。

    1. 运行以下 docker 命令来部署应用程序:
    • docker build -t reissue:v1。
    • docker 运行重新发布:v1
    1. 如果您检查路径“current_dir\sources\libs\lib\src\main\java\mylib\Library.java”,您可以看到它包含两个初始化方法,但是在 payara/micro:5.2022.3 上部署时init(@observes @initialized(ApplicationScoped.class) ServletContext init) 不会被调用(检查日志)
    package mylib;
    
    import javax.enterprise.context.ApplicationScoped;
    import javax.enterprise.context.Initialized;
    import javax.enterprise.event.Observes;
    import javax.servlet.ServletContext;
    
    @ApplicationScoped
    public class Library {
        public boolean someLibraryMethod() {
            return true;
        }
    
        public void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
            System.out.println(" ### log-1 mylib.Library.init(java.lang.Object) called ###");
        }
    
        public void init(@Observes @Initialized(ApplicationScoped.class) ServletContext init) {
            System.out.println(" ### log-2 mylib.Library.init(javax.servlet.ServletContext) invoked ###");
        }
    }
    

    提前感谢任何最终的回复/提示

【问题讨论】:

  • 请从 server.log 添加带有错误消息的部分
  • 嗨@SlavaKuravsky,没有错误日志只是不会调用带有ServletContext参数的init方法(因此会丢失相应的日志)这仅在payara 5上运行时才会发生。但是在payara 4上部署时,所有init方法都在上面的描述被称为。谢谢
  • 我建议您查看从 4 到 5 的迁移指南,也许它以不同的方式工作
  • 我会再检查一遍,谢谢
  • 我查了一下,但没有找到关于这个的东西

标签: java docker payara-micro


【解决方案1】:

我认为对@Observes @Initialized(ApplicationScoped.class) 的期望存在误解。 JakartaEE specs (8) 说:

初始化上下文(即准备好使用)时会触发具有此限定符的事件。

和 ”语境" 这里指的是 CDI 上下文,ServletContext 绝对不是。

此外,我没有找到任何关于事件消息类型的文档。因此,这完全是特定于实现的,不应该对它做出任何假设(如果你想保持你的代码可移植)。

如果您的 Library 对象在 Payara 4 中两次收到该事件(一次是 Object,一次是 ServletContext),那么这可以被认为是该平台的错误(不是说 bug)。

如果您想在该阶段收到有关服务器启动的通知并获取ServletContext,我建议您实施javax.servlet.ServletContainerInitializerjavax.servlet.ServletContextListenerServletContextListener(相对于另一个)的最大优势是您可以轻松地与 CDI bean(@ApplicationScoped@Singleton)进行交互。

这是一个例子:

package mylib;

import javax.inject.Inject;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;

@WebListener
public class MyListener implements ServletContextListener {

    @Inject
    Library library;

    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println(" ### log-4 mylib.MyListener.contextInitialized() invoked ###");
        System.out.println(sce.getServletContext());
        System.out.println(library);
        System.out.println(library.someLibraryMethod());
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println(" ### log-5 mylib.MyListener.contextDestroyed() invoked ###");
        System.out.println(sce.getServletContext());

    }
}

(用你的 Docker 项目测试过)

希望这可以帮助。

【讨论】:

    猜你喜欢
    • 2019-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-20
    • 2011-03-30
    • 2012-04-15
    • 2011-12-18
    • 1970-01-01
    相关资源
    最近更新 更多