为什么TomEE类加载器进程没有从ear / lib中找到Hibernate类?

时间:2017-09-28 04:05:11

标签: hibernate ear tomee-7

我构建经典的ear应用程序包含子模块EJB(进入jar)和WEB(进入战争)。

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

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

Hibernate jar进入ear/lib。 hibernate-core-4.2.16.Final包含类org/hibernate/integrator/spi/Integrator

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

是对的吗?如果是,为什么?

请帮助

1 个答案:

答案 0 :(得分:2)

它没有从那里检测到它,因为它不是应该放置这种“全局”库的默认假设。 TomEE reference documentation州:

  

三个类加载器最小值:耳朵的类加载器,每个ejb-jar一个,每个WAR文件一个。

正如我们从这句话中得知的那样,EAR应用程序,特别是其EAR模块在容器启动时很早就用自己的类加载器实例进行初始化, WAR初始化之前启动使用自己的类加载器。

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

解决方案

然而,当你放入所有Hibernate jar(以及所有传递依赖项,如 antlr dom4j javassist ,. ..)根据TomEE directory layout进入全局lib目录。这样做更有意义,因为它可以被应用程序的不同部分重用,这些部分可以/将被捆绑到您的EAR可部署甚至是在同一容器中运行的完全不同的应用程序中。因此,全局 jar文件将在ejb模块的类路径中可用,因此Hibernate可以在容器启动时启动。

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

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

提示:

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

  2. 有关传递Hibernate依赖项的完整列表,请查看列表for version 4.2.x hereversion 4.3.x here,Hibernate 5.2.x。您只需要收集/捆绑引用的“编译依赖项”并将它们放入全局TomEE“lib”目录中以使其正常工作。

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

  4. 希望它有所帮助。