我有一个很大的问题就是获取正确的实例或者至少将我使用JNDI查找的实例转换为正确的Web Sphere Liberty接口(16.0.0.4,在Java 7上运行,尽管使用的是Oracle Java 1.8.0_45)后面,在Eclipse Neon.2上开发。)
当我启动服务器和包含EJB的ear时,我会在日志中收到以下通知:
服务器在xxx-ear应用程序的xxx-ejb.jar模块中绑定MyEJB企业bean的xxx.interfaces.MyLocal接口。绑定位置是:java:global / xxx / MyEJB!xxx.interfaces.MyLocal
然后我有一个Web应用程序(ear),它有一个服务提供程序(带有 @Produces ),用于以前启动的ejb-service,它将JNDI资源提供为可注入的( @为应用程序的其余部分注入)(有点棘手的事情,主要的想法是允许从配置文件中更改查找位置+还要执行其他一些操作)。它似乎可以正常工作,但是当获得JNDI资源时,它有点工作但不正确。
如果我将ejb部分作为依赖项放入我的web模块,我可以直接注入它( @Inject MyLocal myEjb; )。
作为注入资源,我得到一个带签名的对象:
EJSMyLocal0SLMyEJB_a4549339 @ cc5d2cdd
使用查找我得到一个带签名的对象(与注入同时):
EJSMyLocal0SLMyEJB_a4549339 @ cdda36a7
(不是同一个实例afaik,但“类型”是正确的吗?)
注入的资源在“MyLocal”界面上正确(当然是自动)投射并且没问题。
当我尝试检查使用JNDI获取的资源时,它不符合“MyLocal”的实例或“MyRemote”的条件?实际的转换当然也失败了ClassCastException。 (MyRemote与MyLocal接口基本相同... MyLocal扩展MyRemote ,两个接口都相应地用 @Local 和 @Remote 注释
在测试时,EJB看起来像这样......
@Stateless
@Named
@Default
@Local(MyLocal.class)
@Remote(MyRemote.class)
public class MyEJB implements MyLocal, MyRemote { ... }
我也试图像这样投射JNDI资源。
InitialContext ic = new InitialContext();
Object lookedUpEjb = ic.lookup(lookup); // the 'java:global...' from log
MyRemote jndiEjb = (MyRemote) PortableRemoteObject.narrow(lookedUpEjb, MyRemote.class)
// Tried also casting/checking 'instanceof' to MyLocal...
没有区别,发生相同的ClassCastException?!
我在server.xml中有以下功能
<featureManager>
<feature>javaee-7.0</feature>
<feature>ldapRegistry-3.0</feature>
<feature>localConnector-1.0</feature>
<feature>adminCenter-1.0</feature>
<feature>wsSecurity-1.1</feature>
<feature>ejbLite-3.2</feature>
<feature>ejbRemote-3.2</feature>
<feature>cdi-1.2</feature>
<feature>jpa-2.1</feature>
<feature>jsf-2.2</feature>
<feature>jaxrs-2.0</feature>
<feature>jaxws-2.2</feature>
</featureManager>
我在Liberty JNDI功能上找到了这个文档: https://www.ibm.com/support/knowledgecenter/SSAW57_liberty/com.ibm.websphere.wlp.nd.multiplatform.doc/ae/twlp_ejb_remote.html
我看不出哪里出错了。如何将该对象从JNDI查找转换为MyLocal或MyRemote接口?
----注意----
使用 @EJB 注释不是一个选项(它可以工作),因为它将是对资源的硬编码引用。我希望它是可选的,因此JNDI查找。当资源不可用时, @EJB 将导致应用程序崩溃。
答案 0 :(得分:1)
问题是每个应用程序都有一个不同的ClassLoader,并且绑定到JNDI的对象是使用定义EJB的应用程序的ClassLoader加载的。
对于远程EJB接口,这不应该是一个问题,因为ORB应该为您处理这个问题。在返回此类对象的远程调用中,ORB将序列化对象(从目标ClassLoader),然后使用客户端ClassLoader反序列化。对于这样的查找,PortableRemoteObject.narrow也应该处理这个问题。这里的失败似乎只是ORB中的一个错误。
为了支持对本地EJB接口的跨应用程序访问,需要将本地EJB接口移动到两个应用程序使用的共享库,或者配置为使用单个全局ClassLoader的两个应用程序。有关跨应用程序使用本地EJB接口的更多信息,请参阅此链接:Correct way to lookup local EJB in websphere - Getting ClassCastException(注意:此链接正在讨论传统的WebSphere,但问题与Liberty相同,以及为接口使用共享库的解决方案)。