jakarta-ee - EJB 模块无法从 glassfish 上的另一个 EJB 模块找到类

标签 jakarta-ee deployment ejb-3.0 dependency-management glassfish-2.x

我在我的 Glassfish 2.1 服务器上部署了一个 EJB 3 模块。

我正在尝试部署第二个 EJB 模块,它依赖于第一个模块,但是部署失败,并出现关于可以在第一个 EJB 模块中找到的类的 java.lang.NoClassDefFoundError。

解决 2 个 EJB 模块之间依赖关系的最佳方法是什么?我想单独部署它们,而不是将它们放在同一个 EAR 中。

更具体地说,我在我的第二个 EJB 模块的一个 EJB 中有一个来 self 的第一个 EJB 模块的 EJB 的依赖注入(inject):

@EJB (name="ejb/FirstEJB")
private FirstEJBRemote ejb;

但是在部署期间我得到了关于类 FirstEJBRemote 的 NoClassDefFoundError:

Error in annotation processing: java.lang.NoClassDefFoundError: FirstEJBRemote

最佳答案

要理解为什么会出现这个异常,需要掌握两点:

  1. 一个 EJB 如何引用另一个 EJB
  2. EJB 类加载

让我们首先处理第一个,所以让我们命名第一个 EJB(包含 FirstEJBRemote 类)EJB_A 和第二个 EJB(试图访问 EJB_A 的方法)EJB_B 。无需深入了解 @LocalBean 注释和类似内容,EJB_B 访问 EJB_A 方法的唯一方法是通过接口(interface)。换句话说,EJB_A 实现了一些接口(interface)(在您的例子中是 FirstEJBRemote),EJB_B 声明并通过注入(inject)检索 EJB_A 的实例。到目前为止,还不错。

接下来,我们必须了解 EJB 类加载器。自然地,您的应用程序(在本例中为 EJB)在编译时使用的每个外部类/库也必须在运行时可用。否则,将抛出 ClassNotFoundException,这正是您的情况,因为 EJB_B 在编译时使用 FirstEJBRemote:

private FirstEJBRemote ejb;

要在运行时向 EJB 提供此外部类/库,必须执行以下操作:

  • 将class/library放在应用服务器的lib目录下
  • 将类/库与 EJB 一起打包
  • 将类/库放在包含您的 EJB 的 EAR 类路径中

我们将忽略第三个选项,因为您说您对 EAR 不感兴趣。因此,您可以将 FirstEJBRemote 接口(interface)(当然是以 .jar 文件的形式)放在 Glassfish 的 lib 目录中,它对 EJB_A 和 EJB_B 都可用(因此,您不必既不将其与 EJB_A 一起打包),也可以将此接口(interface)与 EJB_B 一起打包,注意它与 EJB_A 位于同一包中。

在您的评论中,您想知道为什么需要这个“复杂”的过程。答案很简单——如果 EJB 类加载器没有相互隔离,那么使用 EJB_A 部署的每个类都将对 EJB_B 可用。在这种特殊情况下,这是希望的行为,但想象一下当 EJB_A 包含某个库(例如日志库)的版本 1 并且 EJB_B 使用同一个库但版本 2 时会发生什么。两个类都将被加载,您将到处遇到冲突、ClassCastException 等(或者如果您幸运的话,EJB_B 将“仅”被迫使用 version1,因为该类已经被类加载器加载)。

最后,摘录自Oracle GlassFish 3.1 Guide:

Circumventing Class Loader Isolation

Since each application or individually deployed module class loader universe is isolated, an application or module cannot load classes from another application or module. This prevents two similarly named classes in different applications or modules from interfering with each other.

关于jakarta-ee - EJB 模块无法从 glassfish 上的另一个 EJB 模块找到类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16465563/

相关文章:

java - 将日期保留为字符串的最佳方法

java - 消息驱动 Bean 的过滤器类

java - 关于打包 Java EE 应用程序,正确的是

ruby-on-rails - 已部署的 Rails 应用程序出现 Postgresql 错误

linux - 什么触发tomcat自动部署

java - 如何使用 Java 代码向 Flink 集群提交作业?

windows - Cordova : how to deploy windows 10 apps

jboss - 如何在 Jboss 7 的 Application Client Container 中 jun 一个 jar 文件?

java - request.getSession(false) 在调用 session.invalidate() 后不返回 null

java - DAO 设计模式并在多个表中使用它