如何在 Liberty 中正确获取和转换 JNDI 对象
How to get and cast JNDI object correctly in Liberty
我在获取正确的实例或至少将我通过 JNDI 查找获得的实例转换为正确的 Web Sphere Liberty 接口(16.0.0.4,运行 on Java 时遇到了很大的问题7,后面虽然用的是Oracle Java 1.8.0_45,在Eclipse Neon.2).
上开发
当我启动服务器和包含 EJB 的 ear 时,我在日志中收到以下通知:
The server is binding the xxx.interfaces.MyLocal interface of the MyEJB enterprise bean in the xxx-ejb.jar module of the xxx-ear application. The binding location is: java:global/xxx/MyEJB!xxx.interfaces.MyLocal
然后我有一个 Web 应用程序 (ear),它有一个服务提供者(@Produces)用于先前启动的 ejb 服务,它将提供 JNDI 资源作为可注入的(@Inject) 对于应用程序的其余部分(有点棘手,主要思想是允许从配置文件更改查找位置 + 做一些其他事情)。它似乎可以正常工作,但在获取 JNDI 资源时,它可以正常工作,但不正确。
如果我将 ejb 部分作为依赖项放入我的 web 模块中,我可以直接注入它 (@Inject MyLocal myEjb;)。
作为注入的资源,我得到一个带有签名的对象:
EJSMyLocal0SLMyEJB_a4549339@cc5d2cdd
通过查找,我得到了一个带有签名的对象(与注入同时):
EJSMyLocal0SLMyEJB_a4549339@cdda36a7
(不是同一个实例 afaik,但是 "type" 是正确的吗?)
注入的资源正确地(当然是自动地)在 'MyLocal' 接口上投射并且没问题。
当我尝试检查通过 JNDI 获得的资源时,它既不符合 'MyLocal' 的实例也不符合 'MyRemote' 的条件?实际演员表当然也会因 ClassCastException 而失败。 (MyRemote 与 MyLocal 接口基本相同...... MyLocal extends 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 资源不可用时会导致应用程序崩溃。
问题是每个应用程序都有不同的 ClassLoader,绑定到 JNDI 的对象是用定义 EJB 的应用程序的 ClassLoader 加载的。
对于远程 EJB 接口来说,这应该不是问题,因为 ORB 应该已经为您解决了这个问题。在远程调用 returns 这样的对象时,ORB 将序列化该对象(来自目标 ClassLoader),然后使用客户端 ClassLoader 反序列化。对于这样的查找,PortableRemoteObject.narrow 也应该处理这个问题。这里的失败似乎只是 ORB 中的错误。
为了支持对本地 EJB 接口的跨应用程序访问,需要将本地 EJB 接口移动到共享库,供两个应用程序使用,或者两个应用程序都配置为使用单个全局类加载器。有关跨应用程序使用本地 EJB 接口的更多信息,请参阅此 link:(注意:此 link 正在讨论传统的 WebSphere,但问题与 Liberty 相同,解决方案也是如此为界面使用共享库)。
我在获取正确的实例或至少将我通过 JNDI 查找获得的实例转换为正确的 Web Sphere Liberty 接口(16.0.0.4,运行 on Java 时遇到了很大的问题7,后面虽然用的是Oracle Java 1.8.0_45,在Eclipse Neon.2).
上开发当我启动服务器和包含 EJB 的 ear 时,我在日志中收到以下通知:
The server is binding the xxx.interfaces.MyLocal interface of the MyEJB enterprise bean in the xxx-ejb.jar module of the xxx-ear application. The binding location is: java:global/xxx/MyEJB!xxx.interfaces.MyLocal
然后我有一个 Web 应用程序 (ear),它有一个服务提供者(@Produces)用于先前启动的 ejb 服务,它将提供 JNDI 资源作为可注入的(@Inject) 对于应用程序的其余部分(有点棘手,主要思想是允许从配置文件更改查找位置 + 做一些其他事情)。它似乎可以正常工作,但在获取 JNDI 资源时,它可以正常工作,但不正确。
如果我将 ejb 部分作为依赖项放入我的 web 模块中,我可以直接注入它 (@Inject MyLocal myEjb;)。
作为注入的资源,我得到一个带有签名的对象:
EJSMyLocal0SLMyEJB_a4549339@cc5d2cdd
通过查找,我得到了一个带有签名的对象(与注入同时):
EJSMyLocal0SLMyEJB_a4549339@cdda36a7
(不是同一个实例 afaik,但是 "type" 是正确的吗?)
注入的资源正确地(当然是自动地)在 'MyLocal' 接口上投射并且没问题。
当我尝试检查通过 JNDI 获得的资源时,它既不符合 'MyLocal' 的实例也不符合 'MyRemote' 的条件?实际演员表当然也会因 ClassCastException 而失败。 (MyRemote 与 MyLocal 接口基本相同...... MyLocal extends 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 资源不可用时会导致应用程序崩溃。
问题是每个应用程序都有不同的 ClassLoader,绑定到 JNDI 的对象是用定义 EJB 的应用程序的 ClassLoader 加载的。
对于远程 EJB 接口来说,这应该不是问题,因为 ORB 应该已经为您解决了这个问题。在远程调用 returns 这样的对象时,ORB 将序列化该对象(来自目标 ClassLoader),然后使用客户端 ClassLoader 反序列化。对于这样的查找,PortableRemoteObject.narrow 也应该处理这个问题。这里的失败似乎只是 ORB 中的错误。
为了支持对本地 EJB 接口的跨应用程序访问,需要将本地 EJB 接口移动到共享库,供两个应用程序使用,或者两个应用程序都配置为使用单个全局类加载器。有关跨应用程序使用本地 EJB 接口的更多信息,请参阅此 link: