Java基础系列之六:CORBA入门示例

1. 概述

CORBA: Common Object Request Broker Architecture

CORBA是一套标准,包含了相关的API以及通信协议的定义,开发者据此可以实现一种与WebService类似的远程调用机制。

 

我直观地认为,CORBA程序的运行涉及3个进程:

1Server进程通常时持续运行的,在运行之初它会将对象注册到2);

2Name Service存放着不同的对象引用,这些对象通过name进行标识;

3Client进程在需要时会拿着相应的name去向2)索要某一对象引用,得到之后便可调用对象的方法了。

  

2. JacORB

JacORB一类的产品对CORBA做了实现(包括通信协议等等),因此我们只剩下自己的业务代码需要写了。

也其它的产品比如Orbix,只不过后者是个商业软件。

 

3. JacORB的安装

1)下载http://www.jacorb.org/download.html,目前最新jacorb-2.3.1

2)解压:本例中解压到C:\jacorb-2.3.1 

3)操作系统用户环境变量

添加JACORB_HOME  C:\jacorb-2.3.1

修改CLASSPATH  .;%JAVA_HOME%\jre\lib;%JACORB_HOME%\lib\antlr-2.7.2.jar;

%JACORB_HOME%\lib\backport-util-concurrent.jar;%JACORB_HOME%\lib\idl.jar;

%JACORB_HOME%\lib\jacorb.jar;%JACORB_HOME%\lib\logkit-1.2.jar;

%JACORB_HOME%\lib\picocontainer-1.2.jar;%JACORB_HOME%\lib\slf4j-api-1.5.6.jar;

%JACORB_HOME%\lib\slf4j-jdk14-1.5.6.jar;%JACORB_HOME%\lib\wrapper-3.1.0.jar;

修改PATH添加%JACORB_HOME%\bin

4)修改C:\jacorb-2.3.1\etc\jacorb.properties

ORBInitRef.InterfaceRepository=file:/c:/jacorb-2.3.1/IR_Ref

jacorb.naming.ior_filename=c:/jacorb-2.3.1/NS_Ref

其中IR_RefNS_Ref文件所在的位置可以任意,不需要一定跟这一致。这些文件也不需要预先创建。

5)修改C:\jacorb-2.3.1\bin\jaco.bat.tpl

改名为jaco.bat并将文件内容中的@JAVA_CMD@改成java,将原来的“@JACORB_HOME@”改成“%JACORB_HOME %”。

6)命令行执行ns,查看是否有错误。

 

4. IDL的编译

IDLInterface Definition Language,它并非编程语言,只是一般的描述性语言,通常在IDL文件中包括接口以及一些数据类型的定义,有例为证:

 

module demo
{
    module hello {
        
interface  GoodDay {
            string hello_simple();
            wstring hello_wide( in wstring msg );           
        };       
    };
};

  

通过使用JacORB所带的idl编译工具,我把IDL文件映射成Java代码。

 

修改C:\jacorb-2.3.1\bin idl.bat.tpl

改名为idl.bat,打开,将@JAVA_CMD@直接改成java

然后在命令行执行:H:\>idl  -d  C:\DEV\IDLSample  C:\DEV\IDLSample\server.idl

其中-d选项后面跟的目录为idl文件编译后生成的java文件的输出目录。

 

生成的结果包括以下java文件:

_GoodDayStub.java

GoodDay.java

GoodDayHelper.java

GoodDayHolder.java

GoodDayOperations.java

GoodDayPOA.java

GoodDayPOATie.java

 

5. 编写Server程序

1)首先编写GoodDayImpl继承自GoodDayPOA

 

代码
package  corbaimpl;
 
import  demo.hello.GoodDayPOA;
 
public   class  GoodDayImpl  extends  GoodDayPOA {
 
    @Override
    
public  String hello_simple() {
        
//  TODO Auto-generated method stub
         return   " Hello from CORBA server " ;
    }
 
