使用Jacorb创建固定不变的IOR

CORBA 程序中,获取 CORBA 对象有通过命名服务和可操作对象引用 (Interoperable Object Reference,IOR) 两种方式。

IOR 存储几乎所有 ORB(Object Request Broker, 对象请求代理 ) 间协议信息,用于建立客户机和目标对象之间的通信,为 ORB 的互操作提供标准化的对象引用格式。每个 IOR 指定一个或多个所支持的协议,对于每个协议, IOR 包括那个协议所专有的信息。对于 IIOP ,每个 IOR 包括一个主机名, TCP/IP 端口号和一个对象密钥,密钥根据所给出的主机名和端口组合来识别目标对象。一个 IOR 主要有三个部分组成:仓库 ID ,终点信息和对象密钥。

IOR 将所有的 ORB 信息编码在一个字符串中,应用程序通过这个 IOR 字符串就可以获得所要操作的 CORBA 对象,一个 IOR 的例子如下:

IOR:000000000000001749444C3A48656C6C6F4170702F48656C6C6F3A312E30000000000001000000000000005C0

00102000000000C31302E3134302E312E393700290500000000002A5374616E64617264496D706C4E616D652F5065

7273697374656E74504F412F4D7948656C6C6F496D706C0000000000010000000000000008000000004A414300

使用 Jacorb dior 命令可以解析 IOR 字符串的内容,上面的 IOR 解析后的内容为:

TypeId  :       IDL:HelloApp/Hello:1.0

TAG_INTERNET_IOP Profiles:

        Profile Id:             0

        IIOP Version:           1.2

        Host:                   10.140.1.97

        Port:                   10501

        Object key (URL):       StandardImplName/PersistentPOA/MyHelloImpl

        Object key (hex):        0x53 74 61 6E 64 61 72 64 49 6D 70 6C 4E 61 6D 6

5 2F 50 65 72 73 69 73 74 65 6E 74 50 4F 41 2F 4D 79 48 65 6C 6C 6F 49 6D 70 6C

 

        -- Found 1 Tagged Components--

        #0: TAG_ORB_TYPE

        Type: 1245790976 (JacORB)

    要想创建持久化的IOR,则必须让IOR中的Host,Port和Object key固定不变,其中Object key组成:ImplName/POAName/ObjectId。

命名服务方式在上篇博客《 java 构建简单的 CORBA 应用 》中已经简单介绍过,本文主要介绍 IOR 方式, IOR 结构为支持两种方式的 IOR :每次都变化的 IOR ;固定不变的 IOR CORBA 默认使用每次都变化的 IOR ,即每次启动服务端 CORBA 程序后,因为进程所使用的端口号不固定,因此 IOR 内容是每次都会随着端口号变化而变化的,相对比较简单。与每次都变化的 IOR 不同的是,很多时候应用场景要求 IOR 保持固定不变,即 CORBA 服务端应用程序进程号是固定不变的,这样就必须使用持久化的 POA 生成策略。

非常感谢 http://blog.csdn.net/njchenyi/archive/2008/10/16/3086559.aspx 这篇文章给出的小例子,但是由于例子说的不是很清楚,另外,源码不全,因此在实际工作中困难重重,下面我把我自己做的一个实验程序作为例子,讲解固定不变 IOR 的实现。

1. 写一个最简单的 IDL 文件,文件名称是 hello.idl 。代码如下:

module HelloApp{ interface Hello{ string sayHello(); oneway void shutdown(); }; };

2. 就是把这个 idl 文件编译成对应的 java 文件,这是通过 JDK 自带的 idlj 工具完成的,这个工具和 javac 在一个目录下。它的命令格式如下:  
    idlj hello.idl  

我们会发现新生成了一个目录 HelloApp ,下面包含了 6 java 源文件,分述如下:  

HelloPOA POA 指的是 Portable Object Adapter (轻便对象适配器)。这个抽象类是一个基于流的服务器端骨架,提供了服务器端基本的 CORBA 功能。

_HelloSutb 客户端的存根类,为客户端提供了 CORBA 功能。

Hello 这是 java 版的 Hello 接口,它提供了标准的 CORBA 对象功能。

HelloHelper 这是一个辅助类,负责向 CORBA 流中写入或读取对象。

HelloHolder 这是一个 final 类,它持有一个 public Hello 实例变量。它用来操作 CORBA 输入输出流的参数。

HelloOperations 这个类才是我们所预想的那个接口,只包含我们定义的那个方法,不包含 CORBA 的任何东西。

3. 提供一个服务器端的对象,注意这个实现类继承的是 HelloPOA

package com.corba; import org.omg.CORBA.ORB; import HelloApp.HelloPOA; public class HelloImpl extends HelloPOA{ private ORB orb; public void setOrb(ORB orb) { this.orb = orb; } public String sayHello() { return "/n Hello World!/n"; } public void shutdown() { orb.shutdown(false); } }

4. 服务器端程序:

由于使用 jacorb 作为 CORBA 的实现方案,因此需要下载 JacORB2.3.zip 文件,解压后将其 lib 目录的 slf4j-api-1.5.6.jar slf4j-jdk14-1.5.6.jar jacorb.jar 添加到程序的 classpath 中,服务器端程序代码如下:

