您的位置:首页 > 编程语言 > Java开发

JAVA&CORBA详解

2012-11-21 13:38 267 查看
Java IDL技术在Java平台上添加了CORBA(Common Object Request Broker Architecture)功能,提供了基于标准的互操作能力和连接性。Java IDL技术使得分布式的Java Web应用能够通过使用工业标准的IDL和IIOP(Internet Inter-ORB Protocol)来透明地调用远程网络服务的操作。运行时组件(Runtime Components)包括了一个用于分布式计算且使用IIOP通信的Java ORB.

可移植对象适配器(Portable Object Adapter,POA)

CORBA对象的负责分隔服务器端远程调用句柄(handler)到远程对象和它的服务者(servant)。对象由远程调用所暴露,而服务者包含实际处理这些请求的方法。每个对象都可以选择服务者为静态的(一次)或动态的(每个远程调用),在这两种情况下,都允许调用转移到另一台服务器。

在服务器端,POA形成了类似树状的结构,每个POA都负责一到多个服务的对象。树的分支可以是独立活动的、或钝化的,服务者调用有不同的代码和不同的请求处理策略。

API规范

* org.omg.CORBA 包 - 提供了OMG CORBA APIs到Java编程语言的映射

* org.omg.CosNaming 包 - 为Java IDL提供命名服务

* org.omg.PortableServer 包 - 为建立服务器端的可移植的、跨越多ORB的应用程序提供类和接口

* org.omg.PortableInterceptor 包 - 提供了注册ORB钩子的机制,此钩子通过ORB服务能截取正常的ORB执行流

* org.omg.DynamicAny 包 - 提供了使得任何值都能被动态解释(或遍历)和通过DynAny对象构造出来的类和接口

* org.omg.CORBA.ORB - 为CORBA ORB功能的API

分布式对象之间的关系有两方面:客户端和服务器。

服务器提供远程接口,客户端调用远程接口。

在客户端,应用程序包括远程对象的引用。该对象引用有stub方法,它是独立的远程方法。stub方法实际连接到ORB,因此调用它实际上转发调用到服务器。

在服务器端,ORB使用skeleton代码翻译远程调用为本地对象的方法调用。Skeleton把调用转换成指定实现的格式,并在方法中调用。当方法返回时,Skeleton代码转换方法调用的结果或错误,经ORB送回客户端。

Java IDL开发过程

1)定义远程接口

使用IDL语言为远程对象定义接口。

【Billing.idl源代码】如下:

[java]
view plaincopy

// 声明CORBA IDL模块
module BillingApp{
// 声明接口
interface Billing{
string successBilling();
oneway void shutdown();
};
};

2)编译远程接口

使用idlj编译器生成Java语言的stub和skeleton源文件。

idlj编译器缺省只生成客户端的binding代码。如果同时需要客户端的bindings和服务器端的skeletons,必须加上-fall选项。

使用POA(Portable Object Adaptor)的优点:

· 允许编程者构建对象在不同ORB产品之间的可移植实现

· 支持带持久化标识的对象

· 对对象的透明活动提供支持

· 允许单个servant支持多种对象同时标识

注意:确定jdk/bin目录下有:idlj、java、javac、orbd

命令:

idlj -fall Billing.idl

在当前目录下生成BillingApp目录,包含如下六个文件:

· Billing.java ————> 此接口包含IDL接口的Java版本。它继承自org.omg.CORBA.Object,提供标准的CORBA对象功能。

· BillingHelper.java ————> 此类提供辅助功能,Helper类负责读写数据类型到CORBA流,以及插入和提取数据类型。

· BillingHolder.java ————> This final class holds a public instance member of type Billing.

· BillingOperations.java ————> 此接口包含successBilling()和shutdown()方法。

· BillingPOA.java ————> 此抽象类是基于流的服务器Skeleton,为服务器提供基本的CORBA功能。它继承org.omg.PortableServer.Servant,实现了InvokeHandler接口和BillingOperations接口。服务器类BillingServant继承BillingPOA。