    @Override
    
public  String hello_wide(String msg) {
        
//  TODO Auto-generated method stub
         return   " Hello from CORBA server, and the parameter 'msg' is:  "   +  msg;
    }
}

  

2)编写程序入口类Main

 

代码
package  corbaimpl;
 
import  java.util.Properties;
import  org.omg.CosNaming.NamingContextExt;
import  org.omg.CosNaming.NamingContextExtHelper;
import  org.omg.PortableServer.POA;
import  org.omg.PortableServer.POAHelper;
 
public   class  Main {
 
    
public   static   void  main(String[] args) {
        System.out.println(
" >>>>Start to initialize CORBA stuff " );
        System.setProperty(
" jacorb.home " " C:\\jacorb-2.3.1 " );
        
try  {
            Properties props 
=   new  Properties();
            
//
            props.put( " org.omg.CORBA.ORBClass " " org.jacorb.orb.ORB " );
            props.put(
" org.omg.CORBA.ORBSingletonClass " " org.jacorb.orb.ORBSingleton " );
            props.put(
" org.omg.CORBA.ORBInitRef.NameService " " corbaloc::localhost:9527/NameService " );
            
//
            org.omg.CORBA.ORB orb  =  org.omg.CORBA.ORB.init(args, props);
            
//
            POA poaRoot  =  POAHelper.narrow(orb.resolve_initial_references( " RootPOA " ));
            
//
            poaRoot.the_POAManager().activate();
            
//
            GoodDayImpl impl  =   new  GoodDayImpl();
            
//
            org.omg.CORBA.Object obj  =  poaRoot.servant_to_reference(impl);
            
//
            NamingContextExt nc  =  NamingContextExtHelper.narrow(orb.resolve_initial_references( " NameService " ));
            
//
            nc.bind(nc.to_name( " CorbaSample_Server " ), obj);
            
//
            orb.run();
        } 
catch  (Exception ex) {
            ex.printStackTrace();
        }
        System.out.println(
" >>>>End the CORBA server " );
    }
 
}

上面的代码主要做的一件事是,实例化一个GoodDayImpl对象,并通过NamingContextExtbind()方法将该对象注册到Name Service上。最后orb.run()方法会阻塞线程,等待Client程序的连接。

 

6. 编写Client程序

 

代码
import  java.util.Properties;
 
import  org.omg.CosNaming.NamingContextExt;
import  org.omg.CosNaming.NamingContextExtHelper;
 
import  demo.hello.GoodDay;
import  demo.hello.GoodDayHelper;
 
 
public   class  Main {
 
    
static  org.omg.CORBA.ORB orb  =   null ;
    
static  GoodDay gd = null ;
    
public   static   void  main(String[] args) {
        System.out.println(
" >>>>Start to initialize client stuff " );
        Properties props 
=   new  Properties();
        props.put(
" org.omg.CORBA.ORBClass " " org.jacorb.orb.ORB " );
        props.put(
" org.omg.CORBA.ORBSingletonClass " " org.jacorb.orb.ORBSingleton " );
        props.put(
" ORBInitRef.NameService " " corbaloc::localhost:9527/NameService " );
 
        
try  {
            orb 
=  org.omg.CORBA.ORB.init(args, props);
 
            NamingContextExt nc 
=  NamingContextExtHelper.narrow(orb.resolve_initial_references( " NameService " ));
            gd 
=  GoodDayHelper.narrow(nc.resolve(nc.to_name( " CorbaSample_Server " )));
            
//
            String s  =  gd.hello_simple();
            System.out.println(s);
            String s2 
=  gd.hello_wide( " \ " call me client\ "" );
            System.out.println(s2);
 
        } 
catch  (Exception e) {
            e.printStackTrace();
        }
    }
 
}

