Java EE:代理无法转换为本地接口,也许是类加载问题?

时间:2011-11-01 23:02:12

标签: java-ee ejb-3.0 classloader

我目前正在“重新安排”我的Java EE应用程序,它由三个组件组成:

  • MyAppInterface:主要是JPA和JAXB注释的POJO,也是一些EJB本地接口
  • MyAppServer:JPA Facades,EJBs,Jersey资源
  • MyAppWeb:GWT前端,通过HTTP / REST通过loadbalancer与MyAppServer通信

MyAppServer和MyAppWeb都使用MyAppInterface中定义的类; MyAppServer通过MyAppInterface中的本地接口“导出”其部分EJB。 MyAppInterface是一种API,它是您使用MyAppServer所需要的。

在Maven中我将MyAppInterface打包为jar,MyAppServer和MyAppWeb都打包为war,依赖于compile范围内的MyAppInterface。所以MyAppInterface.jar最终都出现在两个war文件中。

当我将两个war文件作为单独的应用程序部署在同一Glassfish上时,部署成功。它们之间的JAXB-Jersey驱动的通信工作,所以我必须假设两个应用程序都可以加载MyAppInterface。

但在一个案例中,我想从MyAppWeb访问MyAppServer-EJB。通过InitialContext进行的JNDI查找有效,但是当我尝试将获得的代理强制转换为本地接口时,我得到了一个ClassCast异常:

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的重复包含有关。那是对的吗?你有什么建议吗?

您如何分发和打包组件?

注意:目前我想避免创建EAR,而是保持灵活选择要部署的组件......

1 个答案:

答案 0 :(得分:1)

是的,对于本地EJB,接口JAR需要位于用于类加载的共享位置。 EJB规范实际上不需要跨应用程序(或独立模块)访问本地EJB,但大多数应用程序服务器使用简单代理实现本地EJB。

您需要在EAR中将模块打包到lib目录中的JAR,或者您需要安排JAR由两个应用程序都可见的产品级类加载器加载。