· _BillingStub.java ————> 此类是客户端stub,为客户端提供CORBA功能。它继承org.omg.CORBA.Object,提供标准CORBA对象功能。还扩展了BillingOperations接口和org.omg.CORBA.portable.IDLEntity接口。

3)实现服务器端

一旦使用idlj编译器后,就可以使用它产生的Skeleton装配服务器应用程序了。另外要实现远程接口方法,服务器代码应包含启动ORB和等待远程客户端调用的机制。

服务器端由两个类组成,一个是servant,另一个是Server。

servant是BillingImpl类,是Billing IDL接口的实现,每个Billing实例均由BillingImpl实例实现。servant是BillingPOA的子类。

servant包含了IDL定义的所有方法,与通常的Java方法类似。

server类含服务器的main()方法,它:

· 创建和初始化ORB实例

· 获得根POA的引用并激活POAManager

· 创建一个Servant实例(CORBA的Billing对象的实现)并通知ORB

· 获得根命名上下文

· 在命名上下文用“Billing”名注册新对象

· 等待客户端调用此新对象

【BillingImpl.java源码】:

[java]
view plaincopy

01.import org.omg.CORBA.ORB;
02.import BillingApp.*;
03.class BillingImpl extends BillingPOA{
04. private ORB orb;
05. public void setORB(ORB orb_val){
06. this.orb = orb_val;
07. }
08. /**
09. * 实现successBilling()方法
10. */
11. public String successBilling() {
12. return "/nBilling success!!/n";
13. }
14. /**
15. * 实现shutdown()方法
16. */
17. public void shutdown(){
18. orb.shutdown(false);
19. }
20.}
import org.omg.CORBA.ORB;
import BillingApp.*;
class BillingImpl extends BillingPOA{
private ORB orb;
public void setORB(ORB orb_val){
this.orb = orb_val;
}
/**
* 实现successBilling()方法
*/
public String successBilling() {
return "/nBilling success!!/n";
}
/**
* 实现shutdown()方法
*/
public void shutdown(){
orb.shutdown(false);
}
}

【BillingServer.java源码】:

[java]
view plaincopy

view plaincopy to clipboardprint?
01.import org.omg.CORBA.ORB;
02.import org.omg.CosNaming.NameComponent;
03.import org.omg.CosNaming.NamingContextExt;
04.import org.omg.CosNaming.NamingContextExtHelper;
05.import org.omg.PortableServer.POA;
06.import BillingApp.*;
07.public class BillingServer {
08. public static void main(String args[]){
09. try{
10. // 创建和初始化ORB
11. ORB orb = ORB.init(args, null);
12. // 获得根POA的引用并激活POAManager
13. POA rootpoa = (POA)orb.resolve_initial_references("RootPOA");
14. rootpoa.the_POAManager().activate();
15. // 创建servant并注册到ORB
16. BillingImpl billingImpl = new BillingImpl();
17. billingImpl.setORB(orb);
18. // 从servant获得对象引用
19. org.omg.CORBA.Object ref = rootpoa.servant_to_reference(billingImpl);
20. Billing href = BillingHelper.narrow(ref);
21. // 得到根命名上下文
22. org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
23. // 使用命名上下文,它是互操作命名服务规范的一部分
24. NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
25. // 在命名中绑定对象引用
26. String name = "Billing";
27. NameComponent path[] = ncRef.to_name(name);
28. ncRef.rebind(path, href);
29. System.out.println("BillingServer is ready and waiting...");
30. // 等待客户端调用
31. orb.run();
32. }catch(Exception e){
33. System.err.println("ERROR:"+e);
34. e.printStackTrace(System.out);
35. }
36. System.out.println("BillingServer Exiting ...");
37. }
38.}
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 BillingApp.*;
public class BillingServer {
public static void main(String args[]){
try{
// 创建和初始化ORB
ORB orb = ORB.init(args, null);
// 获得根POA的引用并激活POAManager
POA rootpoa = (POA)orb.resolve_initial_references("RootPOA");
rootpoa.the_POAManager().activate();
// 创建servant并注册到ORB
BillingImpl billingImpl = new BillingImpl();
billingImpl.setORB(orb);
// 从servant获得对象引用
org.omg.CORBA.Object ref = rootpoa.servant_to_reference(billingImpl);
Billing href = BillingHelper.narrow(ref);
// 得到根命名上下文
org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
// 使用命名上下文,它是互操作命名服务规范的一部分
NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
// 在命名中绑定对象引用
String name = "Billing";
NameComponent path[] = ncRef.to_name(name);
ncRef.rebind(path, href);
System.out.println("BillingServer is ready and waiting...");
// 等待客户端调用
orb.run();
}catch(Exception e){
System.err.println("ERROR:"+e);
e.printStackTrace(System.out);
}
System.out.println("BillingServer Exiting ...");
}
}

