跳到导航
BEA Dev2Dev Oracle and BEA
首页 资源中心 dev2dev学堂 在线技术论坛 User Group CodeShare
dev2dev 首页 > 资源中心 > 技术文章
开发实体EJB 增强的性能和开发

时间:2004-06-01
作者:Ajay VohraDeepak Vohra
浏览次数:
本文关键字:EJB 实体Bean 性能 CMP BMP
文章工具
推荐给朋友 推荐给朋友
打印文章 打印文章

Enterprise JavaBean (EJB) 是一些应用程序组件,它们实现了 EJB 体系结构规范,并且是 Java 2 Enterprise Edition (J2EE) 平台的一部分。EJB 是开发和部署分布式的、可伸缩的、事务型的、安全的、可移植的、基于组件的商业应用的理想选择。

Enterprise JavaBean (EJB)一些应用程序组件,它们实现了EJB体系结构规范,并且是Java 2 Enterprise Edition (J2EE) 平台的一部分。EJB是开发和部署分布式的、可伸缩的、事务型的、安全的、可移植的、基于组件的商业应用的理想选择。

基于EJB的商业应用需要一个EJB容器,用于运行时的执行。所有遵从J2EE规范的应用服务器,包括WebLogic 8.1在内,都提供了EJB容器。

EJB体系结构背后的主要动机是关系的分离:它将与应用程序基础设施相关的部分(例如事务处理和安全性)与核心应用程序部分(例如业务逻辑)分离开来。简言之,EJB体系结构通过指定EJB容器与EJB开发者之间职责的区别,从而达到这种关系上的分离。例如,透明地实现事务处理是EJB容器的职责,而实现业务逻辑则应由EJB开发者负责。虽然EJB容器执行任务时可能需要某些线索(hint),但是,比起实际地实现这些与基础设施相关的活动来,提供这类线索(通过基于XML的部署描述符)的代价是非常少的。总之,这种关系分离的策略使得商业应用的开发比其他方式要高效得多。

EJB体系结构规范有4种版本:1.01.12.02.1。事实上,EJB version 1.0已经过时了,而最新版本,即2.1,由于刚刚才出现,所以还没有广泛提供。BEA WebLogic Server 8.1同时支持1.12.0这两种版本。我们强烈建议在WebLogic Server 8.1中进行开发时使用EJB version 2.0

实体bean是一种EJB。除了EJB背后的一般动机外,使用实体bean的特定动机是为持久存储中的业务域(business-domain)实体提供一种驻留在内存中的、可共享的、面向对象的视图。通常,业务域对象就是关系数据库中一个表里面的一行。在本文中,我们讨论了关于在WebLogic Server 8.1环境下Entity EJB的设计、开发和部署的特定问题。至于关于EJB技术的综合教程,我们推荐http://java.sun.com/j2ee上的J2EE教程。

概述
实体bean是设计用来管理关系数据库中的数据的。在BEA WebLogic Server 8.1环境下,Entity EJB的开发包括EJB的设计、生成、打包和部署。

从设计的角度来看,实体bean可以由两条正交轴线来分类:持久性和访问。顺着持久性这条轴线,有两种类型的实体beanBean管理的持久性(Bean-managed persistenceBMP)和容器管理的持久性(Container-managed persistenceCMP)。如果是CMP,则EJB容器将管理实体bean的持久性。而对于BMP,则由实体bean的开发者通过指定的Java代码来管理实体bean的持久性。CMPBMP之间的选择是互斥的。顺着访问这条轴线,又有两种类型的bean:远程的和本地的。远程实体bean提供了定位的透明性,并且可以从不同的Java虚拟机上访问。相反,本地实体bean只能在同一应用服务器内访问。本地和远程之间的选择不是互斥的,因此可以设计具有双重接口的bean

EJB体系结构规范中,每个实体EJB组件都是由一组指定的Java类和一组指定的XML部署描述符组成。EJB的打包过程包括将所有指定的EJB Java类文件和XML部署描述符文件打包到一个Java Archive (JAR)文件中。如果实体EJB还要依赖于一些Java助手类文件,那么也可以将这样的类文件包括到EJB JAR文件中,或者将它们单独打包到一个不同的JAR文件中。

EJB的部署可分为两种方式,要么是在BEA WebLogic Server 8.1内直接部署EJB JAR文件以及所依赖的任何JAR文件,要么是首先将EJB jar文件和所有依赖的JAR文件打包到一个企业应用归档(enterprise application archiveEAR)文件内,然后再在WebLogic Server 8.1内部署这个EAR文件。

