Remote Method Invocation with Java-RMI Automatically generated Skeleton - Demarshalling - Dispatch Stub - Marshalling Network ServerI Server Client Contains only functionality
What does the client see? A remote object (proxy, stub) can be casted to all interface the server implements, be accessed only via interface methods. On a remote invocation non-remote arguments are copied (using serialization), remote arguments are given as reference, different to local invocation java.rmi.RemoteException can always be thrown. Remote Objects always support the interface Remote. (Tag interface)
How to build the server? Class diagram: RemoteObject Remote Provided by the JDK RemoteServer UnicastRemoteObject Activatable Provided by the programer ServerI ServerImpl - every method which is remotely invocable must be declared to throw RemoteException. - Skeletons/Stubs are created with the JDK tool rmic.
Coordination with a naming service The naming service (rmiregistry) is a remote Java object, manages relationships between Strings (i.e. names) and remote Java objects (on the same host). remote Java objects register themselves with java.rmi.Naming.bind(String name,Remote obj); java.rmi.Naming.rebind(String name,Remote obj); the name has the form: “//host:port/identifier“ (default: host=localhost, port=1099) clients use the name to receive a stub: Remote Naming.lookup(String name);
Examplary Server Server interface: interface ServerI extends Remote { public void doSomeService() throws RemoteException;} Server implementation: class Server extends UnicastRemoteObject implements ServerI { public Server() throws RemoteException { super();} public void doSomeService() throws RemoteException { System.out.println("Working hard..");} ....
Initialisation+Registration ... public static void main(String args[]) {try { // create instance Server myServer = new Server(); // bind it to the naming service Naming.rebind(“//elfe:4711/HardServer", myServer); // done } catch(Exception ex) { ex.printStackTrace(); System.exit(5); }
Remote Invocation of the Server public class Client { static public void main(String args[]) { try { // locate Server Remote rs = Naming.lookup(“//elfe:4711/HardServer"); ServerI server = (ServerI) rs; // use service server.doSomeService(); // done } catch(Exception ex) { ex.printStackTrace(); System.exit(5); } } }
Compilation, Configuration, Startup Compile classes jedi> javac Server.java ServerI.java Client.java Create Skeletons and Stubs jedi> rmic Server Start naming service on elfe elfe> rmiregistry 4711 & Start server on elfe elfe> java Server & Start client somewhere jedi> java Client Working hard.. on elfe
Installation of JacORB Source code with examples and documentation: http://www.inf.fu-berlin.de/~brose/jacorb local installation in the Sun pool: setenv JACO /import/public/opt/JacORB1_1 setenv PATH $JACO/bin:$PATH setenv CLASSPATH $JACO/lib/idl.jar:$JACO/lib/jacorb.jar:$CLASSPATH cp $JACO/jacorb_properties.template ~/.jacorb_properties edit ~/.jacorb_properties (an install script is on the WWW) adapt the URL settings in the property file; at least this entry: jacorb.NameServerURL=file:/....
Overview about CORBA Client Server Servant Servant Impl. Servant IDL Interface Skeleton Stub POA POA ORB
Class Hierarchie for CORBA Servers for the Interface Foo Servant <<interface>> FooOperations FooPOA FooPOATie FooDelegateImpl Delegate allows use of inheritence: new FooPOATie(new FooDelegateImpl()) Delegates to <<interface>> Foo FooImpl Servants are no CORBA objects
The CORBA COS Naming Service A naming context stores relationships between names and Objects, is itself a CORBA object (allows hierarchical, potentially cyclic name spaces). name = sequence<name_components>, name_component=(string id, string kind) ORB provides bootstrapping with the root context NameServer (ORB uses jacorb.NameServerURL; it points to an IOR) bind an object in a subcontext NamingContext.bind(Name n, Object o); resolve an object Object Object NamingContext.resolve(Name n); create a new sub context NamingContext NamingContext.new_context(); NamingContext.bind_new_context(Name n); bug in JDK use NamingContextExt !
Examplary Server now in CORBA Server IDL interface: interface Server { void doSomeService();}; Server implementation: class ServerImpl extends ServerPOA { public void doSomeService() { System.out.println("Working hard..");} // main method follows
Initialisation+Registration static public void main(String args[]) { try { // access CORBA, activate POA ORB orb = org.omg.CORBA.ORB.init(args, null); POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA")); poa.the_POAManager().activate(); // from now on requests are handled !!! // get name server NamingContextExt nc = NamingContextExtHelper.narrow(orb.resolve_initial_references("NameService")); // generate a server and register it at the POA org.omg.CORBA.Object cob = poa.servant_to_reference(new ServerImpl()); // generate a name NameComponent [] name = new NameComponent[1]; name[0] = new NameComponent( "HardServer", "some kind"); // bind server to name nc.bind(name, cob); // done System.out.println("Server is ready."); orb.run(); } catch(Exception ex){ex.printStackTrace();} } } // main, class
Remote Invocation of the Server class Client { static void main(String args[]) { try{ // get ORB and naming service ORB orb = org.omg.CORBA.ORB.init(args, null); NamingContextExt nc = NamingContextExtHelper.narrow(orb.resolve_initial_references("NameService")); // generate the name NameComponent [] name = new NameComponent[1]; name[0] = new NameComponent( "HardServer", "some kind"); // query naming service, cast the stub org.omg.CORBA.Object cob = nc.resolve(name); Server server = ServerHelper.narrow(cob); // use the generated Helper class // use service server.doSomeService(); } catch(Exception ex){ ex.printStackTrace(); } } }
Compile the Example Generate skeleton,stubs, helper classes from the IDL > idl server.idl Skeletons: ServerPOA.java,ServerPOATie.java Stub: _ServerStub.java Helpers: ServerHelper.java, ServerHolder.java Interfaces: Server.java, ServerOperations.java compile the classes > javac *.java (take care of your CLASSPATH!)
Startup your Scenario Start the naming service > ns NSIOR NSIOR should be: file(jacorb.NameServerURL) E.g.: file:/home/tnfink/ns.ior /home/tnfink/ns.ior start the server jedi> jaco ServerImpl Server is ready. Start the client troll> jaco Client Working hard. (auf jedi)
Miscellaneous Methods Convert CORBA object references to Java Strings: String ORB.object_to_string(org.omg.CORBA.Object obj); org.omg.CORBA.Object ORB.string_to_object(String ior); test for existance of an CORBA object (i.e. stub) boolean Object._non_existent(); test if two CORBA objects are equal boolean Object._is_equivalent(Object other); a return of false does not guarantee inequality! Duplicate a CORBA object (reference) Object Object.duplicate();
Miscellaneous Tools, Parameters naming service GUI >nmg analysis of IORs > dior -f ns.ior ------IOR components----- TypeId : IDL:omg.org/CosNaming/NamingContextExt:1.0 Profile Id : TAG_INTERNET_IOP IIOP Version : 1.1 Host : 160.45.110.127 Port : 1281 ... Parameter for debug output (0=none, 1=important, ... 10) jacorb.verbosity = 0
Java RMI CORBA Java RMI is easy to learn and use, does not support heterogeneity, scalability, reliability CORBA needs effort for learning is a sophisticated industrial tool for the real world.