虽然Client也有由IDL编译生成的代码,但它并没有我们后来实现的GoodDayImpl类,但我们却可以在这里调用该类的方法并得到返回,这里面也就是CORBA机制在起作用。

 

7. 运行程序

1)首先,就像我们在概述中的图片中所看见的,我们需要一个Name Service,由于我们装了JacORB,可以用它提供的Name Service,启动方法是在命令行执行:

ns  -DOAPort=9527”,其中9527Name Service进程所要监听的端口,你也可以指定不同的。

2)启动Server,命令行进入相关的classes目录,执行“java corbaimpl.Main

3)启动Client,命令行进入相关的classes目录,执行“java Main”(当时我把Main放在default package下的,所以这里不需要写package名),正常在Client执行后会有两行输出:

Hello from CORBA server.

Hello from CORBA server, and the parameter 'msg' is: “call me client”.

 

8. 遇到的各种错误

话说JacORB的配置确实是比较那个,你知道的……,google出来的也常常是化石级别的帖子。

 

1)配置完成后在命令行执行ns命令,出现错误是“NoClassDefFoundError”,请检查以下两项:

>>JAVA_HOME路径中是否包含空格。此前我一直都把jdk安装在C:\Program files下,所以一直提示“NoClassDefFoundError: org/jacorb/naming/NameServer

>>是否已经将C:\jacorb-2.3.1\lib下必要的jar文件路径都添加到CLASSPATH中了,我比较不求甚解,因为一开始试了几个后还是报NoClassDefFoundError,后来很生气很暴力地把lib下所有的jar都添加到CLASSPATH中了(参见上面的环境变量定义)。

 

2)关于nsorbd

前面我们说了,在运行ServerClient之前,需要将Name Service先运行起来,我在写这个例子的最开始明明ns已经正常启动了,Server却始终连接不上,google到的帖子中有说要执行:start orbd -ORBInitialPort 1050

执行完了之后还真可以连上,Client也工作正常,搞得我很莫名。后来我稍稍研究了一下,发现跟代码中初始化ORB对象前设置的Properties有关系。

如果写成这种形式:

 

props.put( " org.omg.CORBA.ORBInitialPort " " xxx " );
props.put(
" org.omg.CORBA.ORBInitialHost " " localhost " );

则能连上orbd,但连不上JacORBnsServer程序提示org.omg.CORBA.OBJECT_NOT_EXISTns命令行输出错误“Received a request with a non-jacorb object key”)。

如果写成这种形式:

 

props.put( " org.omg.CORBA.ORBInitRef.NameService " " corbaloc::localhost/NameService " );

则能连上JacORBns,但连不上orbd

 

后来知道orbdJava(Sun)提供的一个简单的Name Service实现,而连接它所需要的Properties的写法正是第一种。

 

3)关于corbaloc中的端口

上面提到Server在初始化ORB时提供的属性为:

 

代码
System.setProperty( " jacorb.home " " C:\\jacorb-2.3.1 " );
props.put(
" org.omg.CORBA.ORBClass " " org.jacorb.orb.ORB " );
props.put(
" org.omg.CORBA.ORBSingletonClass " " org.jacorb.orb.ORBSingleton " );
props.put(
" org.omg.CORBA.ORBInitRef.NameService " " corbaloc::localhost:9527/NameService " );

这么写完全可以连上jacorbns,不过~~corbaloc中的端口9527被忽略,即这里可以随便写端口号,或者不写端口,一样能连上。

 

如果~~,如果Server初始化ORB时提供的属性仅为:

 

props.put( " org.omg.CORBA.ORBInitRef.NameService " " corbaloc::localhost:9527/NameService " );

也完全可以连上jacorbns,不过这时你在corbaloc中提供的端口必须是ns正在监听的端口,即启动ns时参数DOAPort的值。

 

而对于Client, 测试发现的情况是无论如何写法,必须在corbaloc中标识出ns的监听端口,否则无法连接。

 

此点目前无解中,存疑。

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值