このドキュメントでは、IDLからJava言語へのマッピング仕様に従ってIDL-to-Javaコンパイラで生成したコード(仕様の詳細については準拠に関するドキュメントを参照)、およびサンプルのクライアント・アプリケーションとサーバー・アプリケーションについて説明します。
ここに記載したコードの詳細な説明については、入門チュートリアル「Java IDL入門」を参照してください。
次のファイル(Hello.idl)はOMGインタフェース定義言語(IDL)で記述されたもので、CORBAオブジェクトのsayHello()オペレーションが文字列(string)を返しshutdown()メソッドがORBを停止させています。OMG IDLは、分散型アプリケーションでプログラミング言語に依存しないオペレーション・インタフェースを指定するために設計された、純粋な宣言型の言語です。IDLはさまざまなプログラミング言語にマッピングできます。IDLをJavaにマッピングする方法は「IDLとJava言語のマッピングのサマリー」で説明しています。
OMG IDLの構文とセマンティックスの詳細は、CORBA仕様の第3章を参照してください。
Hello.idl
module HelloApp { interface Hello { string sayHello(); oneway void shutdown(); }; };
idljコンパイラは、IDL-to-Javaマッピングを使用してIDLインタフェース定義を対応するJavaインタフェース、クラスおよびメソッドに変換します。次に、それを使用してクライアントとサーバー・コードを実装できます。次のファイルは、次のコマンドを使用してIDL-to-JavaコンパイラでHello.idlをコンパイルすると生成されます。
idlj -fall Hello.idl
シグニチャ・インタフェース・ファイルHello.javaは、org.omg.portable.IDLEntity、org.omg.CORBA.Object、およびオペレーション・インタフェースHelloOperationsを拡張しています。シグニチャ・インタフェースは、指定した型のインタフェースをほかのインタフェースで使用する場合にメソッド宣言のシグニチャ型として使用します。クライアントの観点からは、CORBA Hello
オブジェクトのオブジェクト参照は、このインタフェースを実装します。
注: スタブはHello
インタフェースを実装します(ここで各メソッドのコードを生成して引数を整列化してメソッドを呼び出し、引数の整列化を解除します)。
package HelloApp; /** * HelloApp/Hello.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ public interface Hello extends HelloOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity { } // interface Hello
Javaオペレーション・インタフェースHelloOperations.java
。サーバー側のマッピングで使用され、同じ場所にあるクライアントとサーバーに最適化された呼出しを提供するメカニズムとして使用されます。サーバーの開発者は、オペレーション・インタフェースで指示されたメソッドに対して実装を提供します。
このインタフェースにはsayHello()メソッドおよびshutdown()メソッドが含まれます。IDL-to-Javaマッピングは、IDLインタフェースで定義されたオペレーションをすべてこのファイルに組込み、スタブとスケルトンで共有します。
注: サーバーの開発者は、通常、HelloPOA
を拡張し、オペレーション・インタフェースで提供されたメソッドに対して実装を提供します。
package HelloApp; /** * HelloApp/HelloOperations.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ public interface HelloOperations { String sayHello (); void Shutdown (); } // interface HelloOperations
JavaクラスHelloHelper
は補助的な機能を提供します。特に、CORBAオブジェクト参照を適切な型にキャストするためのnarrow()メソッドは重要な役割を果たします。Helperクラスは、CORBAストリームへのデータ型の読取りと書込み、およびAnyからのデータ型の挿入および抽出を扱います。HolderクラスはHelperクラスのメソッドに入出力を委譲します。
package HelloApp; /** * HelloApp/HelloHelper.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ abstract public class HelloHelper { private static String _id = "IDL:HelloApp/Hello:1.0"; public static void insert (org.omg.CORBA.Any a, HelloApp.Hello 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 HelloApp.Hello 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 (HelloApp.HelloHelper.id (), "Hello"); } return __typeCode; } public static String id () { return _id; } public static HelloApp.Hello read (org.omg.CORBA.portable.InputStream istream) { return narrow (istream.read_Object (_HelloStub.class)); } public static void write (org.omg.CORBA.portable.OutputStream ostream, HelloApp.Hello value) { ostream.write_Object ((org.omg.CORBA.Object) value); } public static HelloApp.Hello narrow (org.omg.CORBA.Object obj) { if (obj == null) return null; else if (obj instanceof HelloApp.Hello) return (HelloApp.Hello)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 (); HelloApp._HelloStub stub = new HelloApp._HelloStub (); stub._set_delegate(delegate); return stub; } } }
JavaクラスHelloHolderには、Hello型のpublicインスタンス・メンバーが入ります。IDL型のパラメータがoutまたはinoutであればHolderクラスが使用されます。これは、org.omg.CORBA.portable.OutputStreamおよびorg.omg.CORBA.portable.InputStream引数(CORBAは許可しますが、Javaのセマンティックスには簡単にマッピングできません)に対するオペレーションを提供します。HolderクラスはHelperクラスのメソッドに入出力を委譲します。これはorg.omg.CORBA.portable.Streamableを実装します。
HelloApp/HelloHolder.javapackage HelloApp; /** * HelloApp/HelloHolder.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ public final class HelloHolder implements org.omg.CORBA.portable.Streamable { public HelloApp.Hello value = null; public HelloHolder () { } public HelloHolder (HelloApp.Hello initialValue) { value = initialValue; } public void _read (org.omg.CORBA.portable.InputStream i) { value = HelloApp.HelloHelper.read (i); } public void _write (org.omg.CORBA.portable.OutputStream o) { HelloApp.HelloHelper.write (o, value); } public org.omg.CORBA.TypeCode _type () { return HelloApp.HelloHelper.type (); } }
Javaクラス_HelloStubは、クライアント側マッピングのスタブ・ファイルです。これはorg.omg.CORBA.portable.ObjectImplを拡張し、Hello.javaインタフェースを実装します。
HelloApp/_HelloStub.javapackage HelloApp; /** * HelloApp/_HelloStub.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ public class _HelloStub extends org.omg.CORBA.portable.ObjectImpl implements HelloApp.Hello { public String sayHello () { org.omg.CORBA.portable.InputStream _in = null; try { org.omg.CORBA.portable.OutputStream _out = _request ("sayHello", 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 sayHello (); } finally { _releaseReply (_in); } } // sayHello public void Shutdown () { org.omg.CORBA.portable.InputStream _in = null; try { org.omg.CORBA.portable.OutputStream _out = _request ("Shutdown", false); _in = _invoke (_out); } 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) { Shutdown (); } finally { _releaseReply (_in); } } // Shutdown // Type-specific CORBA::Object operations private static String[] __ids = { "IDL:HelloApp/Hello: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 _HelloStub
JavaクラスHelloImplPOAはサーバー側のマッピングのスケルトン・ファイルで、サーバー用に基本的なCORBA機能を提供します。これはorg.omg.PortableServer.Servantを拡張し、InvokeHandlerインタフェースとHelloOperationsインタフェースを実装します。サーバー・クラスHelloServantはHelloPOAを拡張します。
HelloApp/HelloPOA.javapackage HelloApp; /** * HelloApp/HelloPOA.java * Generated by the IDL-to-Java compiler (portable), version "3.0" * from Hello.idl * Thursday, March 22, 2001 2:17:15 PM PST */ public abstract class HelloPOA extends org.omg.PortableServer.Servant implements HelloApp.HelloOperations, org.omg.CORBA.portable.InvokeHandler { // Constructors private static java.util.Hashtable _methods = new java.util.Hashtable (); static { _methods.put ("sayHello", new java.lang.Integer (0)); _methods.put ("Shutdown", new java.lang.Integer (1)); } 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: // HelloApp/Hello/sayHello { String __result = null; __result = this.sayHello (); out = rh.createReply(); out.write_string (__result); break; } case 1: // HelloApp/Hello/Shutdown { this.Shutdown (); out = rh.createReply(); 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:HelloApp/Hello:1.0"}; public String[] _all_interfaces (org.omg.PortableServer.POA poa, byte[] objectId) { return (String[])__ids.clone (); } public Hello _this() { return HelloHelper.narrow( super._this_object()); } public Hello _this(org.omg.CORBA.ORB orb) { return HelloHelper.narrow( super._this_object(orb)); } } // class HelloPOA
アプリケーションを完了するには、開発者がクライアントとサーバーのコードを記述する必要があります。
ここで紹介するサーバーは、サーバントとサーバーの2つのクラスで構成されます。サーバントHelloImplはHello IDLインタフェースの実装で、各HelloインスタンスはHelloImplインスタンスによって実装されます。サーバントは、idljコンパイラにより例のIDLから生成されるHelloPOAのサブクラスです。
サーバントには、IDLオペレーションごとに1つのメソッドが含まれます(この例では、sayHello()およびshutdown()メソッド)。サーバント・メソッドは、Javaの通常のメソッドと変わりはありません。ORBの処理、引数や結果の整列化などを行うコードは、スケルトンで実装します。
次の例では、一時サーバーのコードを示します。持続サーバーを使った「Hello World」アプリケーションについては、持続サーバーを使ったHello Worldの例を参照してください。
次のコードは、開発者によって記述されます。
HelloServer.java// HelloServer.java // Copyright and License import HelloApp.*; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.*; import org.omg.PortableServer.*; import org.omg.PortableServer.POA; import java.util.Properties; class HelloImpl extends HelloPOA { private ORB orb; public void setORB(ORB orb_val) { orb = orb_val; } // implement sayHello() method public String sayHello() { return "\nHello world !!\n"; } // implement shutdown() method public void shutdown() { orb.shutdown(false); } } 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 = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); rootpoa.the_POAManager().activate(); // create servant and register it with the ORB HelloImpl helloImpl = new HelloImpl(); helloImpl.setORB(orb); // get object reference from the servant org.omg.CORBA.Object ref = rootpoa.servant_to_reference(helloImpl); Hello href = HelloHelper.narrow(ref); // get the root naming context // NameService invokes the 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 = "Hello"; 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 ..."); } }
次の例では、Javaクライアント・アプリケーションを示します。CORBAクライアントは、サーブレット、JSP、アプレットなどとして記述できます。
HelloClient.java// Copyright and License import HelloApp.*; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.*; public class HelloClient { static Hello helloImpl; public static void main(String args[]) { try{ // create and initialize the ORB ORB orb = ORB.init(args, null); // get the root naming context org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); // Use NamingContextExt instead of NamingContext. This is // part of the Interoperable naming Service. NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef); // resolve the Object Reference in Naming String name = "Hello"; helloImpl = HelloHelper.narrow(ncRef.resolve_str(name)); System.out.println("Obtained a handle on server object: " + helloImpl); System.out.println(helloImpl.sayHello()); helloImpl.shutdown(); } catch (Exception e) { System.out.println("ERROR : " + e) ; e.printStackTrace(System.out); } } }
Java CORBAアプリケーションのコンパイルと実行の詳細については、「Hello Worldの構築方法と実行方法」を参照してください。