这里的问题是,从用于将其部署到服务器的 ear 模块引用 EJB 与从需要 EJB 类与服务器接口的客户端引用它是不同的。
如果您在 ear 模块中包含依赖项,它将认为您正在声明要部署的 EJB 模块。它将把它放在 EAR 的根目录中并在 application.xml 中声明它。
如果你包含依赖项,例如,在一个 war 模块中,你将得到完全相同的工件,但它将被视为一个库并放置在 WEB-INF/lib 中。
现在,当您生成瘦战争时,对 ejb 模块的显式依赖与 WAR 中的依赖不匹配,因为 Maven 不认为它们是同一件事。这导致 JAR 被保存在使用它的 WAR/s 中。
我知道的唯一解决方案是始终为 ejb 模块生成客户端工件,即使客户端工件与主工件相同。
<type>ejb</type>
现在,您只需在 EAR 中使用依赖项。对于客户,您总是使用<type>ejb-client</type>
一个。
要从 WAR/s 中删除客户端并将其定位在 EAR 的 lib 目录中,您必须显式地将依赖项添加到 ear 模块。
因此,您的 ear 模块中的 ejb 模块有两个依赖项:一个依赖于 ejb 本身,一个依赖于客户端。第一个将 EJB 放在 EAR 的根目录中并在 application.xml 中声明它。第二个会将客户端放在 EAR 的 lib 目录中,并在必要时更新 WAR/s manifest/s。
但是如果客户端和主要工件是相同的,你会得到重复吗?
简短的回答是肯定的。长答案是肯定的。它确实会被复制,但只有一次,而不是在每个使用它的 WAR 中。我认为没有一种干净的方法可以避免这种情况,我不确定它在概念上是否有意义。当然,您可以使用 PackagingExcludes 和自定义清单,但是拥有两次 JAR 是有意义的。
如果您的客户端 JAR 真的更薄(例如,只有接口),并且 WAR/s 引用客户端 JAR 有效地禁止他们访问 EJB 实现,这始终是一个好主意。
您可以将相同的 JAR 视为前一个 JAR 的特例,将它们分开在概念上是有意义的。
因此,我的建议是始终为 ejb 生成客户端工件并按照说明进行操作。总有一些东西可以排除在外,至少是任何不需要的非类文件,例如 package.html 或 ejb-jar.xml。