这两天研究Corba,总是感觉需要在Java的命令行执行“idlj”命令。而且为了产生BaseImpl,总是需要带上一大堆的参数,让人感觉浑身不舒服,今天在网上闲逛,发现居然Maven早就开发出了支持Corba开发的Plug-in插件,为了不失完整性,先在这里将生成Corba服务的两种方式分别进行陈述:
1)利用JDK自带的工具:
a.撰写IDL文件:
module ChinaApp { interface China { string MorningChina(); }; };
b.生成Corba框架代码:
idlj -fall -oldImplBase China.idl
c.执行成功后一共可以得到6个java文件,内容如下:
package ChinaApp; /** * ChinaApp/_ChinaImplBase.java . 由 IDL-to-Java 编译器(可移植),版本 "3.2" 生成 来自 China.idl 2008年3月21日 星期五 上午09时21分56秒 CST */ public abstract class _ChinaImplBase extends org.omg.CORBA.portable.ObjectImpl implements ChinaApp.China, org.omg.CORBA.portable.InvokeHandler { //_TestImplBase.java 用idlj -fall -oldImplBase China.idl // Constructors public _ChinaImplBase() { } private static java.util.Hashtable _methods = new java.util.Hashtable(); static { _methods.put("MorningChina", new java.lang.Integer(0)); } public org.omg.CORBA.portable.OutputStream _invoke( String $method, org.omg.CORBA.portable.InputStream in, org.omg.CORBA.portable.ResponseHandler $rh) { org.omg.CORBA.portable.OutputStream out = null; java.lang.Integer __method = (java.lang.Integer) _methods.get($method); if (__method == null) throw new org.omg.CORBA.BAD_OPERATION(0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE); switch (__method.intValue()) { case 0: // ChinaApp/China/MorningChina { String $result = null; $result = this.MorningChina(); out = $rh.createReply(); out.write_string($result); break; } default: throw new org.omg.CORBA.BAD_OPERATION(0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE); } return out; } // _invoke // Type-specific CORBA::Object operations private static String[] __ids = { "IDL:ChinaApp/China:1.0" }; public String[] _ids() { return (String[]) __ids.clone(); } } // class _ChinaImplBase
package ChinaApp; /** * ChinaApp/_ChinaStub.java . 由 IDL-to-Java 编译器(可移植),版本 "3.2" 生成 来自 China.idl 2008年3月21日 星期五 上午09时21分56秒 CST */ public class _ChinaStub extends org.omg.CORBA.portable.ObjectImpl implements ChinaApp.China { public String MorningChina() { org.omg.CORBA.portable.InputStream $in = null; try { org.omg.CORBA.portable.OutputStream $out = _request("MorningChina", true); $in = _invoke($out); String $result = $in.read_string(); return $result; } catch (org.omg.CORBA.portable.ApplicationException $ex) { $in = $ex.getInputStream(); String _id = $ex.getId(); throw new org.omg.CORBA.MARSHAL(_id); } catch (org.omg.CORBA.portable.RemarshalException $rm) { return MorningChina(); } finally { _releaseReply($in); } } // MorningChina // Type-specific CORBA::Object operations private static String[] __ids = { "IDL:ChinaApp/China:1.0" }; public String[] _ids() { return (String[]) __ids.clone(); } private void readObject(java.io.ObjectInputStream s) throws java.io.IOException { String str = s.readUTF(); String[] args = null; java.util.Properties props = null; org.omg.CORBA.Object obj = org.omg.CORBA.ORB.init(args, props).string_to_object(str); org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate(); _set_delegate(delegate); } private void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException { String[] args = null; java.util.Properties props = null; String str = org.omg.CORBA.ORB.init(args, props).object_to_string(this); s.writeUTF(str); } } // class _ChinaStub
package ChinaApp; /** * ChinaApp/China.java . 由 IDL-to-Java 编译器(可移植),版本 "3.2" 生成 来自 China.idl 2008年3月21日 星期五 上午09时21分56秒 CST */ public interface China extends ChinaOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity { } // interface China
package ChinaApp; /** * ChinaApp/ChinaHelper.java . 由 IDL-to-Java 编译器(可移植),版本 "3.2" 生成 来自 China.idl 2008年3月21日 星期五 上午09时21分56秒 CST */ abstract public class ChinaHelper { private static String _id = "IDL:ChinaApp/China:1.0"; public static void insert(org.omg.CORBA.Any a, ChinaApp.China that) { org.omg.CORBA.portable.OutputStream out = a.create_output_stream(); a.type(type()); write(out, that); a.read_value(out.create_input_stream(), type()); } public static ChinaApp.China extract(org.omg.CORBA.Any a) { return read(a.create_input_stream()); } private static org.omg.CORBA.TypeCode __typeCode = null; synchronized public static org.omg.CORBA.TypeCode type() { if (__typeCode == null) { __typeCode = org.omg.CORBA.ORB.init().create_interface_tc(ChinaApp.ChinaHelper.id(), "China"); } return __typeCode; } public static String id() { return _id; } public static ChinaApp.China read(org.omg.CORBA.portable.InputStream istream) { return narrow(istream.read_Object(_ChinaStub.class)); } public static void write(org.omg.CORBA.portable.OutputStream ostream, ChinaApp.China value) { ostream.write_Object((org.omg.CORBA.Object) value); } public static ChinaApp.China narrow(org.omg.CORBA.Object obj) { if (obj == null) return null; else if (obj instanceof ChinaApp.China) return (ChinaApp.China) obj; else if (!obj._is_a(id())) throw new org.omg.CORBA.BAD_PARAM(); else { org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate(); ChinaApp._ChinaStub stub = new ChinaApp._ChinaStub(); stub._set_delegate(delegate); return stub; } } public static ChinaApp.China unchecked_narrow(org.omg.CORBA.Object obj) { if (obj == null) return null; else if (obj instanceof ChinaApp.China) return (ChinaApp.China) obj; else { org.omg.CORBA.portable.Delegate delegate = ((org.omg.CORBA.portable.ObjectImpl) obj)._get_delegate(); ChinaApp._ChinaStub stub = new ChinaApp._ChinaStub(); stub._set_delegate(delegate); return stub; } } }
package ChinaApp; /** * ChinaApp/ChinaHolder.java . 由 IDL-to-Java 编译器(可移植),版本 "3.2" 生成 来自 China.idl 2008年3月21日 星期五 上午09时21分56秒 CST */ public final class ChinaHolder implements org.omg.CORBA.portable.Streamable { public ChinaApp.China value = null; public ChinaHolder() { } public ChinaHolder(ChinaApp.China initialValue) { value = initialValue; } public void _read(org.omg.CORBA.portable.InputStream i) { value = ChinaApp.ChinaHelper.read(i); } public void _write(org.omg.CORBA.portable.OutputStream o) { ChinaApp.ChinaHelper.write(o, value); } public org.omg.CORBA.TypeCode _type() { return ChinaApp.ChinaHelper.type(); } }
package ChinaApp; /** * ChinaApp/ChinaOperations.java . 由 IDL-to-Java 编译器(可移植),版本 "3.2" 生成 来自 China.idl 2008年3月21日 星期五 上午09时21分56秒 CST */ public interface ChinaOperations { String MorningChina(); } // interface ChinaOperations
2)利用Maven的plug-in插件
a.配置POM文件如下:
<build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>idlj-maven-plugin</artifactId> <executions> <execution> <goals> <goal>generate</goal> </goals> </execution> </executions> <configuration> <compiler>idlj</compiler> <sources> <source> <includes> <include>China.idl</include> </includes> <emitStubs>true</emitStubs> <emitSkeletons>true</emitSkeletons> </source> </sources> </configuration> </plugin> </plugins> </build>
b.执行编译打包成功后会得到与其面方法大体相同的几个类,只不过其中有一个类值得在这里提一下,与前面不同的是在Maven的Plug-in生成的类中没有BaseImpl类,但是多了一个POA类,这两个类继承的东西虽然有些差异,但是实现的方法以及方法的实现细节还是基本上相同的,下面就列出POA类的细节:
package ChinaApp; /** * ChinaApp/ChinaPOA.java . 由 IDL-to-Java 编译器(可移植),版本 "3.2" 生成 来自 D:/corba/src/main/idl/China.idl 2008年3月21日 星期五 */ public abstract class ChinaPOA extends org.omg.PortableServer.Servant implements ChinaApp.ChinaOperations, org.omg.CORBA.portable.InvokeHandler { // Constructors private static java.util.Hashtable _methods = new java.util.Hashtable(); static { _methods.put("MorningChina", new java.lang.Integer(0)); } public org.omg.CORBA.portable.OutputStream _invoke( String $method, org.omg.CORBA.portable.InputStream in, org.omg.CORBA.portable.ResponseHandler $rh) { org.omg.CORBA.portable.OutputStream out = null; java.lang.Integer __method = (java.lang.Integer) _methods.get($method); if (__method == null) throw new org.omg.CORBA.BAD_OPERATION(0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE); switch (__method.intValue()) { case 0: // ChinaApp/China/MorningChina { String $result = null; $result = this.MorningChina(); out = $rh.createReply(); out.write_string($result); break; } default: throw new org.omg.CORBA.BAD_OPERATION(0, org.omg.CORBA.CompletionStatus.COMPLETED_MAYBE); } return out; } // _invoke // Type-specific CORBA::Object operations private static String[] __ids = { "IDL:ChinaApp/China:1.0" }; public String[] _all_interfaces(org.omg.PortableServer.POA poa, byte[] objectId) { return (String[]) __ids.clone(); } public China _this() { return ChinaHelper.narrow(super._this_object()); } public China _this(org.omg.CORBA.ORB orb) { return ChinaHelper.narrow(super._this_object(orb)); } } // class ChinaPOA
说了半天,可能还没有说清楚什么是Corba,下面就贴一些Corba的八卦,CORBA 公用对象请求代理(调度)程序体系结构(Common Object Request Broker Architecture),缩写为 CORBA,是对象管理组织(Object Management Group)对应当今快速增长的软硬件的协同工作能力的要求而提出的方案。简而言之,CORBA 允许应用程序和其他的应用程序通讯,而不论他们在什么地方或者由谁来设计。CORBA 1.1 由对象管理组织在 1991 年发布。他定义了接口定义语言(IDL)和应用编程接口(API),从而通过实现对象请求代理(ORB)来激活客户/服务器的交互。CORBA 2.0 于 1994 年的 12 月发布。他定义了如何跨越不同的 ORB 提供者而进行通讯。
ORB 是一个中间件,他在对象间建立客户-服务器的关系。通过 ORB,一个客户可以很简单地使用服务器对象的方法而不论服务器是在同一机器上还是通过一个网络访问。ORB 截获调用然后负责找到一个对象实现这个请求,传递参数和方法,最后返回结果。客户不用知道对象在哪里,是什么语言实现的,他的操作系统以及其他和对象接口无关的东西。
在传统的客户/服务器程序中,开发者使用他们自己设计的或者公认的标准定义设备之间的协议。协议的定义依赖于实现的语言,网络的传输和其他许许多多因素。ORB 将这个过程简单化。使用 ORB,协议定义是通过应用接口,而该接口是接口定义语言(IDL)的一个实现,他和使用的编程语言无关的。并且 ORB 提供了很大的灵活性。他让程序员选择最适当的操作系统,运行环境和设计语言来建设系统中每个组件。更重要的是,他允许集成已经存在的组件。
CORBA 是在面向对象标准化和互操作性道路上的一个信号。通过 CORBA,用户不必要知道软硬件的平台和他们处在企业网的什么地方就可以操作。
ORB 结构
下面我来用些图形说明一下:
通过 ORB 发送请求
面的图形说明的是客户端发送一个请求到对象的实现。客户端是希望对某对象执行操作的实体。对象的实现是一片代码和数据来实际实现对象。ORB 负责下面的必要的机制:对该请求找到对象的实现,让对象的实现准备好接受请求,和请求交换数据。客户端的接口完全独立于对象的位置,其实现的语言和其他不影响对象接口的东西。
ORB 接口的结构
上面的图形显示的是一个独立的对象请求代理(ORB)的结构。ORB 的接口是灰色的矩形。箭头说明 ORB 的调用关系。
为了提出一个请求,客户端可以使用动态调用接口(Dynamic Invocation Interface)(和目标对象的接口独立)或者一个 OMG 的 IDL 占位程序(具体的占位程序依赖于目标对象的接口)。客户端也可以直接和 ORB 在某些地方交互。
对象的实现通过 OMG 的 IDL 产生的骨架或者是一个动态骨架的调用来接受请求。对象的实现可能在处理请求或其他的时候调用 ORB。
对象接口定义的定义可以有下面两种方式。接口可以通过接口定义语言静态的定义,这叫做 OMG 的 IDL。该语言按照可以进行的操作和该操作的参数定义对象类型。或者(也可以作为补充),接口可以加入到 Interface Repository service。该服务描述了该接口作为一个对象的组件,并允许运行时访问这些组件。在任何 ORB 实现中,IDL 和 Interface Repository 有相同的表达能力。
客户端使用占位程序或者动态调用接口
客户端通过访问对象的对象引用和了解对象的类型及要求执行的操作来发布一个请求。客户调用占位程序例程来请求或者动态构造请求。
无论动态还是占位程序的接口都可以相同实现。接收方不可能知道请求是如何发布的。
对象的实现接受请求
ORB 向对象实现定位适当的代码,传递参数,传输控制。这一切都通过 IDL 骨架或者动态骨架。骨架对于不同的接口和对象适配器是不同的。在执行该请求的时候,对象的实现可能由 ORB 通过对象适配器来获得一定的服务。当请求完成,控制和输出值返回给客户。
对象的实现可能会选择使用的对象适配器。该决定基于对象的实现要求的服务。
接口和 Implementation Repositories
上图说明的是接口和实现信息如何让客户和对象实现访问的。接口用 OMG 的 IDL 和/或 Interface Repository 定义。该定义用于产生客户占位程序和对象的实现的骨架。
对象的实现的信息在安装时就提供好了,储存在 Implementation Repository 中以便请求发布的时候使用。