クライアントプログラムでは、サーバー側で起こった変更や更新への対応が必要になることがあります。たとえば、株価サーバー上で株価が更新されるたびに、クライアントのグラフ表示プログラムやスプレッドシートプログラムでも更新を行いたいといった場合などです。このような場合、クライアントには 2 つのオプションがあります。
このドキュメントの例では、クライアントプログラムからサーバーにコールバックオブジェクトを渡す方法と、その後にサーバーからクライアントに変更を通知する方法について説明します。ここでは、単純なアプリケーションを拡張したコードを紹介します。アプリケーションを簡略化した箇所については、コード内にコメントを記載します。
このドキュメントで紹介するコードは、次のようなものです。
サンプルのコンパイルと実行の手順についても説明します。
このアプリケーション例で使用する callback.idl ファイルは、次のようなものです。
interface Listener { void message(in string msg); }; interface MessageServer { void register(in Listener lt); };
このアプリケーション例で使用する Server.java ファイルは、次のようなものです。
import org.omg.CORBA.ORB; import org.omg.PortableServer.POA; import org.omg.PortableServer.POAHelper; import org.omg.CosNaming.NameComponent; import org.omg.CosNaming.NamingContext; import org.omg.CosNaming.NamingContextHelper; public class Server { public static void main(String[] args) { try { //create and initialize the ORB Properties props = System.getProperties(); props.put("org.omg.CORBA.ORBInitialPort", "1050"); //Replace MyHost with the name of the host on which you are running the server props.put("org.omg.CORBA.ORBInitialHost", "<MyHost>"); ORB orb = ORB.init(args, props); System.out.println("Initialized ORB"); //Instantiate Servant and create reference POA rootPOA = POAHelper.narrow( orb.resolve_initial_references("RootPOA")); MessageServerImpl msImpl = new MessageServerImpl(); rootPOA.activate_object(msImpl); MessageServer msRef = MessageServerHelper.narrow( rootPOA.servant_to_reference(msImpl)); //Bind reference with NameService NamingContext namingContext = NamingContextHelper.narrow( orb.resolve_initial_references("NameService")); System.out.println("Resolved NameService"); NameComponent[] nc = { new NameComponent("MessageServer", "") }; namingContext.rebind(nc, msRef); //Activate rootpoa rootPOA.the_POAManager().activate(); //Start readthread and wait for incoming requests System.out.println("Server ready and running ...."); //REMOVE THE NEXT LINE FOR THE SIMPLER EXAMPLE msImpl.startReadThread(); orb.run(); } catch (Exception e) { e.printStackTrace(); } } }
このファイルのコードでは、新しいクライアントを登録し、メッセージを受け付けたあと、登録されたクライアントにそのメッセージを中継します。このアプリケーション例で使用する MessageServerImpl.java ファイルは、次のようなものです。
import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.Vector; import java.util.Iterator; public class MessageServerImpl extends MessageServerPOA { private Vector clients = new Vector(); private ReadThread rt = null; public MessageServerImpl() { rt = new ReadThread(this); } public void register(Listener lt) { clients.add(lt); } public void startReadThread() { rt.start(); } public void message(String msg) { Iterator it = clients.iterator(); while (it.hasNext()) { Listener lt = (Listener) it.next(); lt.message(msg); //FOR THE SIMPLER EXAMPLE, ADD A SIMPLE //MESSAGE TO BE CALLED BACK, FOR EXAMPLE, //SLEEP FOR 30 SECONDS, THEN SEND THE TIME } } } //EXCLUDE THIS CLASS FOR THE SIMPLER EXAMPLE class ReadThread extends Thread { MessageServerImpl msImpl = null; public ReadThread(MessageServerImpl msImpl) { this.msImpl = msImpl; } public void run() { BufferedReader br = new BufferedReader( new InputStreamReader(System.in)); try { for (;;) { System.out.print("message > "); String msg = br.readLine(); msImpl.message(msg); } } catch (Exception e) { e.printStackTrace(); } } }
このアプリケーション例で使用する Client.java ファイルは、次のようなものです。
import java.util.Properties; import org.omg.CORBA.ORB; import org.omg.PortableServer.POA; import org.omg.PortableServer.POAHelper; import org.omg.CosNaming.NameComponent; import org.omg.CosNaming.NamingContext; import org.omg.CosNaming.NamingContextHelper; public class Client { public static void main(String[] args) { try { //initialize orb Properties props = System.getProperties(); props.put("org.omg.CORBA.ORBInitialPort", "1050"); //Replace MyHost with the name of the host on which you are running the server props.put("org.omg.CORBA.ORBInitialHost", "<MyHost>"); ORB orb = ORB.init(args, props); System.out.println("Initialized ORB"); //Instantiate Servant and create reference POA rootPOA = POAHelper.narrow( orb.resolve_initial_references("RootPOA")); ListenerImpl listener = new ListenerImpl(); rootPOA.activate_object(listener); Listener ref = ListenerHelper.narrow( rootPOA.servant_to_reference(listener)); //Resolve MessageServer MessageServer msgServer = MessageServerHelper.narrow( orb.string_to_object("corbaname:iiop:1.2@localhost:1050#MessageServer")); //Register listener reference (callback object) with MessageServer msgServer.register(ref); System.out.println("Listener registered with MessageServer"); //Activate rootpoa rootPOA.the_POAManager().activate(); //Wait for messages System.out.println("Wait for incoming messages"); orb.run(); } catch (Exception e) { e.printStackTrace(); } } }
Listener は、サーバーからのメッセージ受信を識別すると、そのメッセージをクライアントに表示します。このアプリケーション例で使用する ListenerImpl.java ファイルは、次のようなものです。
public class ListenerImpl extends ListenerPOA { public void message(String msg) { System.out.println("Message from server : " + msg); } }
rm -rf ./classes ./orb.db
mkdir -p ./classes <path_to_java>/bin/idlj -fall -td ./classes callback.idl
<path_to_java>/bin/javac -classpath ./classes -d ./classes *.java
<path_to_java>/bin/orbd -ORBInitialPort 1050 -ORBInitialHost <host_name> &
<path_to_java>/bin/java -classpath ./classes Server -ORBInitialPort 1050
サーバーを開始すると、端末ウィンドウに次のような出力が表示されます。
Initialized ORB Resolved NameService Server ready and running .... message >
このプロンプトを使用してクライアントにメッセージを送信することになりますが、その前に、クライアントアプリケーションを開始する必要があります。CLIENT 端末で次の手順を実行して、クライアントアプリケーションを実行します。クライアントコードの properties セクションで、サーバーが実行されているホスト名を使用したことを確認してください。
<path_to_java>/bin/java -classpath ./classes Client -ORBInitialPort 1050
クライアントアプリケーションからの出力が、次のような形式で表示されます。
Initialized ORB Listener registered with MessageServer Wait for incoming messages
コールバックを使用した機能を表示するには、サーバー端末のプロンプトにデータを入力します。そうすると、そのデータがすべてのクライアント端末に表示されます。通知の内容には、クライアントが関心を持つものを何でも含めることができます。
一例として、フットボールの試合のスコアが変化したときに、クライアントに通知してみます。
message > Niners TD. Niners 7 - Giants 0 message > Giants TD. Niners 7 - Giants 7 message > Niners TD. Niners 14 - Giants 7
上記のようなメッセージが送信されると、クライアントに次のように表示されます。
Wait for incoming messages Message from server : Niners TD. Niners 7 - Giants 0 Message from server : Giants TD. Niners 7 - Giants 7 Message from server : Niners TD. Niners 14 - Giants 7