module Stock { exception Invalid_Stock {}; interface Quoter { long get_quote(in string stock_name) raises (Invalid_Stock); }; module Callback { struct Info { string stock_name; long value; }; // Distributed callback interface // (invoked by the Supplier) interface Handler { void push(in Info data); }; }; interface Notifying_Quoter { // Register a distributed callback handler void register(in string stock_name, in long threshold, in Callback::Handler handler) raises (Invalid_Stock); }; };
% idltojava stock.idl % ls -lR Stock/*.java -rw-r--r-- 347 Stock/Invalid_Stock.java -rw-r--r-- 1564 Stock/Invalid_StockHelper.java -rw-r--r-- 832 Stock/Invalid_StockHolder.java -rw-r--r-- 393 Stock/Notifying_Quoter.java -rw-r--r-- 1897 Stock/Notifying_QuoterHelper.java -rw-r--r-- 859 Stock/Notifying_QuoterHolder.java -rw-r--r-- 326 Stock/Quoter.java -rw-r--r-- 1747 Stock/QuoterHelper.java -rw-r--r-- 769 Stock/QuoterHolder.java -rw-r--r-- 2872 Stock/_Notifying_QuoterImplBase.java -rw-r--r-- 1715 Stock/_Notifying_QuoterStub.java -rw-r--r-- 2135 Stock/_QuoterImplBase.java -rw-r--r-- 1594 Stock/_QuoterStub.java -rw-r--r-- 315 Stock/Callback/Handler.java -rw-r--r-- 1879 Stock/Callback/HandlerHelper.java -rw-r--r-- 841 Stock/Callback/HandlerHolder.java -rw-r--r-- 470 Stock/Callback/Info.java -rw-r--r-- 1991 Stock/Callback/InfoHelper.java -rw-r--r-- 814 Stock/Callback/InfoHolder.java -rw-r--r-- 1775 Stock/Callback/_HandlerImplBase.java -rw-r--r-- 906 Stock/Callback/_HandlerStub.java
import Stock.*; // The package containing our stubs. import org.omg.CosNaming.*; // StockClient uses the naming service. import org.omg.CORBA.*; // All CORBA applications need these classes. public class StockClient { 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"); NamingContext ncRef = NamingContextHelper.narrow(objRef); // Resolve the object reference in naming NameComponent nc = new NameComponent("Stock", ""); NameComponent path[] = {nc}; Quoter quoterRef = QuoterHelper.narrow(ncRef.resolve(path)); // Call the Hello server object and print results int val = quoterRef.get_quote("IBM"); System.out.println("IBM = "+val); } catch(Exception e) { System.out.println("ERROR : " + e); e.printStackTrace(System.out); } } }
import Stock.*; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.*; public class StockServer { public static void main(String args[]) { try{ // Create and initialize the ORB ORB orb = ORB.init(args, null); // Create the servant and register it with the ORB QuoterServant quoterRef = new QuoterServant(); orb.connect(quoterRef); // Get the root naming context org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); // Bind the object reference in naming NameComponent nc = new NameComponent("Stock", ""); NameComponent path[] = {nc}; ncRef.rebind(path, quoterRef); // Wait for invocations from clients java.lang.Object sync = new java.lang.Object(); synchronized(sync){ sync.wait(); } } catch(Exception e) { System.err.println("ERROR: " + e); e.printStackTrace(System.out); } } } class QuoterServant extends _QuoterImplBase { public int get_quote(String stock_name) throws Stock.Invalid_Stock { return 103; } }
import Stock.*; // The package containing our stubs. import Stock.Callback.*; import org.omg.CosNaming.*; // StockClient uses the naming service. import org.omg.CORBA.*; // All CORBA applications need these classes. public class StockClient2 { public static void main(String args[]) { try{ // Create and initialize the ORB ORB orb = ORB.init(args, null); // Create the Callback servant and register it with the ORB HandlerServant handlerRef = new HandlerServant(); orb.connect(handlerRef); // Get the root naming context org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); // Resolve the object reference in naming NameComponent nc = new NameComponent("NotifyingStock", ""); NameComponent path[] = {nc}; Notifying_Quoter quoterRef = Notifying_QuoterHelper.narrow(ncRef.resolve(path)); // Register Handler with server object quoterRef.register("IBM", 100, handlerRef); // Wait for invocations from notifying server java.lang.Object sync = new java.lang.Object(); synchronized(sync){ sync.wait(); } } catch(Exception e) { System.out.println("ERROR : " + e); e.printStackTrace(System.out); } } } class HandlerServant extends _HandlerImplBase { public void push(Stock.Callback.Info data) { System.out.println(data.stock_name + " = " + data.value); } }
import Stock.*; import Stock.Callback.*; import org.omg.CosNaming.*; import org.omg.CosNaming.NamingContextPackage.*; import org.omg.CORBA.*; // For maps import java.util.*; public class StockServer2 { public static void main(String args[]) { try{ // Create and initialize the ORB ORB orb = ORB.init(args, null); // Create map: table of registered clients Map cb_map = Collections.synchronizedMap(new HashMap()); // Create the servant and register it with the ORB Notifying_QuoterServant quoterRef = new Notifying_QuoterServant(cb_map); orb.connect(quoterRef); // Get the root naming context org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService"); NamingContext ncRef = NamingContextHelper.narrow(objRef); // Start monitoring thread: will send events to clients (new Stock_Monitoring(cb_map)).start(); // Bind the object reference in naming NameComponent nc = new NameComponent("NotifyingStock", ""); NameComponent path[] = {nc}; ncRef.rebind(path, quoterRef); // Wait for invocations from clients java.lang.Object sync = new java.lang.Object(); synchronized(sync){ sync.wait(); } } catch(Exception e) { System.err.println("ERROR: " + e); e.printStackTrace(System.out); } } } // This is only needed for the map of clients class Pair { public Pair(int first, Stock.Callback.Handler second) { _first = first; _second = second; } public int threshold() {return _first;} public Stock.Callback.Handler handler() {return _second;} private int _first; private Stock.Callback.Handler _second; } // Handles the registration of clients class Notifying_QuoterServant extends _Notifying_QuoterImplBase { public Notifying_QuoterServant(Map cb) { super(); map = cb; } public void register(String stock_name, int threshold, Stock.Callback.Handler handler) throws Stock.Invalid_Stock { System.out.println("Registering " + stock_name); map.put(stock_name, new Pair(threshold, handler)); } private Map map; } // Thread that monitors (in polling mode) the source of stock prices // and sends notification to subscribed clients when relevant. // The table of subscribed clients is shared with the registration servant. class Stock_Monitoring extends Thread { public Stock_Monitoring(Map cb) { super(); map = cb; System.out.println("Constructing monitor -- " + map.size() + " elements"); } private Map map; public void run() { // Loop -- get new value // Verify if someone needs it // For now, just iterate over all clients for (;;) { try { sleep(1000); Iterator iter = map.entrySet().iterator(); while (iter.hasNext()) { Map.Entry e = (Map.Entry)iter.next(); String stock = (String)e.getKey(); Pair p = (Pair)e.getValue(); System.out.println("Pushing " + stock + " " + p.threshold()); try { p.handler().push(new Stock.Callback.Info(stock, p.threshold())); } catch (Exception e1) { System.err.println("Client for " + stock + " has unregistered"); iter.remove(); } } } catch(Exception e2) { System.err.println("ERROR: " + e2); e2.printStackTrace(System.out); } } } }
setenv JAVA_HOME /usr/local/Java/LastJDK alias java $JAVA_HOME/bin/java alias javac $JAVA_HOME/bin/javac alias tnameserv $JAVA_HOME/bin/tnameserv
% tnameserv -ORBInitialPort 1050 &
% idltojava stock.idl
% javac StockClient1.java Stock/*.java % javac StockClient2.java Stock/*.java Stock/Callback/*.java
% javac StockServer1.java Stock/*.java % javac StockServer2.java Stock/*.java Stock/Callback/*.java
% java StockServer1 -ORBInitialPort 1050 & % java StockServer2 -ORBInitialPort 1050 &
% java StockClient1 -ORBInitialPort 1050 % java StockClient2 -ORBInitialPort 1050