一、EJB技术简介
EJB的全称是Enterprisejavabean。是JAVA中的商业应用组件技术。EJB结构中的角色EJB组件结构是基于组件的分布式计算结构,是分布式应用系统中的组件。
一个完整的基于EJB的分布式计算结构由六个角色组成,这六个角色可以由不同的开发商提供,每个角色所作的工作必须遵循Sun公司提供的EJB规范,以保证彼此之间的兼容性。这六个角色分别是EJB组件开发者(EnterpriseBeanProvider)、应用组合者(ApplicationAssembler)、部署者(Deployer)、EJB服务器提供者(EJB ServerProvider)、EJB容器提供者(EJBContainerProvider)、系统管理员(SystemAdministrator):
二、EJB中各角色的分析
1、EJB组件开发者(EnterpriseBeanProvider)
EJB组件开发者负责开发执行商业逻辑规则的EJB组件,开发出的EJB组件打包成ejb-jar文件。EJB组件开发者负责定义EJB的remote 和home接口,编写执行商业逻辑的EJBclass,提供部署EJB的部署文件(deployment descriptor)。部署文件包含EJB的名字,EJB用到的资源配置,如JDBC等。EJB组件开发者是典型的商业应用开发领域专家。
EJB组件开发者不需要精通系统级的编程,因此,不需要知道一些系统级的处理细节,如事务、同步、安全、分布式计算等。
2、应用组合者(ApplicationAssembler)
应用组合者负责利用各种EJB组合一个完整的应用系统。应用组合者有时需要提供一些相关的程序,如在一个电子商务系统里,应用组合者需要提供JSP(JavaServerPage)程序。
应用组合者必须掌握所用的EJB的home和remote接口,但不需要知道这些接口的实现。
3、部署者(Deployer)
部署者负责将ejb-jar文件部署到用户的系统环境中。系统环境包含某种EJBServer和EJBContainer。部署者必须保证所有由EJB组件开发者在部署文件中声明的资源可用,例如,部署者必须配置好EJB所需的数据库资源。
部署过程分两步:部署者首先利用EJBContainer提供的工具生成一些类和接口,使EJBContainer能够利用这些类和接口在运行状态管理EJB。部署者安装EJB组件和其他在上一步生成的类到EJBContainer中。部署者是某个EJB运行环境的专家。
某些情况下,部署者在部署时还需要了解EJB包含的业务方法,以便在部署完成后,写一些简单的程序测试。
4、EJB服务器提供者(EJBServerProvider)
EJB服务器提供者是系统领域的专家,精通分布式交易管理,分布式对象管理及其它系统级的服务。EJB服务器提供者一般由操作系统开发商、中间件开发商或数据库开发商提供。
在目前的EJB规范中,假定EJB服务器提供者和EJB容器提供者来自同一个开发商,所以,没有定义EJB服务器提供者和EJB容器提供者之间的接口标准。
5、EJB容器提供者(EJBContainerProvider)
EJB容器提供者提供以下功能:
提供EJB部署工具为部署好的EJB组件提供运行环境。EJB容器负责为EJB提供交易管理,安全管理等服务。
EJB容器提供者必须是系统级的编程专家,还要具备一些应用领域的经验。EJB容器提供者的工作主要集中在开发一个可伸缩的,具有交易管理功能的集成在EJB服务器中的容器。EJB容器提供者为EJB组件开发者提供了一组标准的、易用的API访问 EJB容器,使EJB组件开发者不需要了解EJB服务器中的各种技术细节。
EJB容器提供者负责提供系统监测工具用来实时监测EJB容器和运行在容器中的EJB组件状态。
6、系统管理员(SystemAdministrator)
系统管理员负责为EJB服务器和容器提供一个企业级的计算和网络环境。
系统管理员负责利用EJB服务器和容器提供的监测管理工具监测EJB组件的运行情况。
三、EJB的体系结构:
EJB分布式应用程序是基于对象组件模型的,低层的事务服务用了API技术。EJB技术简化了用JAVA语言编写的企业应用系统的开发,配置。EJB技术定义了一组可重用的组件:EnterpriseBeans。你可以利用这些组件,象搭积木一样的建立你的分布式应用程序。当你把代码写好之后,这些组件就被组合到特定的文件中去。每个文件有一个或多个EnterpriseBeans,在加上一些配置参数。最后,这些 EnterpriseBeans被配置到一个装了EJB容器的平台上。客户能够通过这些Beans的home接口,定位到某个beans,并产生这个beans的一个实例。这样,客户就能够调用Beans的应用方法和远程接口。
EJB服务器作为容器和低层平台的桥梁管理着EJB容器和函数。它向EJB容器提供了访问系统服务的能力。例如:数据库的管理和事务的管理,或者对于其它的Enterprise的应用服务器。所有的 EJB实例都运行在EJB容器中。容器提供了系统级的服务,控制了EJB的生命周期。EJB中的有一些易于使用的管理工具如: Security--配置描述器(TheDeploymentdescriptor)定义了客户能够访问的不同的应用函数。容器通过只允许授权的客户访问这些函数来达到这个效果。RemoteConnectivity--容器为远程链接管理着低层的通信issues,而且对EnterpriseBeas的开发者和客户都隐藏了通信细节。EJB的开发者在编写应用方法的时候,就象是在条用本地的平台一样的。客户也不清楚他们调用的方法可能是在远程被处理的。LifeCyclemanagment--客户简单的创建一个 Enterprisebeans的实例,并通常取消一个实例。而容器管理着EnterpriseBeans的实例,使 EnterpriseBeans实现最大的效能和内存利用率。容器能够这样来激活和使EnterpriseBeans失效,保持众多客户共享的实例池。等等。 Trasctionmanagement-配置描述器定义了Enterprise beans的事务处理的需求。容器管理着那些管理分布式事务处理的复杂的issues。这些事务可能要在不同的平台之间更新数据库。容器使这些事务之间互相独立,互不干扰。保证所有的更新数据库都是成功发生的,否者,就回滚到事务处理之前的状态。
EJB组件是基于分布式事务处理的企业级应用程序的组件。所有的EJB都有如下的特点:EJB包含了处理企业数据的应用逻辑。定义了EJB的客户界面。这样的界面不受容器和服务器的影响。于是,当一个EJB被集合到一个应用程序中去时,不用更改代码和重新编译。EJB能够被定制各种系统级的服务,例如安全和事务处理的特性,都不是属于EJB类的。而是由配置和组装应用程序的工具来实现。有两种类型的EJB:Session beans和entitybeans.Sessionbeans是一种作为单用户执行的对象。作为对远程的任务请求的相应,容器产生一个Sessionbeans的实例。一个Sessionbeans有一个用户.从某种程度上来说,一个Sessionbean对于服务器来说就代表了它的那个用户.Session beans也能用于事务,它能够更新共享的数据,但它不直接描绘这些共享的数据。Sessionbeans的生命周期是相对较短的。典型的是,只有当用户保持会话的时候,Sessionbeans才是活着的。一旦用户退出了, Sessionbeans就不再与用户相联系了。Sessionbeans被看成是瞬时的,因为如果容器崩溃了,那么用户必须重新建立一个新的Session对象来继续会话。
Sessionbean典型的声明了与用户的互操作或者会话。也就是说,Sessionbean了在客户会话期间,通过方法的调用,掌握用户的信息。一个具有状态的Sessionbean称为有状态的Sessionbean.当用户终止与Sessionbeans互操作的时候.会话终止了,而且,bean也不再拥有状态值。Sessionbean也可能是一个无状态的sessionbean.无状态的 Sessionbeans并不掌握它的客户的信息或者状态。用户能够调用beans的方法来完成一些操作。但是,beans只是在方法调用的时候才知道用户的参数变量。当方法调用完成以后,beans并不继续保持这些参数变量。这样,所有的无状态的sessionbeans的实例都是相同的,除非它正在方法调用期间。这样,无状态的Sessionbeans就能够支持多个用户.容器能够声明一个无状态的 Sessionbeans.能够将任何Sessionbeans指定给任何用户.
Entity Beans对数据库中的数据提供了一种对象的视图。例如:一个Entitybean能够模拟数据库表中一行相关的数据。多个client能够共享访问同一个Entitybean.多个client也能够同时的访问同一个Entitybean.Entity beans通过事务的上下文来访问或更新下层的数据。这样,数据的完整性就能够被保证。EntityBeans能存活相对教长的时间,并且状态是持续的。只要数据库中的数据存在,Entitybeans就一直存活。而不是按照应用程序或者服务进程来说的。即使EJB容器崩溃了, Entitybeans也是存活的。EntityBeans生命周期能够被容器或者Beans自己管理。如果由容器控制着保证Entitybeans持续的issus。如果由Beans自己管理,就必须写Entitybeans的代码,包括访问数据库的调用。
EntityBeans是由主键(primarykey一种唯一的对象标识符)标识的。通常,主键与标识数据库中的一块数据,例如一个表中的一行,的主键是相同的。主键是client能够定位特定的数据块。
四、开发EJB
1、类介绍:
开发EJB的主要步骤一般来说,整个的开发步骤(开发,配置,组装)包括如下几个方面。开发:首先要定义三个类:Bean类本身,Bean的本地和远程接口类。配置:配置包括产生配置描述器--这是一个XML文件、声明了EnterpriseBean的属性、绑定了bean的 class文件(包括stub文件和skeleton文件)。最后将这些配置都放到一个jar文件中。还需要在配置器中定义环境属性。组装应用程序:包括将Enterprisebeans安装到Server服务器中,测试各层的连接情况。程序组装器将若干个Enterprise Beans与其它的组件结合起来。组合成一个完整的应用程序。或者将若干个Enterprisebeans组合成一个复杂的 EnterpriseBean。管理EnterpriseBean。
我们必须定义和编写一些EJB中的基本类。如Enterprisebean类:这是Enterprisebean内部应用逻辑的实现。编写 Enterprisebean的远程接口类。编写Enterprisebean的本地接口类。说明主键类,主键类只是对于 Entitybean才需要的。在Enterprisebean的配置描述器中指定主键的名字。 Enterprisebeans提供者定义了远程接口和本地接口,实现了EJB类本身。Remote接口中提供了客户调用EJB实现的应用逻辑函数的接口。而home接口提供了产生和定位remote接口实例的方法。
在Enterprisebean本身类的实现,本地home接口,远程remote接口之间并没有正式的联系(例如继承关系)。但是,在三个类里声明的方法却必须遵守EJB里面定义的规范。例如:你在Enterprisebean里面声明了一个应用程序的方法或者说应用逻辑。也在beans的remote接口中声明了这个方法,那么,这两个地方必须要同样的名字。Bean的实现里面必须至少有一个Create()方法:ejbCreate()。但是可以有多个带有不同参数的create()方法。 在home接口中,也必须有相同的方法定义(参数的个数相同)。EjbCreate()方法返回的一个容器管理的持久对象。它们都返回一个容器管理持久性的主键值。但是,在home的相应的Create()方法中返回值的类型是remote接口。
注意:实体 bean的实现的ejbCreate方法有点不同。实体bean可以不定义ejbCreate方法。如果实体只是通过应用程序或通过数据库管理程序的途径被加到数据库中,实体bean就省略了ejbCreate方法。EjbCreate返回的值是主键类型。如果ejbCreate方法是容器管理持久性的实体bean的方法,它的返回值就是NULL类型。如果实体bean实现了Bean管理的持久性,ejbCreate方法就返回值类型就是主键类型。容器的任务是把各接口和Enterprisebean的实现类结合起来。保证在编译时和运行时,各接口和实现类是相对应的。
EJB的实现类,各接口要从不同的基类中继承下来。一个会话bean必须实现基类javax.ejb.SessionBean。而实体bean必须实现基类javax.ejb.EntiyBean。这些EJB的基类都是从javax.ejb.EnterpriseBean继承而来。而 javax.ejb.EnterpriseBean又是从java.io.Serializable继承而来。每一个Enterprise Bean都必须有一个remote接口。Remote接口定义了应用程序规定客户可以调用的逻辑操作。这些是一些可以由客户调用的公共的方法,通常由 Enterprisebeans类来实现。注意,Enterprisebean的客户并不直接访问Bean。而是通过 remote接口来访问。Enterprisebean类的remote接口扩展了javax.ejb.EJBObject类的公共java 接口。而Javax.ejb.EJBObject是所有remote接口的基类。其代码如下:
packagejavax.ejb;
publicinterfaceEJBObjectextendsjava.rmi.Remote{
publicEJBHomegetEJBHome()throwsjava.rmi.RemoteException;
publicObjectgetPrimaryKey()throwsjava.rmi.RemoteException;
publicvoidRemove()throwsjava.rmi.RemtoeException,java.rmi.RemoveException
publicHandlegetHandle()throwsjava.rmi.RemoteException;
booleanisIdentical(EJBObjectp0)throwsjava.rmi.RemoteException;
}
getEJBHome()方法允许你取得一个相关的Home接口。对于实体Bean,用getPrimaryKey()方法获得实体 Bean的主键值。Remove()可以删除一个Enterprisebean。具体的语义在各种不同类型的 enterprisebeans的生命周期中,由上下文中解释的。方法getHandle()返回了一个Enterprise bean实例的持久的句柄。IsIndentical()方法允许你去比较Enterprisebeans是否相同。
2、方法:
所有的remote接口中的方法必须声明为公共(public)的,并必须抛出java.rmi.RemotException异常。另外,所有的 remote接口中的方法定义的参数和都必须是在RMI-IIOP中有效的。对每一个在remote接口中定义的方法,在 Enterprisebean类里面都要有相应的方法。相应的方法必须要有同样的名字,同样类型和数量的参数,同样的返回值,而且还要抛出同样的例外。如下代码显示了一个ATM例子的会话bean的remote接口Atm,。里面声明了一个应用方法transfer ()。黑体部分表示EJB规范中必须要有的内容。Remote接口必须扩展javax.ejb.EJBObject类。从客户端调用的 Enterprisebean的每一个方法都必须在remote接口中声明。Transfer()方法抛出了两个意外。其中 InSufficientFundsException例外是应用程序定义的意外。
PublicinterfaceAtmextendsjavax.ejb.EJBObject{
Publicvoidtransfer(StringSource,StringTarget,floatamount)
Throwsjava.rmi.RemoteException,InSufficientFundsException;
}
Home接口必须定义一个或多个的Create()方法。每一个这样的Create()方法都必须命名为Create。并且,它的参数,不管是类型还是数量都必须与bean类里面的ejbCreate()方法对应。注意,home接口中的Create()方法和bean类中ejbCreate()方法的返回值类型是不同的。实体bean的home接口还包含find()方法。每一个Home接口都扩展了javax.ejb.EJBHome接口。如下代码显示了javax.ejb.EJBHome接口的定义:
packagejavax.ejb;
publicinterfaceEJBHomeextendsjava.rmi.Remote(){
voidremove(Handlehandle)throwsjava.rmi.RemoteException,RemoveException;
voidremove(Objectprimarykey)throwsjava.rmi.RemoteException,RemoveException;
EJBMetaDatagetEJBMetaData()throwsRemoteException;
HomehandlegetHomeHandle()throwsRemoteException;
}
这里提供了两个remove()方法来删除Enterprisebean的实例。第一个remove方法是通过句柄来删除一个 Enterprisebean的实例。第二个remove方法通过主键来删除一个Enterprisebean的实例。 在众多的Enterprisebean实例中,句柄唯一的标识一个实例。一个句柄与它引用的Enterprise bean有相同的生命期。考虑一个实体对象,客户可以通过一个句柄来重新获得相应的Enterprisebean的实例。一个句柄能够对应一个Enterprisebean对象的多个实例。例如,即使当Enterprisebean对象所在的主机崩溃了,或者 Enterprisebean对象在不同的机器之间移动,句柄仍是有效的。这里的句柄是Serialized句柄,与CORBA中的字符串化的CORBA对象的引用是相似的概念。在EJBHome接口中的第二个remove操作通过其主键来决定要删除的Enterprise bean。主键可以是扩展了JavaObject类的任何类型,但是,必须要实现Java的Serializable接口。主键是标识实体 bean的主要的方法。通常,主键是数据库中的一个关键字,唯一的定义了由实体bean代表的数据。
方法 getEJBMetaData()返回了Enterprisebean对象的metadata接口。这个接口允许客户获得 Enterprisebean的metadata信息。当开发工具来编译链接应用程序的时候,或者配置工具来配置的时候,可能会用到 metadata信息。Javax.ejb.EJBMetadata接口提供了获得javax.ejb.EJBHome接口,home类,remote接口,还有获得主键的方法。也提供了一个isSesson()的方法来确定在放这个home接口的对象是会话bean还是实体bean。 IsStatelessSession()方法指示这个会话bean是有状态还是无状态的。如下代码显示了javax.ejb.EJBMetadata接口的定义部分的代码。
Publicjavax.ejb;PublicinterfaceEJBMetaData{
EJBHomegetEJBHome();
ClassgetHomeInterfaceClass();
ClassgetRemoteInterfaceClasss();
ClassgetPrimaryKeyClass();
BooleanisSession();
BooleanisStatelesssSession();
}
对每一个Create()方法,EJB规范定义了如下的命名约定。它的返回值是会话bean的remote接口的类型。方法的名字只能是Create ()。对会话bean类中的每一个ejbCreate()方法都必须有一个Create()与之对应。对于每一个Create()方法的参数的类型和数量都必须与会话bean类中的ejbCreate()方法相对应。方法必须抛出java.rmi.RemoteException例外。 方法必须抛出javax.rmi.CreateExeption例外。Create()方法的参数是用来初始化新的会话bean 对象的。如下代码显示了一个会话bean对象的不同的Create()方法,其中必须的部分用粗体显示:
publicinterfaceAtmHomeextendsjavax.ejb.EJBHome{
Atmcreate()throwsjava.rmi.RemoteException,javax.ejb.CreateException;
Atmcreate(ProfilepreferredProfile)
Throwsjava.rmi.RemoteExeption,javax.ehrowsjava.rmi.RemoteException,RemoveException;
EJBMetaDatagetEJBMetaData()throwsRemoteException;
HomehandlegetHomeHandle()throwsRemoteException;
}
这里提供了两个remove()方法来删除Enterprisebean的实例。第一个remove方法是通过句柄来删除一个 Enterprisebean的实例。第二个remove方法通过主键来删除一个Enterprisebean的实例。在众多的 Enterprisebean实例中,句柄唯一的标识一个实例。一个句柄与它引用的Enterprisebean有相同的生命期。考虑一个实体对象,客户可以通过一个句柄来重新获得相应的Enterprisebean的实例。一个句柄能够对应一个 Enterprisebean对象的多个实例。例如,即使当Enterprisebean对象所在的主机崩溃了,或者 Enterprisebean对象在不同的机器之间移动,句柄仍是有效的。这里的句柄是Serialized句柄,与CORBA中的字符串化的CORBA对象的引用是相似的概念。
在EJBHome接口中的第二个remove操作通过其主键来决定要删除的 Enterprisebean。主键可以是扩展了JavaObject类的任何类型,但是,必须要实现Java的 Serializable接口。主键是标识实体bean的主要的方法。通常,主键是数据库中的一个关键字,唯一的定义了由实体bean代表的数据。方法 getEJBMetaData()返回了Enterprisebean对象的metadata接口。这个接口允许客户获得 Enterprisebean的metadata信息。当开发工具来编译链接应用程序的时候,或者配置工具来配置的时候,可能会用到 metadata信息。Javax.ejb.EJBMetadata接口提供了获得javax.ejb.EJBHome接口,home类,remote接口,还有获得主键的方法。也提供了一个isSesson()的方法来确定在放这个home接口的对象是会话bean还是实体bean。 IsStatelessSession()方法指示这个会话bean是有状态还是无状态的。如下代码显示了javax.ejb.EJBMetadata接口的定义部分的代码。
Publicjavax.ejb;
PublicinterfaceEJBMetaData{
EJBHomegetEJBHome();
ClassgetHomeInterfaceClass();
ClassgetRemoteInterfaceClasss();
ClassgetPrimaryKeyClass();
BooleanisSession();
BooleanisStatelesssSession();
}
五、EJB的编程环境:
1、使用Jbuilder
Jbuilder与EJBContainer能够进行无缝连接。Jbuilder和Inprise的应用服务器包括了所有的开发和配置 EnterpriseBeans的工具以及所需要的库:运行和管理EnterpriseBean的容器、命名服务、 事务服务、Java数据库、开发EnterpriseBeans所需要的API、一个增强的java-to-iiop编译器,支持值类型和 RMI信号等等。
Jbuilder还提供了一个快速开发应用程序EnterpriseBeans的工具和向导。通过简单而且直观的步骤,向导帮助你建立一个EnterpriseBean。自己设定某些缺省值,产生了bean的模板,在上面,我们可以增加我们自己的应用逻辑。Jbuilder也提供了一个EJB的接口生成向导。向导在EnterpriseBean的公共方法基础上生成了 Remote接口和Home接口。Jbuilder还提供一个配置器的向导帮助我们逐步的建立XML描述器文件。并将生成的Stubs集中到一个jar文件中。
2、使用Jbuilder之外的集成环境:
如果你使用其它的除了别的集成环境(IDE)。要确定使用了集成环境IDE所带的容器工具。也要验证IDE是否支持EJB规范的相应的版本,还要确定它是否正确的支持EJB的API。
要确定JD到所支持的EJB容器的版本。可以通过检查Inprise的安装说明来确定EJB容器所支持的支持JDK的版本。
在配置EnterpriseBean的时候,你必须使用Inprise的应用服务器所提供的工具。这些工具能够编辑和修改第三方的代理商提供的Inprise配置描述器。还能够验证配置描述器,能够验证bean的源代码。
六、一个简单的HELLO例子
1、安装ApusicApplicationServer
Note:以下以Linux为例,来说明ApusicApplicationServer的安装过程。其他平台的安装,可参考ApusicApplicationServer安装手册。
下载JDK1.2,ApusicApplicationServer必须运行在JDK1.2以上环境中。可从以下站点下载最新JDK。
http://java.sun.com
下载ApusicApplicationServer
ApusicApplicationServer试用版可从以下网址得到:
http://www.apusic.com/download/enter.jsp
在下载完成后,你可以得到一个包裹文件apusic.zip,选定安装目录,假设安装到/usr下,则用以下命令:
cd/usr
jarxvfapusic.zip
/usr下会出现一个目录apusic,ApusicApplicationServer的所有程序都被解压到/usr/apusic下。
将以下路径加入到CLASSPATH中
/usr/apusic/lib/apusic.jar
$JAVA_HOME/lib/tools.jar
用以下命令运行ApusicApplicationServer
java-Xms64mcom.apusic.server.Main-root/usr/apusic
2、定义EJB远程接口(RemoteInterface)
任何一个EJB都是通过RemoteInterface被调用,EJB开发者首先要在RemoteInterface中定义这个EJB可以被外界调用的所有方法。执行RemoteInterface的类由EJB生成工具生成。
以下是HelloBean的RemoteInteface程序:
packageejb.hello;
importjava.rmi.RemoteException;
importjava.rmi.Remote;
importjavax.ejb.*;
publicinterfaceHelloextendsEJBObject,Remote{
file://thismethodjustget"HelloWorld"fromHelloBean.
publicStringgetHello()throwsRemoteException;
}
3、定义HomeInterface
EJB容器通过EJB的HomeInterface来创建EJB实例,和RemoteInterface一样,执行HomeInterface的类由EJB生成工具生成。
以下是HelloBean的HomeInterface程序:
packageejb.hello;
importjavax.ejb.*;
importjava.rmi.Remote;
importjava.rmi.RemoteException;
importjava.util.*;
/**
*Thisinterfaceisextremelysimpleitdeclaresonly
*onecreatemethod.
*/
publicinterfaceHelloHomeextendsEJBHome{
publicHellocreate()throwsCreateException,
RemoteException;
}
4、写EJB类
在EJB类中,编程者必须给出在RemoteInterface中定义的远程方法的具体实现。EJB类中还包括一些EJB规范中定义的必须实现的方法,这些方法都有比较统一的实现模版,编程者只需花费精力在具体业务方法的实现上。
以下是HelloBean的代码:
packageejb.hello;
importjavax.ejb.*;
importjava.util.*;
importjava.rmi.*;
publicclassHelloBeanimplementsSessionBean{
staticfinalbooleanverbose=true;
privatetransientSessionContextctx;
//ImplementthemethodsintheSessionBean
//interface
publicvoidejbActivate(){
if(verbose)
System.out.println("ejbActivatecalled");
}
publicvoidejbRemove(){
if(verbose)
System.out.println("ejbRemovecalled");
}
publicvoidejbPassivate(){
if(verbose)
System.out.println("ejbPassivatecalled");
}
/**
*Setsthesessioncontext.
*
*@paramSessionContext
*/
publicvoidsetSessionContext(SessionContextctx){
if(verbose)
System.out.println("setSessionContextcalled");
this.ctx=ctx;
}
/**
*Thismethodcorrespondstothecreatemethodin
*thehomeinterfaceHelloHome.java.
*Theparametersetsofthetwomethodsare
*identical.Whentheclientcalls
*HelloHome.create(),thecontainerallocatesan
*instanceoftheEJBeanandcallsejbCreate().
*/
publicvoidejbCreate(){
if(verbose)
System.out.println("ejbCreatecalled");
}
/**
*****HEREISTHEBUSINESSLOGIC*****
*thegetHellojustreturna"HelloWorld"string.
*/
publicStringgetHello()
throwsRemoteException
{
return("HelloWorld");
}
}
5、创建ejb-jar.xml文件
ejb-jar.xml文件是EJB的部署描述文件,包含EJB的各种配置信息,如是有状态Bean(StatefulBean) 还是无状态Bean(StatelessBean),交易类型等。ejb-jar.xml文件的详细信息请参阅EJB规范。以下是HelloBean的配置文件:
<?xmlversion="1.0"?>
<!DOCTYPEejb -jarPUBLIC"-//SunMicrosystemsInc.//DTDEnterprise JavaBeans1.2//EN""http://java.sun.com/j2ee/dtds/ejb-jar_1_2.dtd">
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>Hello</ejb-name>
<home>ejb.hello.HelloHome</home>
<remote>ejb.hello.Hello</remote>
<ejb-class>ejb.hello.HelloBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
<assembly-descriptor>
<container-transaction>
<method>
<ejb-name>Hello</ejb-name>
<method-name>*</method-name>
</method>
<trans-attribute>Required</trans-attribute>
</container-transaction>
</assembly-descriptor>
</ejb-jar>
6、编译和部署
编译Java源文件并将编译后class和ejb-jar.xml打包到Hello.jar
mkdirbuild
mkdirbuild/META-INF
cpejb-jar.xmlbuild/META-INF
javac-dbuild*.java
cdbuild
jarcvfHello.jarMETA-INFejb
cd..
用EJB工具生成可部署到ApusicApplicationServer中运行的jar文件:
javacom.apusic.ejb.utils.EJBGen-d/usr/apusic/classes/Hello.jarbuild/Hello.jar
增加/usr/apusic/classes/Hello.jar到CLASSPATH中
将Hello.jar加入到ApusicApplicationServer配置文件中。在/usr/apusic/config/server.xml加入以下几行:
<module>
<ejb>
<ejb-uri>classes/Hello.jar</ejb-uri>
<bean>
<ejb-name>Hello</ejb-name>
<jndi-name>HelloHome</jndi-name>
</bean>
</ejb>
</module>
启动服务器
java-Xms64mcom.apusic.server.Main-root/usr/apusic
7、写客户端调用程序
您可以从JavaClient,JSP,Servlet或别的EJB调用HelloBean。
调用EJB有以下几个步骤:
通过JNDI(JavaNamingDirectoryInterface)得到EJBHomeInterface
通过EJBHomeInterface创建EJB对象,并得到其RemoteInterface
通过RemoteInterface调用EJB方法
以下是一个从JavaClient中调用HelloBean的例子:
packageejb.hello;
importjavax.naming.Context;
importjavax.naming.InitialContext;
importjava.util.Hashtable;
importjavax.ejb.*;
importjava.rmi.RemoteException;
/**
*@authorCopyright(c)2000byApusic,Inc.AllRightsReserved.
*/
publicclassHelloClient{
publicstaticvoidmain(Stringargs[]){
Stringurl="rmi://localhost:6888";
ContextinitCtx=null;
HelloHomehellohome=null;
try{
Hashtableenv=newHashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.apusic.jndi.InitialContextFactory");
env.put(Context.PROVIDER_URL,url);
initCtx=newInitialContext(env);
}catch(Exceptione){
System.out.println("Cannotgetinitialcontext:"+e.getMessage());
System.exit(1);
}
try{
hellohome=(HelloHome)initCtx.lookup("HelloHome");
Hellohello=hellohome.create();
Strings=hello.getHello();
System.out.println(s);
}catch(Exceptione){
System.out.println(e.getMessage());
System.exit(1);
}
}
}
运行HelloClient,可得到以下输出:
HelloWorld
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=505312
http://blog.csdn.net/coolingverse