如何在Liberty

时间:2017-03-13 06:42:16

标签: jndi websphere-liberty

我有一个很大的问题就是获取正确的实例或者至少将我使用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 将导致应用程序崩溃。

1 个答案:

答案 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相同,以及为接口使用共享库的解决方案)。