使用POA编程
创建和使用POA的方法根据要开发程序的类型不同也会有些差异。一个典型POA程序的编写过程包含了以下几步:
1.获得POA根元素
首先要获取POA根元素,它由ORB管理,使用初始对象名“RootPOA”就能获取它并供给程序使用。操作方法如下:
ORB orb = ORB.init(argv, null);
POA rootPOA = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));
2.定义POA策略
正如前面所提到的,POA是一个无需重写代码就能够在多个ORB产品之间使用的对象适配器。它同时也是为永久对象(该种对象即使在存放它们的服务器重启后仍然能够继续存在)所设计的。开发者需要能够对对象的标识、状态、存储和生命周期等参数进行控制。这些都是通过使用POA策略实现的,POA策略的内容与线程、生命期、对象唯一性、激活等有关。
可供开发者设定的策略有七种。它们是:
n Thread Policy
针对某个程序选取合适的线程处理技术需要考虑很多因素,诸如程序中要用到的对象数量、操作系统支持多线程的程度,预期的系统负载等等。BOA不支持多线程,但是在POA中就解决了这个问题,它通过线程策略指定将创建的POA要使用的线程模型。你可以使用:
n ORB_CTRL_MODEL:本模型允许使用多线程同时对多个请求进行处理,由ORB负责分配请求给线程(系统默认设定)。
n SINGLE_THREAD_MODEL:本模型不使用线程,所有请求都将依次处理(但在J2SE1.4中本模型还未实现)。
能够如下创建本策略:
Policy p[] = new Policy[7];
p[0] = rootPOA.createt_thread_policy(ThreadPolicyValue.ORB_CTRL_MODEL);
在本例中我们生成了一个包含了所有七项策略内容的数组。在首个元素中我们创建了线程策略。要注意到我们创建的线程策略仍是系统默认值。这只是一个演示如何创建策略的例子。
n Lifespan Policy
POA支持两种类型的CORBA对象:CORBA默认使用的是永久对象,另一种新对象就是暂时对象。暂时对象离开了创建它的进程就不能再继续存在;它能够在一些需要临时对象的情况(例如程序回调时)时被采用。与此相对的,永久对象即使离开了创建它的进程仍可以继续生存。例如,如果客户端向一个未启动(或没有运行)的目标对象发送一个请求,ORB就会为该对象启动这个服务进程(如果需要)同时激活该对象本身。这个激活过程对客户来说是透明的。
生命期策略能够被用来指定将要创建POA的对象类型。你可以创建对象:
n TRANSIENT:这种对象离开创建它们的POA实例就不能再继续存在(默认设定)。
n PERSISTENT:这种对象即使离开了创建它们的进程也能继续存在。
下面的代码说明如何创建永久生命期策略:
p[1] = rootPOA.create_lifespan_policy(LifespanPolicyValue.PERSISTENT);
就像你从上面的两个例子中看到的,可以使用类似于create_nameOf_policy(policNameValue.value)格式的函数来定义策略。
n Object ID Uniqueness Policy
该策略用来指定是否服务端只有唯一的一个对象标识符。该策略的值可以是:
n UNIQUE_ID:服务端只支持一个明确的对象ID(默认设定)。
n MULTIPLE_ID:一个服务端可以支持一个或多个对象ID。
下面的代码说明如何令一个服务端可以使用一个或多个对象ID:
p[2] = rootPOA.create_id_uniqueness_policy(
IdUniquenessPolicyValue.MULTIPLE_ID);
n ID Assignment Policy
该策略用来指定对象ID是由应用程序还是ORB生成。选项有:
n USER_ID:只能由应用程序给对象指定唯一ID。
n SYSTEM_ID:由POA为对象分配唯一ID(默认设定)。要注意如果生命期策略设置的是PERSISTENT,那么在同一个POA的所有实例对象中其被分配的对象ID必须要是唯一的。
下面的代码说明如何创建一个ID分配策略,指定由应用程序生成对象ID:
p[3] = rootPOA.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID);
n Servant Retention Policy
该策略指定是否要让创建的POA在对象映射中保留活动服务端。选项有:
n RETAIN:指定POA在映射中保留活动对象(默认设定)。
n NON_RETAIN:不保留活动对象。
下面的代码说明如何使用服务端维持策略指定POA不在对象映射中保留活动对象:
p[4] = rootPOA.create_servant_retention_policy(
ServantRetentionPolicyValue.NON_RETAIN);
n Request Processing Policy
本策略用来指定POA如何处理客户端请求。选项如下:
n USE_ACTIVE_OBJECT_MAP_ONLY:如果在活动对象映射中未查找到对象ID,那么将抛出OBJECT_NOT_EXIST异常(默认设定)。但是要注意,要使用本设定你必须要把Servant Retention Policy的值设置成RETAIN。
n USE_DEFAULT_SERVANT:如果在活动对象映射中没有找到该对象ID,或服务器维持策略当前设置是NON_RETAIN,那么请求将会被分派给默认服务端。
n USE_SERVANT_MANAGER:如果在活动对象映射中没有找到该对象ID,或服务器维持策略当前被设置成NON_RETAIN,那么就由服务端管理器尝试去确定或激活一个服务端,否则抛出异常。
下面的代码展示了如何创建请求处理策略指定把请求分派给默认服务端:
p[5] = create_request_processing_policy(
RequestProcessingPolicyValue.USE_DEFAULT_SERVANT);
n Implicit Activation Policy
该策略指定是否允许POA中的服务器自动激活。选项如下(没有默认设定):
n IMPLICIT_ACTIVATION:自动激活服务端。但要注意这需要设置SYSTEM_ID和RETAIN策略。
n NO_IMPLICIT_ACTIVATION:服务端不会自启动。
根POA始终使用如下策略:
n Thread policy: ORB_CTRL_MODEL。
n Lifespan policy: TRANSIENT。
n Object ID uniqueness: UNIQUE_ID。
n ID assignment policy: SYSTEM_ID。
n Servant retention policy: RETAIN。
n Request processing policy: USE_ACTIVE_OBJECT_MAP_ONLY。
n Implicit activation policy: IMPLICIT_ACTIVATION。
3.新建POA
新建一个POA并应用你刚定义的策略。在已存在的POA上使用create_POA函数新建POA,它将作为该父POA的子节点。创建一个新的POA你需要定义以下内容:
1.命名该POA,该名字在同一父节点的所有POA元素中必须唯一。
2.POA管理器会与该新POA建立关联。如果设定参数是null,那么将会未其创建一个新的POA管理器。
3.新POA必须要与一个已定义的策略数组相关联。
下面的程序展示了如何建立POA:
POA poa = rootPOA.create_POA("childPOA", null, policy);
4.启动POAManager
一个POAManager可以与一个或多个POA对象相关联。它负责控制POA的处理方法。POAManager可以是以下状态之一:
n Holding:关联POA接收请求并以队列形式排放。
n Active:关联POA开始处理请求。
n Inactive:关联POA拒绝接收新请求并停止处理还未执行的请求。
n Discarding:关联POA丢弃新请求。
当一个POAManager对象被创建时,默认是Holding状态。这就意味着它并不会自动启动。需要开发人员按如下方法激活:
poa.the_POAManager().activate();
如果没有这步操作,POAManager将始终保持Holding状态,那么所有对服务端的请求都将被挂起在一个队列中。
5.启动服务端
如果设置的是USE_DEFAULT_SERVANT策略,服务器程序请求POA启动某未知对象,那么不管其对象ID是什么POA都将为其调用一个单独服务端。服务器程序使用set_servant对服务端进行注册。
另外,如果设置了RETAIN策略,服务端和与它相关联的对象ID都将被存入对应POA的当前对象映射中。要激活该对象可以使用下列的三种方法之一去完成:
1.服务器程序能够直接使用activate_object或activate_object_with_id方法激活该独立对象。
2.通过让POA调用一个用户设定的服务端管理,服务器程序能够使POA在收到请求时激活对象。可以通过set_servant_manager函数注册服务端关联。
3.如果同时还设置了IMPLICIT_ACTIVATION策略,当服务器程序想要获取对未激活服务端的引用时,POA将会自动激活该对象。
但是,如果设置的是NON_RETAIN策略,POA会使用默认服务器或服务器管理器去寻找一个已被激活的服务端。但是要注意,在POA看来服务器仅在请求时间内是活动的。POA不会将该客户对象关联存入活动对象映射。
6.创建对象引用
当要在服务器中创建一个对象引用时,必须要将它与客户端关联。对象引用包含对象标识符等ORB需要的信息,用来识别及定位和该对象相关的服务器和POA。对象引用可以用以下的三种方式创建:
1.直接激活服务端并且将它与对象引用关联。下面的代码演示了如何通过servant_to_reference函数将一个活动服务端映射到关联对象引用:
org.omg.CORBA.Object obj = orb.resolve_initial_references("NameService");
NamingContextExt rootctx = NamingContextExtHelper.narrow(obj);
NameComponent nc[] = rootctx.to_name("PersistentMathServer");
rootctx.rebind(nc, poa.servant_to_reference(servant));
2.服务器程序直接生成引用。下面的代码就演示了应该如何做:
Context ctx = new InitialContext();
ctx.rebind("MathServer", poa.create_reference_with_id(id, tie._all_interfaces(poa, id)[0]));
3. 指定服务器程序自动激活服务端。这只有当使用IMPLICIT_ACTIVATION策略,在POA创建时才会发生。