问题描述
我目前正在重新安排我的Java EE应用程序,它包含三个组件:
I'm currently "rearranging" my Java EE application, which consists of three components:
- MyAppInterface:主要是JPA-和JAXB -annotated POJO,也是一些EJB本地接口
- MyAppServer:JPA Facades,EJBs,Jersey资源
- MyAppWeb:GWT前端,通过HTTP与MyAppServer通信/ REST via loadbalancer
MyAppServer和MyAppWeb都使用MyAppInterface中定义的类; MyAppServer通过MyAppInterface中的本地接口导出其部分EJB。 MyAppInterface是一种API,它是您使用MyAppServer所需的。
Both MyAppServer and MyAppWeb use the classes defined in MyAppInterface; MyAppServer "exports" some of its EJBs via local interfaces in MyAppInterface. MyAppInterface is kind of the API, it's what you need to work with MyAppServer.
在Maven我将MyAppInterface打包为 jar
,MyAppServer和MyAppWeb都打包为 war
,并且在 compile
范围内依赖于MyAppInterface。所以MyAppInterface.jar最终都出现在两个war文件中。
In Maven I am packaging MyAppInterface as jar
, both MyAppServer and MyAppWeb are packaged as war
with a dependency on MyAppInterface in a compile
scope. So MyAppInterface.jar ends up in both war-files.
当我在同一个Glassfish上将两个war文件作为单独的应用程序部署时,部署成功。它们之间的JAXB-Jersey驱动的通信工作,所以我必须假设两个应用程序都可以加载MyAppInterface。
When I deploy both war-files as separate applications on the same Glassfish, deployment is successful. The JAXB-Jersey-powered communication between them works, so I have to assume that both applications can classload MyAppInterface.
但在一个案例中,我想访问一个来自MyAppWeb的MyAppServer-EJB。通过 InitialContext
进行JNDI查找有效,但是当我尝试将获取的代理强制转换为本地接口时,我得到了一个ClassCast异常:
But in one case, I'd like to access a MyAppServer-EJB from MyAppWeb. The JNDI-lookup via InitialContext
works, but when I try to cast the obtained proxy to the local interface, I get a ClassCast exception:
com.sun.enterprise.container.common.spi.util.InjectionException: Error creating managed object for class: class com.skalio.bonusapp.web.server.StoreServiceImpl
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:315)
at com.sun.enterprise.web.WebContainer.createServletInstance(WebContainer.java:717)
at com.sun.enterprise.web.WebModule.createServletInstance(WebModule.java:1959)
...
Caused by: java.lang.reflect.InvocationTargetException
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.createManagedObject(InjectionManagerImpl.java:307)
... 28 more
Caused by: java.lang.ClassCastException: $Proxy365 cannot be cast to com.skalio.bonusapp.beans.SettingsBeanLocal
at com.skalio.bonusapp.web.server.StoreServiceImpl.getServerSettings(StoreServiceImpl.java:85)
at com.skalio.bonusapp.web.server.StoreServiceImpl.(StoreServiceImpl.java:47)
... 33 more
Google让我相信这可能是一个类加载问题,可能与MyAppInterface.jar的重复包含有关。那是对的吗?您建议做什么?
Google makes me believe that this could be a classloading issue, possibly related to the the duplicate inclusion of MyAppInterface.jar. Is that correct? What do you suggest to do?
您如何分发和包装组件?
How would you distribute and package the components?
注意:在我想避免创建EAR,而是保持灵活选择要部署的组件......
Note: At the moment I'd like to avoid creating an EAR and rather keep flexibility of choosing what components to deploy where...
推荐答案
是对于本地EJB,接口JAR需要位于用于类加载的共享位置。 EJB规范实际上不需要跨应用程序(或独立模块)访问本地EJB,但大多数应用程序服务器使用简单代理实现本地EJB。
Yes, for local EJB, the interface JAR needs to be in a shared location for class loading. The EJB spec actually doesn't require local EJBs to be accessible across applications (or standalone modules), but most application servers implement local EJB with simple proxies.
您需要使用lib目录中的JAR将模块打包到EAR中,或者需要安排JAR由两个应用程序都可见的产品级类加载器加载。
You either need to package your modules in an EAR with the JAR in the lib directory, or you need to arrange for the JAR to be loaded by a product-wide class loader that is visible to both applications.
这篇关于Java EE:代理无法转换为本地接口,也许是类加载问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!