设计EJB
在设计一个实体时,需要考虑的几个重要选择是:

  1. 是设计一个CMP实体bean还是一个BMP实体bean
  2. 是设计一个本地实体bean,还是设计一个远程实体bean,抑或是设计一个双重接口的实体bean
  3. 是设计一个粗粒度(coarse-grained)的实体bean,还是一个细粒度(fine-grained)的实体bean
  4. 是使用数据传输对象,还是使用getset方法来访问实体EJB中的数据。

下面将讨论在开发实体EJB时要面临的这些设计选择。

CMPBMP
记住,虽然可能存在一些很合理的例外,但是一般情况下我们强烈推荐使用CMP这种设计。至于为什么要选择CMP,而不是BMP,这里有三大主要原因。

  1. BMP相比,CMP提供了跨多种不同数据库的可移植性,因为CMP实体bean不包含任何特定于数据库的持久性代码。CMP易于设计、实现和维护。
  2. 通常,CMP拥有好于BMP的性能,因为EJB容器将自动生成特定于数据库的代码,并且这些代码将为目标数据库而优化。
  3. CMP通过使用本地接口,使得在相关EJB的网络中程序性地(programmatically)进行导航变得非常容易。

本地接口、远程接口和双重接口
因为CMP通过本地接口管理着实体EJB之间的关系,所以我们强烈建议总是提供一个本地接口。我们认为远程接口需要的时候很少,但是如果仔细评估一下就会证明远程接口也是需要的。所以,我们还是设计一个双重接口吧。

本地接口通过本地客户机提供了对EJB的优化的访问;远程方法调用(remote method invocationRMI)的语义不要求通过本地客户机、使用本地接口来访问EJB

远程客户机与EJB容器位于不同的虚拟机上,它需要RMI和远程接口来访问EJB。从理论上讲,单单设计一个本地实体存在着一个明显的缺点,那就是只有在相同应用服务器内的客户机才能访问该实体bean。然而,这只是一个理论上的缺点,因为实际上很少需要从应用服务器之外访问实体EJB

粗粒度与细粒度
这是一个非常有争议的专题,所以还应根据您个人的经验小心地评价关于此专题的一些不同观点。我们的选择是,实体EJB最常用于表示应用程序业务域中各个实体,所以应该让实体EJB尽量地细粒度,不过也应将设计限定为仅提供一个本地接口。关于这个问题的争论始于EJB体系结构规范1.x版本,当时只能通过一个远程接口来访问实体EJB。建立在EJB 1.x版本基础上的任何反对使用细粒度实体EJB的观点,虽然当时也有合理之处,但是在EJB体系结构规范2.0  中却已不合时宜了,并且最终遭到反对。请谨记:有些专家可能不同意我们的观点,所以我们鼓励您通过实验进行考证,并在此专题上形成自己的观点。

