将 Enterprise JavaBeans 与 Liberty 上的远程接口配合使用
如果 EJB 由另一 Java 虚拟机 (JVM) 或同一 JVM 内的另一应用程序托管,那么您可通过远程接口远程访问 Enterprise Java™ Bean (EJB) 方法。WebSphere® Application Server 使用 RMI-IIOP 技术实现远程 EJB 接口。可使用 ejbRemote-3.2 功能部件启用远程 EJB 支持。
关于此任务
要配置 Liberty 服务器以运行已启用远程 EJB 支持的应用程序,必须设置 ejbRemote-3.2 功能部件。
使用远程 EJB 接口时,查看以下注意事项:
- 命名
使用 java: namespace
EJB 规范要求远程接口绑定至 java: 名称空间;例如:java:global/ExampleApp/ExampleModule/ExampleBean!com.ibm.example.ExampleRemoteInterface java:app/ExampleModule/ExampleBean!com.ibm.example.ExampleRemoteInterface java:module/ExampleBean!com.ibm.example.ExampleRemoteInterface
EJB 组件未像在 WebSphere® Application Server 传统版中一样绑定至缺省 Java 命名和目录接口 (JNDI) 名称空间,所以 ibm-*-bnd.xml 文件中的 @EJB 查找和绑定不能使用此名称空间。对于同一服务器内的 EJB 组件,这些查找必须使用 java: 名称,对于另一服务器中的 EJB 组件,这些查找必须使用 corbaname: URL。
- 使用 corbaname: URL这些接口还会绑定至 java:global 名称空间中所使用接口的类似上下文中的 ORB CosNaming 名称服务。通过使用 corbaname: URL,可借助 JNDI 访问这些接口;例如:
corbaname::test.ibm.com:2809#ejb/global/ExampleApp/ExampleModule/ExampleHomeBean!com.ibm.example.ExampleEJBHomecorbaname:rir:#ejb/global/ExampleApp/ExampleModule/ExampleHomeBean!com.ibm.example.ExampleEJBHome
在服务器上,URL 的 rir: 形式使用本地名称服务。在客户机上,它使用缺省的或已配置的远程名称服务。
- 对 corbaname: URL 进行转义
根据对象管理组 (OMG) 命名服务规范,corbaname: URL 中的一些字符必须转义。Liberty 尝试确定从 java:global 名称空间派生的 corbaname: URL 是否需要转义,然后自动进行转义。不能在所有情况下进行转义。例如,如果名称包含单个点 (.) 并且没有无效字符,那么它不能自动转义。要强制以特定方式解释名称,需要按 OMG 命名服务规范中所述手动对 URL 转义。
对于企业 bean,考虑以下 java:global 名称:
corbaname: URL 的简单形式不能自动转义,因为它表示不同但有效的位置。因此,以下 URL 不会按预期工作:java:global/TestApp/TestModule/TestBean!test.TestRemoteInterface
反而必须按以下方式对此 URL 进行手动转义:corbaname:rir:#ejb/global/TestApp/TestModule/TestBean!test.TestRemoteInterface
corbaname:rir:#ejb/global/TestApp/TestModule/TestBean!test%5c.TestRemoteInterface
OMG 命名服务规范中完整描述了用于对 corbaname: URL 进行转义的语法。
- 通过程序使用 JNDI 名称可通过程序从 InitialContext 查找这些示例中的所有 URL 和 JNDI 名称。查找 java: 名称时,产生的对象可直接转型为预期类型;例如:
但是,使用 corbaname: URL 检索对象时,必须使用 RMI 样式的强制类型转换(称为收缩);例如:Object found = new InitialContext().lookup("java:global/ExampleApp/ExampleModule/ExampleBean!com.ibm.example.ExampleRemoteInterface"); ExampleRemoteInterface bean = (ExampleRemoteInterface) found;
Object found = new InitialContext().lookup("corbaname:rir:#ejb/global/ExampleApp/ExampleModule/ExampleBean!com.ibm.example.ExampleRemoteInterface"); ExampleRemoteInterface bean = (ExampleRemoteInterface)PortableRemoteObject.narrow(found, ExampleRemoteInterface.class);
- 互操作性
- 打包在带有 V2.0 部署描述符的 EJB JAR 模块中时,支持 IIOP 协议的任何产品可调用一些企业 bean,这些企业 bean 将 EJB 2.x 远程编程模型与 EJBHome 和 EJBObject 配合使用。WLP_INSTALL_DIR/clients/ejbRemotePortable.jar 文件必须包含在远程客户机的类路径上。此文件包含与 Liberty 服务器通信时所需的系统值类。从 WebSphere Application Server Liberty 或 WebSphere Application Server 传统版 中远程访问 EJB 组件时,此文件不是必需的。在 Liberty 上使用 EJB 3 远程编程模型的 EJB 组件可供 WebSphere Application Server 进程远程访问。Liberty 未提供用于从独立 Java 进程启动 EJB 组件的瘦客户机。Liberty 未对远程 EJB 组件提供工作负载管理或故障转移功能,包括您启动 WebSphere Application Server 传统版中的 EJB 组件时。
- 存根类
- 启动 WebSphere Application Server 上的远程 EJB 时,客户机必须包括存根类。在某些情况下,如果客户机为
WebSphere Application Server,那么该产品自动生成正确的存根类:
- 如果客户机应用程序启动包含在同一应用程序内的远程 EJB,那么 Liberty 自动生成存根类。
- 如果目标 EJB 在另一应用程序上运行,并且将 EJB 2.x 远程编程模型与 EJBHome 和 EJBObject 配合使用,那么客户机的类路径上必须包含存根类。如果 EJB 在 WebSphere Application Server 传统版上,那么可在 ejbdeploy 命令处理 EAR 后从该 EAR 中的应用程序复制 EJB 客户机 JAR。如果 EJB 在 WebSphere Application Server Liberty 上托管,那么必须使用 Java SDK 附带的 rmic 程序为目标 EJB 生成存根类,然后必须对客户机包含这些存根类。
- 如果目标 EJB 在另一应用程序上运行,并且正在使用 EJB 3 远程编程模型,那么客户机 WebSphere Application Server Liberty 或 WebSphere Application Server 传统版进程自动生成存根类。在 Liberty 上使用 EJB 3 远程编程模型的 EJB 组件只能由 WebSphere Application Server 或 WebSphere Application Client 进程远程访问。
- 事务传播
- Liberty 不支持出站或入站事务传播。此外,EJB 规范要求即使产品支持出站事务传播时,它仍然必须发送一个空事务上下文。此上下文必须被使用 Required(缺省)、Mandatory 或 Supports 事务属性的 EJB 组件拒绝。如果客户机或服务器在 Liberty 中,那么带有活动全局事务的客户机不能启动带有缺省事务属性的 EJB。如果 EJB 更改为使用 RequiresNew 或 NotSupported 事务属性,那么客户机可启动 EJB。但是,EJB 完成的事务性工作不会作为客户机事务的一部分落实。
- 异步方法
- EJB 远程接口可以有类型为 Future 的返回值的异步方法。服务器会将 Future
对象返回至客户机,用于检索该值。建议不要使用远程异步方法,因为未声明结果的累积可能耗尽内存。为了缓解此问题,如果客户机在 24 小时内未检索结果或最大未声明结果数超过 1000,那么服务器结果将到期。可在 server.xml
文件中调整这些值;例如:
<ejbContainer> <async maxUnclaimedRemoteResults="10"unclaimedRemoteResultTimeout="10m"/> </ejbContainer>