Hello World Ear: NoModuleFileException:文件不存在具有uri: core-api.



我有一个简单的EAR文件,配置如下:

app.ear
|-- lib/...
|-- META-INF/application.xml
|-- core.jar
|   |-- test/MyServiceImpl.class
|   `-- META-INF/MANIFEST.MF // Class-Path: core-api.jar 
|-- core-api.jar
|   `-- test/MyService.class
`-- web.war
    `-- META-INF/MANIFEST.MF // Class-Path: core.jar core-api.jar

application.xml如下所示:

<?xml version="1.0"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" id="app 1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd" version="6">
  <application-name>MyApp</application-name>
  <display-name>My App</display-name>
  <module id="mod 1">
    <java>core-api.jar</java>
  </module>
  <module id="mod 2">
    <java>core.jar</java>
  </module>
  <module id="mod 3">
    <web>
      <web-uri>web.war</web-uri>
      <context-root>/</context-root>
    </web>
  </module>
  <library-directory>lib</library-directory>
</application>

当我尝试将应用程序部署到服务器时,我得到以下异常:

[*] 00000088 SystemErr     R Caused by: org.eclipse.jst.j2ee.commonarchivecore.internal.exception.NoModuleFileException: A file does not exist for module element having uri: core-api.jar
[*] 00000088 SystemErr     R    at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.ModuleRefImpl.checkType(ModuleRefImpl.java:591)
[*] 00000088 SystemErr     R    at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.ModuleRefImpl.initModuleFileFromEAR(ModuleRefImpl.java:167)
[*] 00000088 SystemErr     R    at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.ModuleRefImpl.getModuleFile(ModuleRefImpl.java:120)
[*] 00000088 SystemErr     R    at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.EARFileImpl.getModuleFile(EARFileImpl.java:165)
[*] 00000088 SystemErr     R    at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.EARFileImpl.getDeploymentDescriptor(EARFileImpl.java:817)
[*] 00000088 SystemErr     R    at org.eclipse.jst.j2ee.commonarchivecore.internal.impl.ModuleRefImpl.getDeploymentDescriptor(ModuleRefImpl.java:230)
[*] 00000088 SystemErr     R    ... 49 more

我使用Websphere测试环境v8.5.5.0

UPDATE:我怀疑也许压缩算法用来压缩耳朵文件可能是罪魁祸首,似乎我是对的;使用7zip解压缩和重新压缩ear文件导致部署工作正常,没有错误。

我使用gradle作为构建工具,它提供了自己的压缩归档机制。我尝试将entryCompression模式设置为ZipEntryCompression.STORED,但没有成功。

这使我想到一个新问题:

  1. 我如何控制ear文件的组装/压缩以符合Websphere的期望?

  2. gradle用什么方法压缩耳朵?

UPDATE 2:查看gradle源代码,我可以看到Zip实现使用ant的org.apache.tools.zip.ZipOutputStream(1.9.3)。以前有人在这个过程中遇到过困难吗?

UPDATE 3:我好像一直在转移注意力。我已经检查了应该正确部署的文件,并看到ear在ear的根(即app.ear!app/<root>)之上包含一个额外的文件夹级别。

假设与压缩算法无关,有人有什么想法吗?

UPDATE 4:好吧,我真的很接近了,在检查了一些示例ear文件并测试了各种理论之后,我设法让部署工作。我做了这些事情,它起作用了(见更新5)。

  • 在application.xml中我使用ejb模块代替java模块。
  • 我在core.jar中包含了一个基本的META-INF/ejb-jar.xml文件(尽管规范说你不需要它们),因为websphere显然不喜欢它缺少
  • 我从application.xml中删除了core-api.jar模块

所以我现在有以下application.xml:

<?xml version="1.0"?>
<application ...>
  <application-name>MyApp</application-name>
  <display-name>My App</display-name>
  <module id="mod 1">
    <ejb>core.jar</ejb>
  </module>
  <module id="mod 2">
    <web>
      <web-uri>web.war</web-uri>
      <context-root>/</context-root>
    </web>
  </module>
  <library-directory>lib</library-directory>
</application>

最后一个问题:如何将工件"部署"到ear项目而不将其添加到应用程序xml中?或者,在解决部署问题之后,如何自定义application.xml ?

UPDATE 5:为我的问题的波动状态道歉。

虽然应用程序成功部署,但它没有启动,给了我一个错误,说我的ejb jar没有ejb。我已经决定,根据我收到的建议和下面的答案,我的基于spring的jar被归类为"实用程序"jar,应该放在lib文件夹中。

我希望将来在ejb中使用这些jar,因此希望将它们保存在lib文件夹中,而不是直接保存在war中。

这是我的最终应用程序。xml:

<?xml version="1.0"?>
<application ...>
  <application-name>MyApp</application-name>
  <display-name>My App</display-name>
  <module>
    <web>
      <web-uri>web.war</web-uri>
      <context-root>/</context-root>
    </web>
  </module>
  <library-directory>lib</library-directory>
</application>

感谢您的时间和耐心。

我可以从application.xml头中看到您正在使用JavaEE 6打包,并且您还提到您正在使用WebSphere 8.5.5,因此请遵循一些ear打包信息。

如果使用带注释的EJB 3,则根本不需要application.xml。X,然后遵循标准包装约定:

app.ear
|-- lib/$UTILITY_JARS_HERE
|-- EJB.jars
|-- web.war

请注意,这是Java EE 6结构的默认打包,在此之后,您放置在lib目录中的所有实用程序jar将对ejb和war都可用,因此只有当ejb和web应用程序都需要实用程序jar时,您才应该使用该目录。如果你的实用程序jar只被你的web应用程序使用,那么你应该把它们打包到war包中的标准web - inf/lib文件夹中。

现在,如果您正在使用ejb。除了application.xml和声明ejb和war之外,您应该保持推荐的方法,将utilities jar放在lib文件夹中,而仅由web层需要的工具放在war包的lib文件夹中。

如果出于任何原因你想把你的utilities jar保存在根目录或ear目录,你可以使用在ear目录的Manifest中声明它们的方法,但是你不能在war包的Manifest中再次声明它们。war文件和ejb的类加载器将自动看到ear清单中声明的所有jar。

javaEE 6规范第8章"应用程序组装和部署";对这个问题有完整的解释。你可在此下载文件

最新更新