(以下标*的环境参数是需要用户自己配置的。其他参数安装程序会自动配置,但由于 安装不得当或其他原因,也可能不正确,这里列出来,对照检査一遍是否都正确。另外, 我们假设程序安装在 C- \Program filesliona目录下,如果不是,作相应改变。) 1. User variables CLASSPATH (* 在 CLASSPATH的末尾添加以下路径 C: Program FilesllONAlorbix art\1.2\localhost;\, \classes (添加的部分与前面部分用分号;隔开,下同) It javac, It Java工具会在运行时添加 C \Program Files\\orbix art12 classes,所以不 必在这里设置。增加当前目录、和 \classes会对你工作带来便利 2) PATH 在末尾增加C: Program filesionalbin 这样你可以在任何目录运行Obix2000的命令了。 2. System variables: 1)IT PRODUCT DIR() 如果没有 IT PRODUCT DIR,单击”new”按钮,添加它,其值设置为C: Program FileslIona,也即程序安装路径。这个参数非常重要, Orbix自动设置其他关于目录的参数 时都基于它 2)JAVA HOME ( :加JAⅤA_HOME,设置为 C: Builder4jdkl.3,或其他JDK路径。 It javac和 It _ java 的运行需要它 3) PATH 增加C: Program fileslionabin User variables和 System variables中只需设置一个就行,当然都设置也无妨 4)IT IDL CONFIG FILE (* FilesllOl41"iler工具需要这个参数,添加这个参数,设置为 C: \Program 在开始编程之前,请确保上述设置是正确的。当你使用命令行方式时,如果你改变了设 置,为使改变生效,需要重新开一个DOS窗口,然后在此窗口下操作,但不必重启机器 22编写第一个 CORBA程序 221命令行方式 我们先介绍在命令行方式下的开发步骤,编写一些小型的测试程序可以使用这种方式, 因为没有必要启动庞大的 J Builder4。后面我们再介绍在 J Builder4集成开发环境下的 使用方法。实际上两者步骤是类似的,只是方便程度不一样。 通常,开发一个 CORBA应用的大致步骤如下: )定义IDL。 2)用 IDL complier将IDL编译成 Client Stub代码和 Server Skeleton代码。 3)编写 Server方的实现( Implementation)代码
11 (以下标*的环境参数是需要用户自己配置的。其他参数安装程序会自动配置,但由于 安装不得当或其他原因,也可能不正确,这里列出来,对照检查一遍是否都正确。另外, 我们假设程序安装在 C:\Program Files\IONA 目录下,如果不是,作相应改变。) 1. User variables: 1)CLASSPATH(*) 在 CLASSPATH 的末尾添加以下路径: C:\Program Files\IONA\orbix_art\1.2\localhost; .\;.\classes (添加的部分与前面部分用分号;隔开,下同) it_javac, it_java工具会在运行时添加C:\Program Files\IONA\orbix_art\1.2\classes, 所以不 必在这里设置。增加当前目录 .\ 和.\classes 会对你工作带来便利。 2)PATH 在末尾增加 C:\Program Files\IONA\bin 这样你可以在任何目录运行 Orbix2000 的命令了。 2.System variables: 1)IT_PRODUCT_DIR (*) 如果没有 IT_PRODUCT_DIR,单击”new”按钮,添加它,其值设置为 C:\Program Files\IONA,也即程序安装路径。这个参数非常重要,Orbix 自动设置其他关于目录的参数 时都基于它。 2)JAVA_HOME (*) 添加 JAVA_HOME,设置为 C:\JBuilder4\jdk1.3,或其他 JDK 路径。it_javac 和 it_java 的运行需要它。 3)PATH 增加 C:\Program Files\IONA\bin User variables 和 System variables 中只需设置一个就行,当然都设置也无妨。 4)IT_IDL_CONFIG_FILE(*) idl compiler 工具需要这个参数,添加这个参数,设置为 C:\Program Files\IONA\orbix_art\1.2\etc 在开始编程之前,请确保上述设置是正确的。当你使用命令行方式时,如果你改变了设 置,为使改变生效,需要重新开一个 DOS 窗口,然后在此窗口下操作,但不必重启机器。 2.2 编写第一个 CORBA 程序 2.2.1 命令行方式 我们先介绍在命令行方式下的开发步骤,编写一些小型的测试程序可以使用这种方式, 因为没有必要启动庞大的 JBuilder 4。 后面我们再介绍在 JBuilder 4 集成开发环境下的 使用方法。实际上两者步骤是类似的,只是方便程度不一样。 通常,开发一个 CORBA 应用的大致步骤如下: 1)定义 IDL。 2)用 IDL complier 将 IDL 编译成 Client Stub 代码和 Server Skeleton 代码。 3)编写 Server 方的实现(Implementation)代码
4)编写 Server 5)编写 Client )编译和调试 7)运行程序。 编写 Server Implementation和编写 Server不是一回事。 Server和 Client都是带有main( 函数的可执行的程序。但 Server Implementation是对 interface的实现,它可以单独放在 个java文件中,也可以和 Server放在同一个文件中 下面以一个简单的例子详细讲解各个步骤。 第一步:定义DL 首先建立一个工作目录,这里假设为 D: myworklsimpleDemo 然后编写IDL。这个例子我们使用1.21节中 grid.id,一个对二维数组操作的例子。可 以使用任何文本编辑器编写,如 UltraEdit等。之后保存到 D myworklsimpleDemo下。 grid idl定义了一个接口 interface grid。其中定义两个方法get0和setO,用以获取和设置 数组元素值。注意属性( attribute)的定义,这是C和JAVA中没有的概念(在 Delphi中有 这个概念),实际上它就相当于类的数据定义,但在映射到Java时被映射成方法 第二步:编译DL为 Java stub和 Skeleton. 打开DOs窗口,进入到 D: \myworklsimpleDemo目录,在Dos命令提示符下键入: idl-jbase-jpoa grid idl 参数- base表示生成 java stub code,参数-jpoa表示生成 java skeleton code,在 Orbix2000 中,骨架代码使用POA方式。 缺省情况下idl编译器会创建一个java_ output的目录,如果ld中有 module定义,还会 生成与此 module同名的子目录,并将编译后生成的java程序放在此目录中 你可以开关参数控制编译方式,例如,如果想将客户stub和服务器 skeleton代码分开 可以键入: idl-jbase: -Oclient grid idl idl-jpoa: - Oserver grid idl -O参数控制输出目录。编译器会自动生成 client和 server目录,并将代码分别放在这 目录中 我们知道,id编译器会将 module映射成 package,缺省情况下, module simpleDemo 映射成 package simpleDemo。如果想自己控制 package的生成,例如要生成 package demos. simpleDemo形式的包,可以 idl-jbase: -Oclient-jbase: - Demos grid idl 编译器会在 module指定的包前再加上-P参数指定的包前缀,即生成 package demos. simpleDemo。注意不要写成- Pdemos. simpleDemo,否则会生成 package demos. simple Demo. simpleDemo 附录B中列出了d命令的用法。 注意 我们看看id生成的stub和 skeleton代码。 Stub Code包含以下文件 grid. java 定义了接口 interface grid, public interface grid
12 4)编写 Server。 5)编写 Client。 6)编译和调试。 7)运行程序。 编写 Server Implementation 和编写 Server 不是一回事。Server 和 Client 都是带有 main() 函数的可执行的程序。但 Server Implementation 是对 interface 的实现,它可以单独放在一 个.java 文件中,也可以和 Server 放在同一个文件中。 下面以一个简单的例子详细讲解各个步骤。 第一步:定义 IDL 首先建立一个工作目录,这里假设为 D:\mywork\simpleDemo。 然后编写 IDL。这个例子我们使用 1.2.1 节中 grid.idl,一个对二维数组操作的例子。可 以使用任何文本编辑器编写,如 UltraEdit 等。之后保存到 D:\mywork\simpleDemo 下。 grid.idl 定义了一个接口 interface grid。其中定义两个方法 get()和 set(),用以获取和设置 数组元素值。注意属性(attribute)的定义,这是 C 和 JAVA 中没有的概念(在 Delphi 中有 这个概念),实际上它就相当于类的数据定义,但在映射到 Java 时被映射成方法。 第二步:编译 IDL 为 Java Stub 和 Skeleton. 打开 DOS 窗口,进入到 D:\mywork\simpleDemo 目录,在 Dos 命令提示符下键入: idl –jbase –jpoa grid.idl 参数-jbase 表示生成 java stub code,参数–jpoa 表示生成 java skeleton code,在 Orbix 2000 中,骨架代码使用 POA 方式。 缺省情况下 idl 编译器会创建一个 java_output 的目录,如果 idl 中有 module 定义,还会 生成与此 module 同名的子目录,并将编译后生成的.java 程序放在此目录中。 你可以开关参数控制编译方式,例如,如果想将客户 stub 和服务器 skeleton 代码分开, 可以键入: idl –jbase:-Oclient grid.idl idl –jpoa:-Oserver grid.idl -O 参数控制输出目录。编译器会自动生成 client 和 server 目录,并将代码分别放在这 目录中。 我们知道,idl 编译器会将 module 映射成 package,缺省情况下,module simpleDemo 映射成 package simpleDemo。如果想自己控制 package 的生成,例如要生成 package demos.simpleDemo 形式的包,可以: idl –jbase:-Oclient –jbase:-Pdemos grid.idl 编译器会在 module 指定的包前再加上-P 参数指定的包前缀,即生成 package demos.simpleDemo 。 注 意 不 要 写 成 -Pdemos.simpleDemo , 否 则 会 生 成 package demos.simpleDemo.simpleDemo。 附录 B 中列出了 idl 命令的用法。 注意, 我们看看 idl 生成的 stub 和 skeleton 代码。 Stub Code 包含以下文件: grid.java 定义了接口 interface grid, public interface grid
tends gridOpera org. omg CORBA Object, CORBA } 接由 grid idl中 d映射而来 Stub. java 桩代码,定义了 class_ gridStub public class gridStub extends org. omg CORBA portable. Objectlmpl plements grid t class gridStub中实现了客户方的setO和geto等方法,它 们封装了ORB的功能,截取客户的调用,执行 Marshaling/Unmarshing等操作,最终得到调用结果。也就 是说,在客户方声明一个grid类型的对象,实际上使用 ridHelper操作得到的是一个 gridStub类型的实例,调用 grid上的方法实际上是调用 gridStub上的方法。 gridHelper. java 定义 public class gridHelper{} 帮助客户方grid对象生成一个 gridStub类型的实例,同时 得到服务器对象的引用。 gridHolder. java 定义 public final class grid Holder implements org. omg CORBA portable Streamable 当需要处理out, inout类型的参数时,需要这个类 gridOperations. java EX public interface gridOperations int get( i 这个接口实际上是 Server使用的。当客户方需要使用 callback功能时,也需要这个接口。 Skeleton Code则包含以下文件 gridPOA. java 定义类 abstract public class gridPOA extends org. omg. Portable Server. Servant implements org. omg CORBA portable. InvokeHandler gridOperations Server方的 Implementation代码直接继承自这个类 gridPOATie. java 定义类 public class gridPOATie extends simpleDemo. gridPOA
13 extends gridOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity { } 直接由 grid.idl 中的 interface grid 映射而来。 _gridStub.java 桩代码,定义了 class _gridStub public class _gridStub extends org.omg.CORBA.portable.ObjectImpl implements grid{ public void set(){…} ; pubic int get(){..}; …} class _gridStub 中实现了客户方的 set()和 get()等方法,它 们封装了 ORB 的 功 能 , 截 取 客 户 的 调 用 , 执 行 Marshaling/Unmarshing 等操作,最终得到调用结果。也就 是说,在客户方声明一个 grid 类型的对象,实际上使用 gridHelper 操作得到的是一个_gridStub 类型的实例,调用 grid 上的方法实际上是调用_gridStub 上的方法。 gridHelper.java 定义 public class gridHelper{ } 帮助客户方 grid 对象生成一个_gridStub 类型的实例,同时 得到服务器对象的引用。 gridHolder.java 定义 public final class gridHolder implements org.omg.CORBA.portable.Streamable{} 当需要处理 out,inout 类型的参数时,需要这个类。 gridOperations.java 定义 public interface gridOperations{ void set() int get() } 这个接口实际上是 Server 使用的。当客户方需要使用 callback 功能时,也需要这个接口。 Skeleton Code 则包含以下文件: gridPOA.java 定义类 abstract public class gridPOA extends org.omg.PortableServer.Servant implements org.omg.CORBA.portable.InvokeHandler, gridOperations { } Server 方的 Implementation 代码直接继承自这个类。 gridPOATie.java 定义类 public class gridPOATie extends simpleDemo.gridPOA {
当使用代理方式而不是继承方式创建 Server Object时 使用这个类。 jpoa参数只生成上述两个文件,实际上 Skeleton Code也包含 gridOperations. java,因 为 class gridPOA就是实现 gridOperations的 上述接口(类)的继承关系如下: gridOperations gI gridPOA gridStub gridImpl grid idl中只定义了一个 interface grid,实际上如果定义了多个 interface,那么对每个 nterface都会生成和上面类似的一套代码 第三步:编写 Server方的 Implementation代码(即编写 Servant) 到现在为止,我们才开始真正编写代码。 引入了POA概念后, Server方的实现对象称为 Servant,编写 Implementation代码实际 上就是对IDL定义的每个 interface,都编写一个 Servant,其中要现实 interface中定义的每 个方法 这里我们将 Servant类定义为 class gridImpl,类名字可以自己随便取,通常都命名为 xxxlmpl的形式。 Class gridImpl直接继承自 gridPOA。 在 D: \myworklsimpleDemo目录下创建一个 gridlmpl. java文件,内容如下 package simple Dem public class gridlmpl extends gridPOA( short m height; //store the height short m width: // store the width int m_array[[: a 2D array to hold the grid data private int i=0 private int =0 rivate int n=0: public gridImpl(short width, short height) m array =new int[width][height]; //allocate the 2D array m height height; //set up height m width =width; // set up width
14 } 当使用代理方式而不是继承方式创建 Server Object 时, 使用这个类。 -jpoa 参数只生成上述两个文件,实际上 Skeleton Code 也包含 gridOperations.java,因 为 class gridPOA 就是实现 gridOperations 的。 上述接口(类)的继承关系如下: gridOperations grid _gridStub gridPOA gridImpl grid.idl 中只定义了一个 interface grid,实际上如果定义了多个 interface, 那么对每个 interface 都会生成和上面类似的一套代码。 第三步:编写 Server 方的 Implementation 代码(即编写 Servant) 到现在为止,我们才开始真正编写代码。 引入了 POA 概念后,Server 方的实现对象称为 Servant, 编写 Implementation 代码实际 上就是对 IDL 定义的每个 interface,都编写一个 Servant,其中要现实 interface 中定义的每 个方法。. 这里我们将 Servant 类定义为 class gridImpl,类名字可以自己随便取,通常都命名为 xxxImpl 的形式。Class gridImpl 直接继承自 gridPOA。 在 D:\mywork\simpleDemo 目录下创建一个 gridImpl.java 文件,内容如下: package simpleDemo; public class gridImpl extends gridPOA{ short m_height; // store the height short m_width; // store the width int m_array[][]; // a 2D array to hold the grid data private int i=0; private int j=0; private int n=0; public gridImpl(short width, short height) { m_array = new int[width][height]; // allocate the 2D array m_height = height; // set up height m_width = width; // set up width
} Implementation of the method which reads the height attribute public short height eturn m height } Implementation of the method which reads the width attribute public short width return m width Implementation of the set operation public void set (short x, short y, int value) n++; System. out. printIn "+n+"H+OA Server/HU"+i+"iH+OA grid. seto----); System.out. printIn ("In grid. seto X=+x) System.out. println ('In grid. seto="+y) System.out. printIn ("In grid set( value="+ value) m arrays」[Ⅹ]=vaue; Implementation of the get operation public int get(short x, short y) System. out. printin ("---HU"+n+"'TH+OA Server /HU"+j+"'TH+OA grid. get(----) int value = m arraylylx System. out. printIn ("In grid geox="+x)
15 } /* * Implementation of the method which reads the height attribute */ public short height() { return m_height; } /* * Implementation of the method which reads the width attribute */ public short width() { return m_width; } /* * Implementation of the set operation */ public void set (short x, short y, int value) { i++; n++; System.out.println ("-----µÚ "+n+" ´Îµ÷Óà Server / µÚ "+i+" ´Îµ÷Óà grid.set()----"); System.out.println ("In grid.set() x = " + x); System.out.println ("In grid.set() y = " + y); System.out.println ("In grid.set() value = " + value); m_array[y][x] = value; } /* * Implementation of the get operation */ public int get (short x, short y) { j++; n++; System.out.println ("-----µÚ "+n+" ´Îµ÷Óà Server / µÚ "+j+" ´Îµ÷ÓÃ: grid.get()----"); int value = m_array[y][x]; System.out.println ("In grid.get() x = " + x);