从 Tomcat 调用 EJB 时出现 NoClassDefFoundError - 类在类路径上为 POJO
我有以下安排:
Tomcat --EJB-invokation--> JBoss
(6.0.14) (5.1.0)
两台服务器在同一台机器上运行。
当我运行 Tomcat web 应用程序时,我在 Tomcat 日志中收到以下错误:
2011-11-02 15:59:02,077 [http-9320-4] ERROR org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/frontend].[action]- "Servlet.service()" pour la servlet action a généré une exception
javax.ejb.EJBException: Unexpected Error
java.lang.NoClassDefFoundError: com/mycompany/app/transfer/internal/dto/account/AccountWithDemandDTO
at com.mycompany.app.back.services.ServiceImpl.findAccount(ServiceImpl.java:925)
at com.mycompany.app.back.services.ServiceImpl.findAccount(ServiceImpl.java:879)
at sun.reflect.GeneratedMethodAccessor2703.invoke(Unknown Source)
...
The class that is not being find made part of an Ear on JBoss :
applicationear.ear
- META-INF
- application.xml
- ...
- transfer-internal-dto-6.0.9.jar
- ...
application.xml
is made up of:
<?xml version="1.0" encoding="UTF-8" ?>
<application ...>
<display-name>myapp</display-name>
<module><ejb>backend-services-6.0.9.jar</ejb></module>
<module><java>transfer-internal-dto-6.0.9.jar</java></module>
...
</application>
Looking at在 JMX 控制台中,我可以看到这个 Jar 文件以及构成耳朵的其他 jar 文件已部署:
id="vfszip:/misc/JavaEE/package/myapp/back/6.0.9/deploy/applicationear.ear/transfer-internal-dto-6.0.9.jar/",type=SubDeployment
所以对我来说,该类存在于 JBoss 上。在 Tomcat 端,客户端应用程序部署为 war:
frontend.war
- WEB-INF
- lib
- transfer-internal-dto-6.0.9.jar
- ...
- META-INF
- MANIFEST.MF
清单中的 Class-Path
声明包括 lib/transfer-internal-dto-6.0.9.jar
。
我对问题可能是什么有点困惑 - 有人有什么想法吗?
一些有用的信息:
- Java 1.6.0_18
- 一切都使用 Maven 打包
- 应用程序使用 twiddle 部署在 JBoss 上 - 热部署被禁用
- 这发生在机器正常重新启动后 - 相同的应用程序在重新启动之前正在工作 - 应用程序已在重新启动之间没有被修改,
- DTO 对象是一个实现 Serialized 的 POJO - 该类的两个字段是其他 POJO(都实现 Serialized,都在同一个 jar 中)。这些辅助 POJO 之一引用了位于不同 .jar 中的两个枚举。此辅助 .jar 在 application.xml 和 MANIFEST.MF 文件中正确定义。此树中的 POJO 都没有静态初始化程序,也没有类似的实例化时间代码。
- 这种安排在我们的测试环境中运行良好
- JBoss 日志中没有任何内容
- 客户端是一个 Struts 应用程序
I have the following arrangement :
Tomcat --EJB-invokation--> JBoss
(6.0.14) (5.1.0)
The two servers are running on the same machine.
When I run the Tomcat webapp, I get the following error in the Tomcat logs:
2011-11-02 15:59:02,077 [http-9320-4] ERROR org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/frontend].[action]- "Servlet.service()" pour la servlet action a généré une exception
javax.ejb.EJBException: Unexpected Error
java.lang.NoClassDefFoundError: com/mycompany/app/transfer/internal/dto/account/AccountWithDemandDTO
at com.mycompany.app.back.services.ServiceImpl.findAccount(ServiceImpl.java:925)
at com.mycompany.app.back.services.ServiceImpl.findAccount(ServiceImpl.java:879)
at sun.reflect.GeneratedMethodAccessor2703.invoke(Unknown Source)
...
The class that is not being found makes up part of an ear on JBoss :
applicationear.ear
- META-INF
- application.xml
- ...
- transfer-internal-dto-6.0.9.jar
- ...
application.xml
is made up of:
<?xml version="1.0" encoding="UTF-8" ?>
<application ...>
<display-name>myapp</display-name>
<module><ejb>backend-services-6.0.9.jar</ejb></module>
<module><java>transfer-internal-dto-6.0.9.jar</java></module>
...
</application>
Looking at the JMX console, I can see that this Jar file is deployed, along with the other jars that make up the ear:
id="vfszip:/misc/JavaEE/package/myapp/back/6.0.9/deploy/applicationear.ear/transfer-internal-dto-6.0.9.jar/",type=SubDeployment
So for me the class is present on JBoss. On the Tomcat side, the client application is deployed as a war:
frontend.war
- WEB-INF
- lib
- transfer-internal-dto-6.0.9.jar
- ...
- META-INF
- MANIFEST.MF
The Class-Path
declaration in the manifest includes lib/transfer-internal-dto-6.0.9.jar
.
I'm a bit stuck as to what the problem might be - does anyone have any ideas?
A few useful bits of information:
- Java 1.6.0_18
- everything is packaged using Maven
- applications are deployed on JBoss using twiddle - hot deploy is disabled
- this happened after a graceful restart of the machine - the same application was working before the restart - the application has not been modified between the restarts
- the DTO object is a POJO that implements Serializable - two fields of the class are other POJOs (both implementing Serializable, both in the same jar). One of these secondary POJOs references two enums which are in a different .jar. This secondary .jar is correctly defined in application.xml and the MANIFEST.MF file. None of the POJOs in this tree has a static initializer nor similar instantiation-time code.
- this arrangement works fine on our test environment
- there is nothing in the JBoss logs
- the client side is a Struts app
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
最后,我观察了测试和生产环境中 JMX 控制台的差异,并注意到了一些差异。这是特别奇怪的,因为环境是被掌握的(即它们是从脚本创建的)并且应用程序也是从脚本部署的,并且一切都在计划关闭之前运行。因此,唯一可能的情况就是部署过程中出现了某种问题。
因此,我们重新启动了 JBoss 服务器,一切正常。
In the end I took at difference of the JMX consoles in our test and production environments and noticed some differences. This is particularly strange as the environments are mastered (ie they are created from scripts) and the applications are also deployed from scripts, and everything worked before the planned shutdown. Therefore the only thing that seemed possible was some kind of problem during the deployment.
We therefore restarted the JBoss server, and everything functioned correctly.