使用 RJB(Ruby Java Bridge) 实现 Ruby 的CORBA RPC

    技术2022-05-11  81

    背景: 需要实现一个以Ruby开发的控制台程序,并提供RPC功能,以CORBA为规范,而CORBA服务端有可能是JAVA/C/C++等语言来实现。

    方案1: 使用Ruby的开源类库Rinn(http://sourceforge.net/projects/rinn/)来直接实现CORBA客户端以实现对服务端的调用。(先用其提供的ridl(idl-to-ruby)来生成IDL的客户端Ruby代码。)

    方案2: 使用java实现CORBA客户端,再通过Rjb(http://rubyforge.org/projects/rjb/),调用java的CORBA客户端代码。

    比较: 方案1 与 方案2 的实现复杂程度差不多, 方案1的开源代码直接用纯Ruby代码实现对接口定义语言(IDL)的解析并实现了IIOP协议下的ruby ORB对象。 我一开始还是比较倾向使用这种方案,因为纯Ruby的实现,可以减少客户端环境的复杂程度,至少只需要有Ruby的运行环境就可以了。但是,该开源项目Rinn似乎很久没有人维护了(最近一次修改是在2001年7月),也没有正式release过。我下载了该代码,试图用它来实现客户端代码,但是遇到了很大的麻烦,代码是基于老的Ruby版本写的,而且还有运行错误,也没有完整的文档说明。最后,放弃了方案1选择了方案2。方案2也需要借助开源的类库:Rjb该项目比较完善,于是下载了rjb-1.0.3开始了我的Ruby-CORBA之旅。

     首先介绍一下我的开发环境:

    Ruby: ruby 1.8.5 (2006-12-25 patchlevel 12) [i386-mswin32]下载地址: http://rubyforge.org/frs/?group_id=167

    Java:java version "1.5.0_06"Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)

    警告: Rjb-1.0.3还不支持1.4或者之前的版本,否则调用会出现[BUG] Segmentation fault。

    我将用一个Demo来说明我是如何使用rjb完成对CORBA服务端调用的。

    第一步: 安装  rjb-1.0.3-mswin32.gem 使用命令行:  gem install D:/Download/Ruby/rjb-1.0.3-mswin32.gem -y安装成功将会提示: Successfully installed rjb, version 1.0.3

    第二步:  创建 CORBA 的 JAVA 服务端/客户端创建CORBA应用程序的过程大体如下: ● 编写IDL接口定义文件;● 将接口定义文件编译为相应高级语言源代码,产生服务器框架与客户端存根; ● 基于服务器框架,编写服务对象实现程序;● 基于客户端存根,编写客户对象调用程序;● 分别编译客户对象和服务对象程序;● 运行服务对象和客户对象程序;

    a. 接口定义 (HelloApp.idl) module HelloApp{     interface  Hello    {        string sayHello(in string vin);        oneway  void  shutdown();     };};

    通过Sun提供的将IDL文件编译成Java源代码的工具idlj(jdk1.3.0_01以上版本),为接口定义文件生成客户端存根和服务器框架:    idlj -fall Hello.idl

    这将在idl文件目录下生成一个 HelloApp 文件夹,其中包含以下文件:Hello.javaHelloHelper.javaHelloHolder.javaHelloOperations.javaHelloPOA.java_HelloStub.java

    b. 接口实现 (HelloImpl.java)     HelloImpl.java是Hello IDL 接口的实现;每个Hello实例都由一个HelloImpl实例来实现。HelloImpl是_HelloImplBase的子类,_HelloImplBase是由 idlj编译器从示例 IDL 中生成的。 //  The servant -- object implementation -- for the Hello // example. Note that this is a subclass of HelloPOA, whose // source file is generated from the compilation of // Hello.idl using j2idl. package  HelloApp; import  org.omg.CORBA.ORB; public   class  HelloImpl  extends  HelloPOA {     private  ORB orb;     public   void  setORB(ORB orb_val) {        orb  =  orb_val;    }     //  implement sayHello(vin) method      public  String sayHello(String vin) {                 return   " Hello  "   +  vin;    }     //  implement shutdown() method      public   void  shutdown() {        orb.shutdown( false );    }}  // end class

    c. 服务端实现 (Server/HelloServer.java)

    package  Server; import  org.omg.CORBA.ORB; import  org.omg.CosNaming.NameComponent; import  org.omg.CosNaming.NamingContextExt; import  org.omg.CosNaming.NamingContextExtHelper; import  org.omg.PortableServer.POA; import  HelloApp.Hello; import  HelloApp.HelloHelper; import  HelloApp.HelloImpl; public   class  HelloServer {     public   static   void  main(String args[]) {         try  {             //  create and initialize the ORB             ORB orb  =  ORB.init(args,  null );                         //  get reference to rootpoa & activate the POAManager             POA rootpoa  =  (POA) orb.resolve_initial_references( " RootPOA " );            rootpoa.the_POAManager().activate();             //  create servant and register it with the ORB             HelloImpl helloImpl  =   new  HelloImpl();            helloImpl.setORB(orb);             // orb.connect((Object) helloImpl);             //  get object reference from the servant             org.omg.CORBA.Object ref  =  rootpoa.servant_to_reference(helloImpl);             //  and cast the reference to a CORBA reference             Hello href  =  HelloHelper.narrow(ref);             //  get the root naming context             //  NameService invokes the transient name service             org.omg.CORBA.Object objRef  =  orb                    .resolve_initial_references( " NameService " );             //  Use NamingContextExt, which is part of the             //  Interoperable Naming Service (INS) specification.             NamingContextExt ncRef  =  NamingContextExtHelper.narrow(objRef);             //  bind the Object Reference in Naming             String name  =   " HelloApp " ;            NameComponent path[]  =  ncRef.to_name(name);            ncRef.rebind(path, href);            System.out.println( " HelloServer ready and waiting ... " );             //  wait for invocations from clients             orb.run();        }         catch  (Exception e) {            System.err.println( " ERROR:  "   +  e);            e.printStackTrace(System.out);        }        System.out.println( " HelloServer Exiting ... " );    }  // end main //  end class

    d. 客户端实现 (Client/HelloClient.java)

    package  Client; import  java.util.Properties; import  org.omg.CORBA.ORB; import  org.omg.CosNaming.NamingContextExt; import  org.omg.CosNaming.NamingContextExtHelper; import  HelloApp.Hello; import  HelloApp.HelloHelper; public   class  HelloClient {         private  Hello remoteHello  =   null ;         public  HelloClient(String host, String port)    {        Properties props  =   new  Properties();        props.put( " org.omg.CORBA.ORBInitialPort " , port);        props.put( " org.omg.CORBA.ORBInitialHost " , host);        String[] args  =  {};         try  {            ORB orb  =  ORB.init(args, props);             //  get the root naming context             //  NameService invokes the transient name service             org.omg.CORBA.Object objRef  =  orb.resolve_initial_references( " NameService " );            NamingContextExt ncRef  =  NamingContextExtHelper.narrow(objRef);             //  get the Object Reference in Naming             String name  =   " HelloApp " ;            remoteHello  =  HelloHelper.narrow(ncRef.resolve_str(name));        }  catch  (Exception e) {            e.printStackTrace(System.out);        }    }         public  java.lang.Object sayHello(String name)    {         return   this .remoteHello.sayHello(name);    }}

    说明: 客户端通过命名服务器中注册的“HelloApp”查找服务端提供的远程的Hello对象。

    e. Ruby 代码实现 (HelloAppClient.rb)

    require  " rjb " clientClass  =  Rjb:: import ( " Client.HelloClient " )client  =  clientClass.new( " localhost " " 1050 " )ret  =  client.sayHello( " Ruby " )puts ret.toString

    其中Ruby 调用 HelloClient 的 sayHello 方法。还可以用 _invoke 方法来调用该方法。

    再编写一个vbs来启动服务:

    const  SERVER_PORT  =   " 1050 " set  sh  =  WScript.CreateObject( " WScript.Shell " )sh.run( " tnameserv -ORBInitialPort  "   +  SERVER_PORT)sh.run( " java Server/HelloServer -ORBInitialPort  "   +  SERVER_PORT)

    运行:


    最新回复(0)