4)实现客户端

与第三步类似,可以使用idlj产生的stub作为客户端应用程序的基础。客户端代码建立于stub之上,启动ORB,使用服务器提供的命名服务查询,获得远程对象的引用,调用其方法。

【BillingClient.java源码】:

[java]
view plaincopy

01.import org.omg.CORBA.ORB;
02.import org.omg.CosNaming.NamingContextExt;
03.import org.omg.CosNaming.NamingContextExtHelper;
04.import BillingApp.*;
05.public class BillingClient {
06. static Billing billingImpl;
07. public static void main(String args[]){
08. try{
09. // 创建和初始化ORB
10. ORB orb = ORB.init(args, null);
11. System.out.println("ORB initialised");
12. // 获得根命名上下文
13. org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
14. // 使用NamingContextExt代替命名上下文,它是互操作命名服务的一部分
15. NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
16. // 在命名中解析对象引用
17. String name = "Billing";
18. billingImpl = BillingHelper.narrow(ncRef.resolve_str(name));
19.
20. System.out.println("Obtained a handle on server object: "+billingImpl);
21. System.out.println(billingImpl.successBilling());
22. billingImpl.shutdown();
23. }catch(Exception e){
24. System.out.println("ERROR: "+e);
25. e.printStackTrace(System.out);
26. }
27. }
28.}
import org.omg.CORBA.ORB;
import org.omg.CosNaming.NamingContextExt;
import org.omg.CosNaming.NamingContextExtHelper;
import BillingApp.*;
public class BillingClient {
static Billing billingImpl;
public static void main(String args[]){
try{
// 创建和初始化ORB
ORB orb = ORB.init(args, null);
System.out.println("ORB initialised");
// 获得根命名上下文
org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
// 使用NamingContextExt代替命名上下文,它是互操作命名服务的一部分
NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef);
// 在命名中解析对象引用
String name = "Billing";
billingImpl = BillingHelper.narrow(ncRef.resolve_str(name));

System.out.println("Obtained a handle on server object: "+billingImpl);
System.out.println(billingImpl.successBilling());
billingImpl.shutdown();
}catch(Exception e){
System.out.println("ERROR: "+e);
e.printStackTrace(System.out);
}
}
}

5)启动应用程序

要运行服务器和客户端,必须先启动命名服务,再启动服务器,最后运行客户端。

此例用到命名服务,它使得servant对象的操作对客户端有效。服务器需要命名服务的对象引用,命名服务可以发布对象引用实现各种接口。客户端使用对象引用来调用方法。

Java SE 1.4以上提供了两种可选的命名服务:

· tnameserv

一种透明的命名服务

· orbd

包含自启动服务、透明的命名服务、持久化命名服务和命名管理器的后台处理进程。

本例使用orbd。

5.1)启动orbd

注意:Solaris系统运行要求root权限并以1024端口开始进程。因此,对所有OS,可以选用大于或等于1024的端口以实现统一。

-ORBInitialPort选项用于指定端口(非缺省状态)。

例如:假定使用1050端口的Java ORB Daemon(orbd),命令如下:

start orbd -ORBInitialPort 1050 -ORBInitialHost localhost

5.2)开始Billing服务器

java BillingServer -ORBInitialPort 1050 -ORBInitialHost localhost

注:如在同一台主机上运行,可省略-ORBInitialHost localhost

5.3)运行客户端应用程序

java BillingClient -ORBInitialPort 1050 -ORBInitialHost localhost
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: