使用Jacorb创建固定不变的IOR

17 篇文章 0 订阅

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 。代码如下:

  1. module HelloApp{     
  2.         interface Hello{     
  3.                 string sayHello();     
  4.                 oneway void shutdown();     
  5.         };     
  6. };    

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 :

  1. package com.corba;  
  2. import org.omg.CORBA.ORB;  
  3. import HelloApp.HelloPOA;  
  4. public class HelloImpl extends HelloPOA{  
  5.     private ORB orb;  
  6.       
  7.     public void setOrb(ORB orb) {  
  8.         this.orb = orb;  
  9.     }  
  10.     public String sayHello() {  
  11.         return "/n Hello World!/n";  
  12.     }  
  13.     public void shutdown() {  
  14.         orb.shutdown(false);  
  15.     }  
  16. }  

4. 服务器端程序:

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

  1. package com.corba;  
  2. import java.util.Properties;  
  3. import org.omg.CORBA.ORB;  
  4. import org.omg.PortableServer.IdAssignmentPolicyValue;  
  5. import org.omg.PortableServer.LifespanPolicyValue;  
  6. import org.omg.PortableServer.POA;  
  7. import org.omg.PortableServer.POAHelper;  
  8. import org.omg.PortableServer.ServantRetentionPolicyValue;  
  9. public class HelloServer {  
  10.     //持久化的POA  
  11.     private static POA persistentPOA = null;  
  12.           
  13.     public static void main(String[] args) {  
  14.          //生成一个对象请求代理(ORB),并初始化    
  15.         Properties props = new Properties();    
  16.         //使用jacorb的CORBA实现方案  
  17.         props.put("org.omg.CORBA.ORBClass", "org.jacorb.orb.ORB");  
  18.         props.put("org.omg.CORBA.ORBSingletonClass", "org.jacorb.orb.ORBSingleton");  
  19.         //使用持久化IOR,必须指定持久化POA的实现名称,默认是"StandardImplName",  
  20.         //可以随便指定  
  21.         props.put("jacorb.implname", "StandardImplName");  
  22.         //这里是指定CORBA服务器端端口为固定端口,是CORBA的IOR固定不变的关键  
  23.         props.put("OAPort", "12500");  
  24. //如果需要指定服务器端的ip地址,则需要使用下面这种方式,默认使用上面的方式//只指定端口即可,ip地址是服务器端程序所在机器的ip,注意这两种只能二选其一  
  25. //props.put("OAAddress", "iiop://10.140.1.97:10501");  
  26.         try{  
  27.             //创建ORB实例  
  28.             ORB orb = ORB.init(args, props);  
  29.               
  30.             //得到一个 RootPOA引用  
  31.             POA rootPoa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));  
  32.             //指定创建持久化POA的策略,使用持久化POA必须指定以下三种策略  
  33.              org.omg.CORBA.Policy[] policies = new org.omg.CORBA.Policy[3];  
  34.                 //POA生命周期是持久化  
  35.                 policies[0] = rootPoa.create_lifespan_policy(LifespanPolicyValue.PERSISTENT);  
  36.                 //CORBA对象的标识符是用户指定的  
  37.                 policies[1] = rootPoa.create_id_assignment_policy(IdAssignmentPolicyValue.USER_ID);  
  38.                 //每次接到一个请求时,POA期望应用程序提供目标对象标识符作为  
  39. //查找伺服程序的索引  
  40.                 policies[2] = rootPoa.create_servant_retention_policy(ServantRetentionPolicyValue.RETAIN);  
  41.                 //创建持久化的POA  
  42.                 persistentPOA = rootPoa.create_POA("PersistentPOA", rootPoa.the_POAManager(), policies);  
  43.                     //清除策略    
  44.                 policies[0].destroy();  
  45.                 policies[1].destroy();  
  46.                 policies[2].destroy();  
  47.                 policies = null;  
  48.               
  49.             //创建伺服程序并注册到ORB上  
  50.             HelloImpl helloImpl = new HelloImpl();  
  51.             helloImpl.setOrb(orb);  
  52.               
  53.             //创建伺服程序标识符,因为使用IdAssignmentPolicyValue.USER_ID  
  54. //策略,所有必须要指定伺服程序id  
  55.             byte[] servantId = "MyHelloImpl".getBytes();  
  56.             //将伺服程序标识符和服务器端CORBA对象关联起来并激活  
  57.             persistentPOA.activate_object_with_id(servantId, helloImpl);  
  58.             //激活POAManager  
  59.             rootPoa.the_POAManager().activate();  
  60.             //通过持久化POA获取CORBA对象  
  61.             org.omg.CORBA.Object ref = persistentPOA.servant_to_reference(helloImpl);  
  62.             //打印CORBA对象的IOR  
  63.             System.out.println("CORBA IOR is:" + orb.object_to_string(ref));  
  64.               
  65.             System.out.println("HelloServer ready and waiting...");  
  66.               
  67.             //启动线程服务,等待调用  
  68.             orb.run();  
  69.         }catch(Exception e){  
  70.             System.out.println("HelloServer occur error:" + e);  
  71.             e.printStackTrace(System.out);  
  72.         }  
  73.         System.out.println("HelloServer exiting ...");  
  74.     }  
  75. }  

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

5. 客户端程序:

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

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

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

 

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值