1

我构建的经典ear 应用程序包含子模块EJB (into jar) 和WEB (into war)。

我将耳朵(JAR + WAR)部署到 TomEE 并使用 Hibernate JPA 提供程序。我收到以下错误:

Caused by: java.lang.NoClassDefFoundError: org/hibernate/integrator/spi/Integrator

Hibernate jars 被放入ear/lib. 有包含类的 hibernate-core-4.2.16.Final org/hibernate/integrator/spi/Integrator

所以我认为 Tomee ClassLoader 进程不会从我的 ear/lib 文件夹中加载类。

这样对吗?如果是,为什么?

请帮忙

4

1 回答 1

2

它不会从那里检测到它,因为它不是应该放置此类“全局”库的默认假设。TomEE 参考文档指出:

最少三个类加载器:一个类加载器用于耳朵,一个用于每个 ejb-jar,一个用于每个 WAR 文件。

正如我们从这句话中了解到的,一个 EAR 应用程序,尤其是它的 EAR 模块,在容器启动的早期就使用它们自己的类加载器实例进行了初始化,并且在使用自己的类加载器启动 WAR 初始化之前。

我猜你的 EAR 模块(jar 文件中的那个)代表后端层模块,扫描 Hibernate 试图加载相关的类文件。可悲的是,它无法在其类加载器的范围内“看到”它们。

解决方案

但是,当您根据TomEE 目录布局将所有 Hibernate jar(以及所有传递依赖项,如antlrdom4jjavassist ……)放入全局目录时,它将起作用。无论如何,这更有意义,因为它可以被应用程序的不同部分重用,这些部分可以/将被捆绑到您的 EAR 可部署中,甚至完全不同的应用程序在同一个容器中运行。因此,全局jar 文件将在 ejb 模块的类路径中可用,因此可以在容器启动时启动 Hibernate。lib

一旦放入容器范围的安装中,您就可以将 Hibernate jar 从捆绑到文件夹中删除(通过在 Maven 项目设置中将EAR/lib其声明为提供的依赖项)。pom.xml

这将 - 作为副作用也大大减少了您的 EAR 包大小,因为这些库现在是“全局的”。在运行时,您还将观察到我们减少了内存占用,因为 Hibernate ORM 的所有类文件只会在容器中加载一次,而不是针对不同的 EAR 或 WAR 包多次加载。

提示:

  1. 在使用 TomEE-7 时,我建议将 Hibernate 至少升级到 4.3.11 版本,因为 4.3.x 的 Hibernate JPA 支持可用于规范的 2.1 版本。此外,如果您有空,请尝试您的应用程序迁移到 Hibernate 5.2.x 版本,因为它带来了很多改进。

  2. 有关传递 Hibernate 依赖项的完整列表,请查看此处的 4.2.x 版本列表或此处的4.3.x 版本列表,类似的 Hibernate 5.2.x。您只需要收集/捆绑引用的“编译依赖项”并将它们放入全局 TomEE“lib”目录中即可。

  3. 还将您在应用程序中使用的 JDBC 驱动程序放在全局lib文件夹中。

希望能帮助到你。

于 2017-10-22T08:23:07.060 回答