- 论坛徽章:
- 0
|
4.2 会话EJB编程模型
如图4-1所示,会话EJB的编程模型简述如下:客户端通过Bean的远程接口访问会话对象。而实现这个远程接口的Java对象是一个会话对象
EJBObject。一个EJBObject会话对象是一个能被客户端通过标准的远程方法调用Java
API访问的远程Java对象。从创建到销毁,会话对象存在于容器中。容器对客户端来说是透明的,容器为Session对象提供了安全、并发、事务、缓存
和其他的服务,每个Session对象拥有一标识。一般情况下,该标识随着服务器的停止而结束。Session
Bean的客户端视图与位置无关,一个和Session对象运行在同一个JVM的客户端和运行在相同或不同机器上的不同JVM的客户端使用相同的
APIs。一个会话对象的客户端可能是另外一个部署在相同或不同容器上的企业Bean,或者是任意的Java程序,如应用程序、Applet,或
Servlet。一个Session Bean的客户端视图也可以映射成非Java客户端环境,如CORBA客户端,这不是由Java程序语言写的。
![]()
多企业Bean可以安装在一个容器中。容器允许客户端通过JNDI查找安装好的主接口。一个Session
Bean的主接口提供了这个Bean创建、删除的方法。一个会话对象的客户端视图是一致的,它不随session
Bean和容器的不同而不同。
下面深入讨论其中相关的问题。
4.2.1 定位Bean的主接口
多个EJB可以部署在同一个容器中。客户端可以使用JNDI查找指定企业Bean的主接口。
客户端使用JNDI来查找会话Bean的主接口。例如,一个Cart会话Bean的主接口可以使用如下代码查找。
Context
initialContext = new InitialContext();
CartHome cartHome =
(CartHome)javax.rmi.PortableRemoteObject.narrow(
initialContext.lookup("java:comp/env/ejb/cart"),CartHome.class);
一个客户端的JNDI命名空间可以配置起来包含网络上在不同机器上的、不同EJB容器中的EJB的主接口。而EJB容器的实际位置对使用企业Bean的客户端来说是透明的。
实现主接口的分布式对象(即EJBHome对象)的生命周期是与EJB容器相关的。客户端应用程序可以获取主接口,而且在客户端的生命周期中多次使用。
客户端可以把主接口的引用传递给另一个应用程序,而接受的应用程序可以使用主接口对象的引用,就和通过JNDI获取的一样。
容器实现了安装在容器中的EJB的主接口。实现会话Bean主接口的对象叫做EJBHome对象。容器使会话Bean的主接口通过JNDI对客户端可用。
主接口允许客户端进行如下操作。
·创建一个新的会话对象
·删除一个会话对象
·为会话Bean获取javax.ejb.EJBMetaData接口
javax.ejb.EJBMetaData接口使应用程序装配工具发现关于Session Bean的信息,并允许松散的Client/Server绑定客户端脚本。
·获取主接口的一个句柄
主句柄是可序列化的,能写入到固定的存储器。然后,句柄可以在另一个不同的JVM中,从固定存储器中反序列化以获取主接口的引用。
4.2.2 创建并使用会话对象
主接口定义一个或多个create(...)方法,每个方法定义了一种创建会话对象的方式,create方法的参数用来初始化创建的会话对象的状态。
下面这个例子演示了有两个create(...)方法的主接口:
public
interface CartHome extends javax.ejb.EJBHome{
Cart
create(String customerName,String account)
throws
RemoteException,BadAccountException,CreateException;
Cart
createLargeCart(String customerName,String account)
throws
RemoteException,BadAccountException,CreateException;}
下面演示了客户端怎样使用主接口的create(...)方法创建远程对象:
cartHome.create("John","7506");
客户端从来不会直接访问会话Bean类的实例。客户端使用会话Bean的远程接口来访问会话Bean的实例。实现会话Bean的远程接口的实例由容器提供,它的实例叫做会话EJBObjects。
会话EJBObject支持:
·对象的业务逻辑方法
会话EJBObject代理对会话Bean实例的业务逻辑方法的调用。
·javax.ejb.EJBObject接口定义的方法。这些方法允许客户端:
·获取会话对象的主接口
·获取会话对象的句柄
·测试会话对象是否与另一个是同一个
·删除会话对象
javax.ebj.EJBObject接口中定义的方法是由容器实现的,而并不是由会话Bean类代理的。
一个会话Bean运行期对象的例子如图4-2所示。
客户端使用Cart主接口的create方法创建一个Cart会话对象。客户端使用这个会话对象来填写购物单并购买相关内容。
假设用户开始购买后终止一两天,然后再去完成.客户端可以通过获取会话对象的句柄,把句柄序列化到持久性的存储器中,然后重新用它来创建最初的Cart来实现。
对下列例子,开始,在JNDI中查找Cart的主接口,然后使用主接口来创建一个Cart会话对象并加入一些购物项:
CartHome
cartHome =
(CartHome)javax.rmi.PortableRemoteObject.narrow{
initialContext.lookup(...),CartHome.class);
Cart
cart =
cartHome.createLargeCart(...);
cart.addItem(66);
cart.addItem(22);
下面我们决定稍候完成这次购物,因此要序列化这个Cart会话对象的句柄并把它存在一个文件里:
Handle
cartHandle = cart.getHandle();
//serialize cartHandle,store in
a
file...
最后我们从文件中反序列化句柄,并重新创建cart会话对象的引用,并购买购物单里的商品:
Handle
cartHandle = ...;//deserialize from a file...
Cart cart =
(Cart)javax.rmi.PortableRemoteObject.narrow(
cartHandle.getEJBObject(),Cart.class);
cart.purchase();
cart.remove();
4.2.3 删除会话对象
客户端可以使用javax.ejb.EJBObject接口的remove()方法删除一个会话Bean,或者使用接口javax.ejb.EJBHome中定义的remove(Handle
hanele)方法。
因为会话对象没有主键供客户端访问,调用方法javax.ejb.EJBHome.remove(Object
primaryKey)会抛出异常javax.ebj.RemoveException。
拥有会话引用的客户端可以做如下事情:
·调用会话对象远程接口中定义的业务方法
·获取会话对象主接口的引用
·获取会话对象的句柄
·在客户端的范围内把引用作为参数或返回值
·删除会话对象,会话对象也可以在生命周期到时被容器自动删除。
引用一个不存在的会话对象是无效的。试图调用一个存在的会话对象会抛出异常:java.rmi.NoSuchObjectException。
4.2.4 会话标识
会话对象作为创建它的客户端的私有资源,在客户端看来是匿名的。和实体对象相反,实体对象有主键作为标识,会话对象隐藏它们的标识。结果是,调用会话Bean的EJBObject.getPrimaryKey()方法和EJBHome.remove(Object
primaryKey)方法会抛出java.rmi.RemoteException异常。
如果调用会话Bean的EJBMetaData.getPrimaryKeyClass()方法,会抛出异常java.lang.RuntimeException。
既然所有的会话隐藏了它它们的标识,就不需要为它们提供finder方法。因此,会话Bean的主接口没有定义任何finder方法。
会话对象句柄在客户端生命结束后可以继续保持,可以把它序列化到一个持久的存储器中。当句柄被反序列化后,会话对象可以正常工作,只要服务器上的会话对象依然存在(时间到或服务器关闭会销毁会话对象)。
客户端代码必须使用javax.rmi.PortableRemoteObject.narrow(...)方法来把调用句柄上的getEJBObject()方法的结果转化成远程接口类型。
自动允许句柄的所有者来调用远程对象的方法。当会话对象的引用从一个句柄中获得,并当会话对象的方法被调用时,容器会基于调用的原则进行访问检查。
1. 有状态会话EJB标识
有状态会话对象具有惟一的标识,在容器创建的时候被分配。
客户端通过调用isIdentical(EJBObject otherEJBObject)方法能判断两个会话对象引用是否一致。
下面演示了有状态会话对象中isIdentical方法的使用:
FooHome fooHome = ...;//obtain home of a stateful session bean
Foo foo1 = fooHome.create(...);
Foo foo2 = fooHome.create(...);
if (foo1.isIdentical(foo1)){//返回true
...
}
if (foo1.isIdentical(foo2)){//返回false
...
}
2. 无状态会话EJB标识
同一标识对象创建的所有无状态会话Bean拥有同样的标识,这个标识是容器分配的。如果无状态会话EJB被部署了多次(每次部署导致一个不同的home的创建),不同的主接口的会话对象就会有不同的标识。
当用来比较同一个无状态什么Bean的不同对象应用时,方法isIdentical(EJBObject otherEJBObject)总会返回true。
下面例子演示了stateless session object的isIdentical方法的使用。
FooHome fooHome = .../obtain home of a stateless session bean
Foo foo1 = fooHome.create();
Foo foo2 = fooHome.create();
if (foo1.isIdentical(foo1)){//返回true
...
}
if (foo1.isIdentical(foo2)){//仍然返回true
...
}
3. getPrimaryKey()
会话对象的标识对客户端来说是透明的,调用会话EJBObject的getPrimaryKey()方法会抛出java.rmi.RemoteException异常。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/15317/showart_262891.html |
|