package com.corba; import java.util.Properties; import org.omg.CORBA.ORB; import org.omg.PortableServer.IdAssignmentPolicyValue; import org.omg.PortableServer.LifespanPolicyValue; import org.omg.PortableServer.POA; import org.omg.PortableServer.POAHelper; import org.omg.PortableServer.ServantRetentionPolicyValue; public class HelloServer { //持久化的POA private static POA persistentPOA = null; public static void main(String[] args) { //生成一个对象请求代理(ORB),并初始化 Properties props = new Properties(); //使用jacorb的CORBA实现方案 props.put("org.omg.CORBA.ORBClass", "org.jacorb.orb.ORB"); props.put("org.omg.CORBA.ORBSingletonClass", "org.jacorb.orb.ORBSingleton"); //使用持久化IOR,必须指定持久化POA的实现名称,默认是"StandardImplName", //可以随便指定 props.put("jacorb.implname", "StandardImplName"); //这里是指定CORBA服务器端端口为固定端口,是CORBA的IOR固定不变的关键 props.put("OAPort", "12500"); //如果需要指定服务器端的ip地址,则需要使用下面这种方式,默认使用上面的方式//只指定端口即可,ip地址是服务器端程序所在机器的ip,注意这两种只能二选其一 //props.put("OAAddress", "iiop://10.140.1.97:10501"); try{ //创建ORB实例 ORB orb = ORB.init(args, props); //得到一个 RootPOA引用 POA rootPoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); //指定创建持久化POA的策略,使用持久化POA必须指定以下三种策略 org.omg.CORBA.Policy[] policies = new org.omg.CORBA.Policy[3]; //POA生命周期是持久化 policies[0] = rootPoa.create_lifespan_policy(LifespanPolicyValue.PERSISTENT); //CORBA对象的标识符是用户指定的 policies[1] = rootPoa.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID); //每次接到一个请求时,POA期望应用程序提供目标对象标识符作为 //查找伺服程序的索引 policies[2] = rootPoa.create_servant_retention_policy(ServantRetentionPolicyValue.RETAIN); //创建持久化的POA persistentPOA = rootPoa.create_POA("PersistentPOA", rootPoa.the_POAManager(), policies); //清除策略 policies[0].destroy(); policies[1].destroy(); policies[2].destroy(); policies = null; //创建伺服程序并注册到ORB上 HelloImpl helloImpl = new HelloImpl(); helloImpl.setOrb(orb); //创建伺服程序标识符,因为使用IdAssignmentPolicyValue.USER_ID //策略,所有必须要指定伺服程序id byte[] servantId = "MyHelloImpl".getBytes(); //将伺服程序标识符和服务器端CORBA对象关联起来并激活 persistentPOA.activate_object_with_id(servantId, helloImpl); //激活POAManager rootPoa.the_POAManager().activate(); //通过持久化POA获取CORBA对象 org.omg.CORBA.Object ref = persistentPOA.servant_to_reference(helloImpl); //打印CORBA对象的IOR System.out.println("CORBA IOR is:" + orb.object_to_string(ref)); System.out.println("HelloServer ready and waiting..."); //启动线程服务,等待调用 orb.run(); }catch(Exception e){ System.out.println("HelloServer occur error:" + e); e.printStackTrace(System.out); } System.out.println("HelloServer exiting ..."); } }

该小应用其实可以不用要客户端程序,直接运行服务器端程序就可以,运行起来之后记录其输出的 IOR 字符串,然后结束服务端程序,多运行几次,比较生成的 IOR 字符串,你就会发现 IOR 每次生成都是一样的,如果不指定端口和策略,每次生成的 IOR 都是不一样的,因为每次 CORBA 都会使用不同的端口。

5. 客户端程序:

为了使应用看起来更完整,同时为了演示 CORBA 客户端调用服务器端的简单过程,下面是一个简单的客户端程序:

package com.corba; import org.omg.CORBA.ORB; import HelloApp.Hello; import HelloApp.HelloHelper; public class HelloClient { static Hello hello; public static void main(String[] args) { try { // 创建一个ORB实例 ORB orb = ORB.init(args, null); // 直接通过IOR向CORBA获取目标对象,IOR是服务器端生成的(自己实现时,第一次需要//拷贝服务器端生成的IOR),因为是固定不变的IOR,因为这里可以直接硬编码写死 hello = HelloHelper.narrow(orb.string_to_object("IOR:000000000000001749444C3A48656C6C6F4170702F48656C6C6F3A312E30000000000001000000000000005C000102000000000E3139322E3136382E312E3130300030D40000002A5374616E64617264496D706C4E616D652F50657273697374656E74504F412F4D7948656C6C6F496D706C0000000000010000000000000008000000004A414300")); // 调用接口对象的方法 System.out.println("Get hello object from corba server:" + hello); System.out.println(hello.sayHello()); //关闭CORBA服务 hello.shutdown(); } catch (Exception e) { System.out.println("HelloClient occur error:" + e); e.printStackTrace(System.out); } } }

首先启动服务端程序,然后启动客户端程序,客户端程序打印出“ Hello World! ”之后,就会关闭 CORBA 服务,服务端程序随之运行结束,由于实现了固定不变的 IOR ,因此服务器端程序和客户端程序可以不用做任何更改反复正常运行。

 

注意:在测试持久化的IOR时,不能简单的比较每次生成的IOR字符串是否相同,只要IOR中的Host,Port和Object key相同即可,另外由于IOR除了上述内容外,还会有一些填充字段,所以有可能持久化的IOR字符串每次也不相同,最好的测试方法是不论重启多少次服务,使用同一个IOR能成功调用服务端的伺服程序。

你可能感兴趣的:(其他)