最佳实践:用 java:comp 来定位 EJB 并提高应用程序的可移植性 | 英文原文 | ||
读者:管理员,体系结构设计师,开发者 产品:WebSphere Studio Application Developer 版本:4.0.x 平台:Linux,Windows NT,Windows 2000,Windows 98,Windows XP 产品:WebSphere Application Server 版本:4.0.x 平台:OS/390,zSeries,AIX,Windows NT,Windows 2000,Linux,HP-UX,Solaris 关键字:JNDI,ejb-ref,java:comp/env,portability,可移植性 主题:基于组件的开发,配置和管理,体系结构,安装与规划,调试-测试-问题诊断,部署应用程序,EJB 摘要如果您把同一个 J2EE 应用程序部署到多个应用程序服务器上,而这些应用程序服务器共享一个 JNDI 名称空间,那么,由于名称空间中的 JNDI 名称必须是唯一的,这样做将会出现问题。部署到 WebSphere Application Server 环境中的 J2EE 应用程序,应该使用 java:comp/env 环境命名上下文(environment naming context(ENC))来查找 EJB,而不是使用 JNDI 名称来查找。有了这个命名上下文,就可以避免发生冲突,应用程序的可移植性也将好得多。 推荐方案背景开发和部署按照 EJB 1.0 规范级别编写的 EJB,困难之一是处理 EJB home 的 JNDI 名称。例如,有很多代码写成像下面的代码片段(取自会话 bean)那样,试图查找 com.ibm.wsc.Bean2 EJB 的 home: Context myInitCtx = new InitialContext();Object result = myInitCtx.lookup("com/ibm/wsc/Bean2Home");com.ibm.wsc.Bean2Home theBean2Home =(com.ibm.wsc.Bean2Home)javax.rmi.PortableRemote.narrow(result,com.ibm.wsc.Bean2Home.class); 这一技术在 Java 开发环境(Java development tooling,JDT)中能工作得很好,在应用程序的部署阶段似乎也不出什么问题。只要看一下上面的代码,就可以确定在名称空间中赋给 Bean2Home 的 JNDI 名称,因为这个名称就是 EJB Home 接口名称。编码约定就跟 EJB 类名被用来构造定位 home 的代码那样相当简单。 当把“Bean2”部署到使用同一个(共享的) JNDI 名称空间的两个不同服务器中时,问题就冒出来了。 例如,有人可能有两台服务器,WSQASV 和 WSFXSV,它们共享同一个名称空间(即 LDAP 或 CosNaming 服务器),并且他想把同一个 J2EE 应用程序(即 .ear 文件)部署到这两台服务器中。由于每台服务器中的会话 bean 都必须查找/使用 Bean2Home 的正确实例,所以,这就出现了一个问题。要避免这个问题,必须做两件事:
EJB 的命名模式已经开发,以硬编码的方式把 JNDI 名称编写到 java 源代码中是问题的真正起因。我们需要这样一种能力,不必根据部署了 EJB 的服务器修改代码就能够提供特定于运行时的信息。结果是创建并实现一个模式,它利用 ResourceBundle 或 Property 文件提供运行时信息,如以下代码片段所示: ResourceBundle myRB = ResourceBundle.getBundle("ServerProps");String myBean2HomeJNDIName = myRB.getString("Bean2HomeName")Context myInitCtx = new InitialContext();Object result = myInitCtx.lookup(myBean2HomeJNDIName);com.ibm.wsc.Bean2Home theBean2Home =(com.ibm.wsc.Bean2Home)javax.rmi.PortableRemote.narrow(result,com.ibm.wsc.Bean2Home.class); 这一技术的全部要求就是为 WSQASV 服务器创建一个唯一的名为 ServerProps.properties 的 .properties 文件,WSQASV 服务器的这个文件包含有类似下面的内容:Bean2HomeName=WSQASV/com/ibm/wsc/Bean2Home WSFXSV 的 ServerProps.properties 文件包含有类似这样的内容:Bean2HomeName=WSFXSV/com/ibm/wsc/Bean2Home 现在,我们有了一个模式,不管将 J2EE 应用程序部署到两台服务器中的哪一台,这个模式都不要求在部署之前对 java 代码作丝毫更改,EJB home 的命名约定得到了一定程度的保护,但受服务器限定。这个“服务器名”限定使得在任一台服务器中都可以正确定位 Bean2Home。在部署阶段,部署者只需要知道 .properties 文件的内容,以将正确的 JNDI 名指定给 EJB。 采用这种技术,只有一个问题还留待部署者去解决:如何管理特定于服务器的 .properties 文件。让人左右为难的是,.properties 文件既是特定于应用程序的(即应用程序中所包含的特定 EJB home 正在被查找),又是特定于服务器的(即 EJB home 的 JNDI 名称取决于安装了该应用程序的服务器)。问题是:ServerProps.properties 文件是在 J2EE 应用程序包(即 .ear 文件)中呢,还是在服务器的类路径中?把 .properties 文件放到 .ear 文件意味着 .ear 文件在部署到上述两台服务器之前必须先作修改。人们不希望这样做,原因与人们不希望修改 java 源代码的原因如出一辙。不过,人们倒是很希望有一个各个部件的单个包,而不必为特定于应用程序的文件具体配置服务器。 EJB 1.1 解决方案幸运的是,EJB 1.1 规范引入了 JNDI 增强功能,特别是环境命名上下文(ENC)以及关于如何“找到” EJB、资源和特定于应用程序的环境变量的强烈推荐的做法。要了解详细信息,请参阅 EJB 1.1 规范的第 14 章和 J2EE 1.2 规范的第 5 章。以下代码片段使用所推荐的 java:comp/env 构造来查找 Bean2Home: Context myInitCtx = new InitialContext();Object result = myInitCtx.lookup("java:comp/env/ejb/Bean2Home");com.ibm.wsc.Bean2Home theBean2Home =(com.ibm.wsc.Bean2Home) javax.rmi.PortableRemote.narrow(result,com.ibm.wsc.Bean2Home.class); 如何把“java:comp/env/ejb/Bean2Home”字符串和驻留在某台特定服务器中的 Bean2Home 的 JNDI 名称关联起来,这项工作留给应用程序的装配者和部署者去做。应用程序开发者既不知道也不关心 Bean2Home 的 JNDI 名称。 特别地,装配者必须在引用 EJB 的 ejb-jar.xml 文件(或者是引用 servlet 的 web.xml 文件)中包含一条带有以下内容的子句: <ejb-ref> <ejb-ref-name>ejb/Bean2Home</ejb-ref-name> <ejb-ref-type>Entity</ejb-ref-type> <home>com.ibm.wsc.Bean2Home</home> <remote>com.ibm.wsc.Bean2</remote> <ejb-link>Bean2</ejb-link></ejb-ref> .xml 文件的内容通常由开发工具(即 WebSphere Studio Application Developer)或装配工具(即应用程序装配工具(Application Assembly tool(AAT)))构建和验证,不要求手工构造。请注意,没有给出 JNDI 名称,只有一条声明,表明这个 EJB(或 servlet)将查找一个给定类型的 EJB home,并且该 EJB home 驻留在这个 J2EE 应用程序包即 .ear 文件中。(如果省略了 ejb-link 描述符,servlet 或 EJB 就可以查找并使用驻留在 JNDI 名称空间中具有这一 bean 类型的任何服务器中所驻留的 Bean2Home。)实际上,应用程序装配者并不知道也不关心 Bean2Home 的 JNDI 名称。JNDI 名称留给部署者指定,其限制条件是,不论 J2EE 应用程序被部署到什么服务器中,Bean2Home 都必须驻留在该 J2EE 应用程序中。 在把应用程序安装/部署到某一特定服务器(例如,在我们的示例中,是 WSQAEV 或 WSFXSV 服务器)中时,部署者必须做两件事:
要点是:
这一技术大大增强了 EJB 的可移植性。很容易就可以部署应用程序,而不必为实际的 JNDI 名称劳心费神。可以从一个 J2EE 应用程序抽取出 EJB,然后很容易就可以将它集成到另一个 J2EE 应用程序中。 剩下的问题是:部署者应选择什么样的 JNDI 名称?要求是:
用于 WebSphere for z/OS 的 Systems Management Administration 工具允许部署者指定特选的 JNDI 名称,如果部署者选择这样做,或者应用程序要求这样做的话。当不使用 java:comp/env 技术进行 lookup( ) 的时候就会出现这种情况。更为重要的是,该管理工具允许部署者指定一个系统生成的名称,这样生成的名称必定是唯一的。名称的格式如下:<sysplex_name>/<server_name>/<application_name>/<module_name>/<component_name>/<class_name> 因此,如果 Bean2 驻留在 EntityBeans.jar 文件中,并且所有的 J2EE 组件都被打包到 BeanSalad.ear 中,.ear 文件将被部署到 WSFXSV 服务器中,这台服务器又在与 WSCPLEX sysplex 相关联的 WebSphere 节点/群集上,那么,所生成的名称将是: WSCPLEX/WSFXSV/BeanSalad/EntityBeans/Bean2/com.ibm.wsc.Bean2Home.class 这个名称唯一地标识了驻留在位于节点 WSCPLEX 的 WSFXSV 服务器中的 Bean2Home,对比于驻留在位于这个节点的 WSQASV 服务器中的 Bean2Home。 通过使用这一技术,我们实现了自管理的 JNDI 名称唯一性,这不为应用程序所知,并且应用程序的可移植性达到了 .ear 文件部署级别(既不需要对代码或部署描述符作修改,也不需要额外的副文件)。 备选方案使用 java:comp/env 的唯一备选方案是继续使用以前讨论的 EJB 1.0 技术。尽管该技术仍然行得通,但使用前面推荐的方案可以解决许多技术问题。 参考资料
作者简介
|