Payara 5-在Jar文件中未调用带有[observer@Initialized(ApplicationScoped



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

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

不过,当使用payara/micro:4.181时,它会被正确调用。

再现所描述的行为:

  1. 从github_link_to_illustration_files下载所附的reproduct_observer_sissue.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 repissue:v1
  • docker运行repissue:v1
  1. 如果您检查路径";current_dir\sources\libs\lib\src\main\java\mylib\Library.java"您可以看到它包含两个init方法,但是在payara/micro:5.222.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 ###");
}
}

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

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

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

并且">上下文";这里指的是CDI上下文,而ServletContext绝对不是。

此外,我没有发现任何关于事件消息类型的文档。因此,这完全是特定于实现的,不应该对此进行任何假设(如果您想保持代码的可移植性(。

如果您的Library对象在Payara 4中两次接收到该事件(一次使用Object,一次使用ServletContext(,则这可能被视为该平台的错误(更不用说bug(。

如果您希望收到服务器启动的通知并在该阶段获得ServletContext,我建议您实现javax.servlet.ServletContainerInitializerjavax.servlet.ServletContextListenerServletContextListener(相对于其他(的最大优势是可以轻松地与CDIBean(@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项目进行测试(

希望这能有所帮助。

更新

我还发现了以下Gist,这似乎正是你想要实现的:https://gist.github.com/mojavelinux/637959

注意,这里@Initialized@Destroyed是自定义限定符,而不是来自包javax.enterprise.context的限定符。

此外,这里还有使用javax.enterprise.context限定符的Gist的更新版本:https://gist.github.com/nineninesevenfour/d9c643ff5a7f98302f89687720d0a138.这样一来,Library的原始代码就可以保持不变。

然而,在更新的Gist中,这两个方法被调用了两次(一次来自Payara,一次来自ServletContextLifecycleNotifier:

// Library.java
public void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
System.out.println(" ### log-1 mylib.Library.init(java.lang.Object) called ###");
}
// App.java
public static void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
System.out.println(new App().getGreeting());
}

相关内容

  • 没有找到相关文章

最新更新