数据传输对象与GetSet方法
这又是一个有争议的专题。我们的观点如下所述:

  • 在实体EJB的本地接口中暴露CMP持久字段的所有get访问器(accessor)方法。
  • 为不属于实体EJB主键的一部分的每个CMP持久字段创建包装器(wrapperset方法,并且在实体EJB的本地接口中暴露这些包装器方法。使用这些包装器方法背后的动机是,CMP要求所有持久字段都具有抽象方法setXXX,如果需要在这些setXXX方法内进行任何验证,那么就可以先在包装器方法内完成验证,然后再调用相应的setXXX方法。如果不需要这样的验证,那么省掉包装器方法而直接包括setXXX方法也无不可。
  • 在某些少见的环境下,可能要求实体EJB有一个远程接口,这时可以为每个实体EJB定义一个数据传输对象,将该数据传输对象作为实体EJB的远程接口中的一个参数,暴露其getset方法。

生成和打包EJB
EJB体系结构规范中,每个实体EJB组件都由一组指定的Java类和一组指定的XML部署描述符组成:

  1. 一个必需的实现实体bean核心功能的bean类。
  2. 一个远程接口、本地接口或双重接口,该接口为实体bean提供了适当的客户机视图。
  3. 一个远程主接口(home interface)、本地主接口或者双重主接口,该接口为实体bean的生命周期管理提供了适当的接口。
  4. 如果是具有组合主键的实体bean,那么还有一个必需的主键类。
  5. 一个ejb-jar XML部署描述符文件,EJB体系结构规范version 2.0对此作了规定。
  6. 一个特定于供应商的 weblogic-ejb-jar XML部署描述符文件,BEA WebLogic Server 8.1 对此有规定。
  7. 如果是CMP实体bean,那么还应有一个特定于供应商的weblogic-cmp-rdbms-jar XML 部署描述符文件,BEA WebLogic Server 8.1对此有规定。

这里使用的例子实体EJB是一个CMP实体EJB,它有一个远程接口,它的名称是AccountEJB。在随WebLogic Server 8.1一起安装的示例文件中,即 /weblogic81/samples/server/examples/src/examples/ejb20/basic/containerManaged目录下,可以找到这个实体EJB

实体bean EJB类和接口可以用EJBGen工具来生成。

EJBGen
EJBGen
是一种EJB 2.0代码生成器,它能够从一个EJB bean类生成本地接口/远程接口、本地主接口/远程主接口、主键类和部署描述符。在EJB bean类中使用EJBGen标记来指定不同的EJB设计配置(例如,本地/远程和CMP/BMP)。在WebLogic Server 8.1 SP01 中,EJBGen 类被包括在/weblogic81/server/lib/weblogic.jar中。在WebLogic Server 8.1 SP02 & SP03中,EJBGen类被包括在/weblogic81/server/lib/ejbgen.jar文件中。将ejbgen.jar添加到Classpath中,以便使用EJBGen工具。

EJBGen通过以下命令来调用:

javadoc -docletpath ejbgen.jar -doclet weblogic.tools.ejbgen.EJBGen
<EjbBeanClass>.java

该命令有一些选项:

  • -d [directory]: 创建EJB/接口和部署描述符时所在的目录。
  • -descriptorDir [directory]: 创建部署描述符时所在的目录。
  • -wls7: 有了–wls7这个选项,就会生成WebLogic Serve 7.1部署描述符。

如果要将更早版本的BEA WebLogic Server部署描述符转换成WebLogic Server 8.1部署描述符,那么可以使用DDConverter

DDConverter
DDConverter
是一个命令行工具,用于将更早版本的XML部署描述符(ejb-jar.xmlweblogic-ejb-jar.xmlweblogic-cmp-rdbms-jar.xml)转换成当前版本的WebLogic Server DDConverter可以用以下命令来调用:

java weblogic.ejb20.utils.DDConverter [options] –d destDir file1 [file2...]

在这个命令中,file是指包含EJB 1.1部署描述符的一个EJB 1.0部署描述符文件或JAR文件。DDConverter的一部分选项有:

  • -d destDir:部署描述符输出到的目录。
  • -EJBVer output EJB version: 指定输出EJB版本。缺省版本是2.0

在部署EJB之前,必须将其打包到一个JAR文件或EAR文件中。

EJB JAR文件
EJB JAR
文件的结构由EJB类和接口以及包含部署描述符的 META-INF目录组成。创建一个目录source/ejb20/basic/containerManaged和一个目录source/ejb20/basic/containerManaged/META-INF。将Account.javaAccountBean.javaAccountHome.java ProcessingErrorException.java/weblogic81/samples/server/examples/src/examples/ejb20/basic/containerManaged目录复制到source/ejb20/basic/containerManaged目录。将ejb-jar.xmlweblogic-ejb-jar.xmlweblogic-cmp-rdbms-jar.xml/weblogic81/samples/server/examples/src/examples/ejb20/basic/containerManaged目录复制到source/ejb20/basic/containerManaged/META-INT目录。

通过Apache Ant使用编译好的EJB Java类文件和部署描述符创建一个JAR文件,Apache Ant  是一种基于Java的联编(build)工具。Apache Ant工具需要一个联编文件。创建一个带有目标的build.xml文件(参见清单1),以便编译EJB源文件并利用编译好的类文件生成一个JAR 文件。

build.xml文件复制到/source目录。运行build.xml中的ejb-jar目标。EJB JAR文件生成在source/dist目录中。EJB JAR可以使用BEA WebLogic appc编译器来编译。用appc编译器来编译并不是必需的,但这是BEA WebLogic推荐的。

appc
appc
编译器利用EJB JAR文件生成容器类,并验证部署描述符。在部署EJB JAR文件之前用 appc编译EJB JAR类的好处是,这样可以识别出在部署EJB JAR时可能发生的错误。要运行 appc编译器,应保证weblogic.jar被包括在Classpath中。appc可以通过以下命令来调用:

java weblogic.appc [options] <jar file or directory>

appc有一些选项:

  • -output<file>:指定输出目录。
  • -keepgenerated: 保留生成的.java文件。
  • -compiler<java>: Java编译器设置成可用。

部署EJB
要部署一个实体EJBJAR文件,必须有一个带有Java命名和目录接口(Java Naming and Directory InterfaceJNDI)名称的数据源。在我以前的文章(WLDJ, Vol. 3, issue 1)中我已解释了如何创建连接池(Connection Pool)。用JNDI "examples-dataSource-demoPool" 创建一个Tx Datasource。这个JNDI 名应该与weblogic-cmp-rdbms-jar.xml部署描述符文件的 <data-source-name>元素中指定的名称相一致。

为了部署实体EJB JAR文件,在管理控制台(administration console)中选择Deployments>EJB Modules节点。单击Deploy a new EJB Module链接(见图1)。

这时会显示出Deploy an EJB Module窗体(见图2)。在Deploy an EJB Module 窗体中选择 upload your files(s) 链接。接着将会显示一个Upload and Install an Application or Module 窗体。选择一个要上载的EJB JAR文件,并单击Upload按钮。

这时会显示出Deploy an EJB Module窗体。选择myserver链接。接着可以看到myserver目录中的子目录列表。单击upload directory链接。在upload目录中选择要部署的EJB JAR,并单击Target Module按钮(见图3)。这时会显示一个Select Targets for this EJB module窗体(见图4)。

Select targets for this EJB module窗体中选择一个或多个目标服务器,并单击Continue按钮。在接着显示出的窗体中,在Name字段中指定用于要部署的EJB模块的名称(见图5)。

单击Deploy按钮以部署EJB JAR文件。这样一来,EJB JAR将被部署到服务器上,并且有一个EJB节点被添加到EJB Modules节点中(见图6)。

EJB应用程序还可以部署到BEA WebLogic Server上,方法是将EJB JAR文件复制到该应用程序要部署到的那个域上的applications目录中。

BEA WebLogic为在 WebLogic服务器上部署EJB提供了一些建议。

  1. 应该将EJB作为企业归档应用程序(EAR应用程序)中的一个EJB JAR来部署,以利于应用程序的移植和修改。
  2. 引用了其他EJBEJB应该部署在相同的应用程序中;weblogic-ejb-jar.xml中的enable-call-by-reference元素应该设置成True,以获得更好的性能。
  3. 部署在WebLogic服务器群集上的EJB应该其次地(homogeneously)部署到群集内每一台受管的服务器上。如果一个EJB只需部署到群集内的一台服务器上,那么在部署之前应使用appc编译器先对 EJB进行编译。

结束语
EJB
应用程序的开发包括创建EJB类、编译EJB类和利用编译好的EJB类创建一个JAR文件,以及将EJBJAR部署到BEA WebLogic Server。通过遵循关于设计、生成和部署EJB JARBEA WebLogic Server上的一些建议,EJB应用程序的性能得到了提高。

参考资料

l           Programming WebLogic Enterprise JavaBeans: http://edocs.bea.com/wls/docs8.1/ejb/index.html

Listing 1:  build.xml file

<project name="example-entity-ejb" default="all" basedir=".">
  <property name="source" value="."/>
   <property name="ejb" value="ejb20/basic/containrManaged"/>
  <property name="build" value="{source}/build"/>
   <property name="j2sdkee" value="c:/j2sdkee1.3.1"/>
  <property name="dist" value="{source}/dist"/>
 
  <target name="init">
    <!-- Create the time stamp -->
    <tstamp/>
    <mkdir dir="{build}"/>
    <mkdir dir="{build}/META-INF"/>
    <mkdir dir="{dist}"/>
  </target>
  <target name="ejb">
    <javac srcdir="{source}" classpath="{j2sdkee}/lib/j2ee.jar"
               destdir="{build}" includes="{ejb}/*.java"/>
    <copy  todir="{build}/META-INF">
    <fileset   dir="META-INF" includes="*.xml" />
    </copy>
  </target>
  <target name="ejb-jar" depends="ejb">
    <jar jarfile="{dist}/entityejb.jar" includes="META-INF/*.xml,
               {ejb}/*.class" basedir="{build}"/>
  </target>
</project>
 作者简介
Ajay Vohra 是DataSynapse公司的高级解决方案架构师。
Deepak Vohra 是一名NuBean顾问兼web开发人员。他拥有Sun Certified Java 1.4 Programmer和Sun Certified Web Component Developer for J2EE证书。
dot dot dot

dot
  作者其它文章
您对本文的评价
您对这篇文章的看法如何?
太棒了!5分 不错啊 4分 一般般 3分 有待提高 2分 不好 1分

   
相关产品