RMI z IIOP POA (do współpracy z omniorb) Tomasz Kubik Java Napisz interfejs: HelloInterface.java import java.rmi.remote; public interface HelloInterface extends java.rmi.remote { public void sayhello() throws java.rmi.remoteexception; Napisz implementację: HelloImpl.java import javax.rmi.portableremoteobject; public class HelloImpl extends PortableRemoteObject implements HelloInterface { public HelloImpl() throws java.rmi.remoteexception { super(); // invoke rmi linking and remote object initialization public void sayhello() throws java.rmi.remoteexception { System.out.println( "It works! Hello World!!" ); Napisz klienta: HelloClient.java import java.rmi.remoteexception; import java.net.malformedurlexception; import java.rmi.notboundexception; import javax.rmi.*; import java.util.vector; import javax.naming.namingexception; import javax.naming.initialcontext; import javax.naming.context; public class HelloClient { public static void main( String args[] ) { Context ic; Object objref; HelloInterface hi; ic = new InitialContext(); catch (NamingException e) { System.out.println("failed to obtain context" + e); e.printstacktrace(); return; 1
// STEP 1: Get the Object reference from the Name Service // using JNDI call. objref = ic.lookup("helloservice"); System.out.println("Client: Obtained a ref. to Hello server."); catch (NamingException e) { System.out.println("failed to lookup object reference"); e.printstacktrace(); return; // STEP 2: Narrow the object reference to the concrete type and // invoke the method. hi = (HelloInterface) PortableRemoteObject.narrow( objref, HelloInterface.class); hi.sayhello(); catch (ClassCastException e) { System.out.println("narrow failed"); e.printstacktrace(); return; catch( Exception e ) { System.err.println( "Exception " + e + "Caught" ); e.printstacktrace( ); return; Napisz serwer: HelloServer.java import javax.naming.initialcontext; import javax.naming.context; import javax.rmi.portableremoteobject ; import com.sun.corba.se.internal.poa.poaorb; import org.omg.portableserver.*; import java.util.*; import org.omg.corba.*; import javax.rmi.corba.stub; import javax.rmi.corba.util; public class HelloServer { public HelloServer(String[] args) { Properties p = System.getProperties(); // add runtime properties here p.put("org.omg.corba.orbclass", "com.sun.corba.se.internal.poa.poaorb"); p.put("org.omg.corba.orbsingletonclass", "com.sun.corba.se.internal.corba.orbsingleton"); ORB orb = ORB.init( args, p ); POA rootpoa = (POA)orb.resolve_initial_references("RootPOA"); // STEP 1: Create a POA with the appropriate policies Policy[] tpolicy = new Policy[3]; tpolicy[0] = rootpoa.create_lifespan_policy( LifespanPolicyValue.TRANSIENT ); 2
tpolicy[1] = rootpoa.create_request_processing_policy( RequestProcessingPolicyValue.USE_ACTIVE_OBJECT_MAP_ONLY ); tpolicy[2] = rootpoa.create_servant_retention_policy( ServantRetentionPolicyValue.RETAIN); POA tpoa = rootpoa.create_poa("mytransientpoa", null, tpolicy); // STEP 2: Activate the POA Manager, otherwise all calls to the // servant hang because, by default, POAManager will be in the // HOLD state. tpoa.the_poamanager().activate(); // STEP 3: Instantiate the Servant and activate the Tie, If the // POA policy is USE_ACTIVE_OBJECT_MAP_ONLY HelloImpl helloimpl = new HelloImpl(); _HelloImpl_Tie tie = (_HelloImpl_Tie)Util.getTie( helloimpl ); String helloid = "hello"; byte[] id = helloid.getbytes(); tpoa.activate_object_with_id( id, tie ); // STEP 4: Publish the object reference using the same object id // used to activate the Tie object. Context initialnamingcontext = new InitialContext(); initialnamingcontext.rebind("helloservice", tpoa.create_reference_with_id(id, tie._all_interfaces(tpoa,id)[0]) ); System.out.println("Hello Server: Ready..."); // STEP 5: Get ready to accept requests from the client orb.run(); catch (Exception e) { System.out.println("Problem running HelloServer: " + e); e.printstacktrace(); public static void main(string args[]) { new HelloServer( args ); Skompiluj źródła: komenda powstałe pliki 1 javac d. classpath. HelloImpl.java HelloImpl.class 2 rmic poa iiop HelloImpl _HelloInterface_Stub.class, _HelloImpl_Tie.class 3 javac d. classpath. HelloInterface.java HelloServer.java HelloClient.java HelloInterface.class HelloServer.class HelloClient.class Utwórz plik iterfejsu w języku idl: komenda rmic idl HelloInterface powstałe pliki HelloInterface.idl omniorb (4.0.5) 3
Skompiluj plik interfejsu w języku idl: komenda omniidl Ie:\omniORB-4.0.5\idl bcxx Wbtp Wbexample Wbh=.h Wbs=.cpp HelloInterface.idl powstałe pliki HelloInterface_i.cc HelloInterface.h HelloInterface.cpp HelloInterface_i.cc - przykładowy plik (implementacja serwera) HelloInterface.h nagłówek HelloInterface.cpp szkielet Napisz klienta HelloInterface_client.cpp #include <iostream.h> #include "HelloInterface.h" static CORBA::Object_ptr getobjectreference(corba::orb_ptr orb); int main (int argc, char **argv) { CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);//, "omniorb3"); // receive reference from NameService CORBA::Object_var obj = getobjectreference(orb); HelloInterface_var hellointerfaceref = HelloInterface::_narrow(obj); if( CORBA::is_nil(helloInterfaceref) ) { cerr << "hello: The object reference is nil!\n" << endl; return -1; hellointerfaceref->sayhello(); cerr << "I did: sayhello()" << endl; orb->destroy(); catch(corba::comm_failure& ex) { cerr << "Caught system exception COMM_FAILURE -- unable to " << "contact the object." << endl; catch(corba::systemexception&) { cerr << "Caught CORBA::SystemException." << endl; catch(corba::exception&) { cerr << "Caught CORBA::Exception." << endl; catch(omniorb::fatalexception& fe) { cerr << "Caught omniorb::fatalexception:" << endl; cerr << " file: " << fe.file() << endl; cerr << " line: " << fe.line() << endl; cerr << " mesg: " << fe.errmsg() << endl; catch(...) { cerr << "Caught unknown exception." << endl; static CORBA::Object_ptr getobjectreference(corba::orb_ptr orb) { CosNaming::NamingContext_var rootcontext; // Obtain a reference to the root context of the Name service: 4
CORBA::Object_var obj; obj = orb->resolve_initial_references("nameservice"); // Narrow the reference returned. rootcontext = CosNaming::NamingContext::_narrow(obj); if( CORBA::is_nil(rootContext) ) { cerr << "Failed to narrow the root naming context." << endl; return CORBA::Object::_nil(); catch(corba::orb::invalidname& ex) { // This should not happen! cerr << "Service required is invalid [does not exist]." << endl; return CORBA::Object::_nil(); // Create a name object, containing the name test/context: CosNaming::Name name; name.length(1); name[0].id = CORBA::string_dup ("HelloService"); name[0].kind = CORBA::string_dup (""); // string copied // Resolve the name to an object reference. return rootcontext->resolve(name); catch(cosnaming::namingcontext::notfound& ex) { // This exception is thrown if any of the components of the // path [contexts or the object] aren't found: cerr << "Context not found." << endl; catch(corba::comm_failure& ex) { cerr << "Caught system exception COMM_FAILURE -- unable to " << "contact the naming service." << endl; catch(corba::systemexception&) { cerr << "Caught a CORBA::SystemException while using the " << "naming service." << endl; return CORBA::Object::_nil(); Napisz serwera (zmodyfikuj plik HelloInterface_i.cc) HelloInterface_server #include <iostream.h> #include "HelloInterface.h" static CORBA::Boolean bindobjecttoname(corba::orb_ptr,corba::object_ptr); // // Example class implementing IDL interface HelloInterface // class HelloInterface_i: public POA_HelloInterface, public PortableServer::RefCountServantBase { private: // Make sure all instances are built on the heap by making the // destructor non-public virtual ~HelloInterface_i(); 5
public: // standard constructor HelloInterface_i(); virtual ~HelloInterface_i(); // methods corresponding to defined IDL attributes and operations void sayhello(); ; // Example implementational code for IDL interface HelloInterface HelloInterface_i::HelloInterface_i(){ // add extra constructor code here HelloInterface_i::~HelloInterface_i(){ // add extra destructor code here // Methods corresponding to IDL attributes and operations void HelloInterface_i::sayHello(){ // insert code here and remove the warning cout << "It works! Hello World!!\n"; cout.flush(); // End of example implementational code int main(int argc, char** argv) { // Initialise the ORB. CORBA::ORB_var orb = CORBA::ORB_init(argc, argv); // Obtain a reference to the root POA. CORBA::Object_var obj = orb->resolve_initial_references("rootpoa"); PortableServer::POA_var poa = PortableServer::POA::_narrow(obj); // We allocate the objects on the heap. Since these are reference // counted objects, they will be deleted by the POA when they are no // longer needed. HelloInterface_i* myhellointerface_i = new HelloInterface_i(); PortableServer::ObjectId_var myhellointerface_iid = poa->activate_object(myhellointerface_i); CORBA::Object_var myhellointerface_var = myhellointerface_i->_this(); CORBA::String_var sior(orb->object_to_string(myhellointerface_var.in())); cerr << "'" << (char*)sior << "'" << endl; cerr.flush(); // Obtain a reference to the object, and register it in the naming service. if(!bindobjecttoname(orb, myhellointerface_var.in()) ) return 1; myhellointerface_i->_remove_ref(); // Obtain a POAManager, and tell the POA to start accepting requests on its objects. PortableServer::POAManager_var pman = poa->the_poamanager(); pman->activate(); cout << "Server started\n"; cout.flush(); orb->run(); orb->destroy(); catch(corba::systemexception&) { cerr << "Caught CORBA::SystemException." << endl; 6
catch(corba::exception&) { cerr << "Caught CORBA::Exception." << endl; catch(omniorb::fatalexception& fe) { cerr << "Caught omniorb::fatalexception:" << endl; cerr << " file: " << fe.file() << endl; cerr << " line: " << fe.line() << endl; cerr << " mesg: " << fe.errmsg() << endl; catch(...) { cerr << "Caught unknown exception." << endl; static CORBA::Boolean bindobjecttoname(corba::orb_ptr orb, CORBA::Object_ptr objref) { // Bind object to name service CosNaming::NamingContext_var nc; CORBA::Object_var _obj1= orb->resolve_initial_references("nameservice"); // narrow this to the naming context nc = CosNaming::NamingContext::_narrow(_obj1.in()); if( CORBA::is_nil(nc) ) { cerr << "Failed to narrow the root naming context." << endl; catch(corba::orb::invalidname& ex) { // This should not happen! cerr << "Service required is invalid [does not exist]." << endl; // Bind to CORBA name service. Same name to be requested by client. CosNaming::Name name; name.length(1); name[0].id=corba::string_dup("helloservice"); nc->rebind (name,objref); catch(corba::comm_failure& ex) { cerr << "Caught system exception COMM_FAILURE -- unable to contact the " << "naming service." << endl; catch(corba::systemexception&) { cerr << "Caught a CORBA::SystemException while using the naming service." << endl; return 1; Skompiluj klienta i serwera z biblioteką OmniORB. 7
Dla VC++ 5/6 skonfiguruj projekt dla serwera (podobnie będzie dla klienta): a) Dodaj do projektu pliki wygenerowane przez kompilator omniidl oraz źródło serwera (Insert->"Files into Project"; HelloInterface.h, HelloInterface.cpp, HelloInterface_server.cpp) b) Ustaw ścieżki dostępu do plików nagłówkowych i bibliotek: 1. Wybierz menu Tools->Options i zakładkę Directories. 2. W polu "Show directories for" wybierz "Include files". 3. Dodaj ścieżkę dostępu do katalogu include w zainstalowanej dystrybucji omniorb (tj. <Top-Level Directory>\include, gdzie <Top-Level Directory> to katalog główny omniorb). 4. W polu "Show directories for" wybierz "Library files". 5. Dodaj ścieżkę dostępu do katalogu bibliotek w dystrybucji omniorb (tj. <Top-Level Directory\lib\x86_win32). c) Ustaw makra i biblioteki w projekcie: 1. Wybierz menu Build->Settings i zakładkę "C/C++". 2. W polu "Category" wybierz "C++ Language". Zaznacz "Enable exception handling". 3. W polu "Category" wybierz "Code Generation". W polu "Use run-time library" wybierz "Multithreaded DLL". 4. W polu "Category" wybierz "Preprocessor". Następnie w polu "Preprocessor" dodaj makra: WIN32, x86,_win32_winnt=0x0400 Jeśli jest to NT 4.0, Windows 2000, XP, Windows 2003 Server, dodaj makra: NT, OSVERSION =4 5. Wybierz zakładlę "Link" 6. W polu "Category" wybierz "Input". W polu "Object/library modules" dodaj biblioteki: ws2_32.lib, mswsock.lib, advapi32.lib, oraz omniorb405_rt.lib, omnidynamic405_rt.lib, omnithread30_rt.lib Aby móc śledzić wykonywanie programu (fragmenty omniorb), należy zamiast powyższych bibliotek dołączyć ich debbugowalne wersje: omniorb405_rtd.lib, omnidynamic405_rtd.lib, omnithread30_rtd.lib Dla VC++ 7 skonfiguruj projekt dla serwera (podobnie będzie dla klienta). Przed kompilacją zapoznaj się z dokumentację omniorb. Konfiguracja projektu: a) Dodaj do projektu pliki wygenerowane przez kompilator omniidl oraz źródło serwera (Project ->"Add existing Item"; HelloInterface.h, HelloInterface.cpp, HelloInterface_server.cpp) b) Ustaw ścieżki dostępu do plików nagłówkowych i bibliotek: 1. Otwórz okno Project Properties 2. Wybierz C++ -> General(Additonal Include Directories) i wprowadź ścieżkę dostępu do katalogu include w zainstalowanej dystrybucji omniorb (tj. <Top-Level Directory>\include, gdzie <Top-Level Directory> to katalog główny omniorb). 3. Wybierz Linker -> General (Additional Library Directories), i wprowadź ścieżkę dostępu do katalogu bibliotek w dystrybucji omniorb (tj. <Top-Level Directory\lib\x86_win32). c) Ustaw makra i biblioteki w projekcie: 1. W Project Properties ->Settings, wybierz zakładkę "C/C++". 2. Wybierz zakładkę "The Code Generaion": 4. Dla "Enable exception Handling" wybierz "Yes" 5. Dla "Run-Time Library" wybierz "Mulithreaded DLL". 6. Wybierz zakładkę "The Code Generaion" Tab: (pod "C++" w "project properties") i w polu "Preprocessor Definitions" dodaj makra: WIN32, x86,_win32_winnt=0x0400 Jeśli jest to NT 4.0, Windows 2000, XP, Windows 2003 Server, dodaj makra: 8
NT, OSVERSION =4 7. Rozwiń zakładkę "Linker" 8. Wybierz zakładkę "Input" 9. Dodaj biblioteki w "Additional Dependencies" ws2_32.lib, mswsock.lib, advapi32.lib, omniorb405_rt.lib, omnidynamic405_rt.lib, omnithread30_rt.lib Aby móc śledzić wykonywanie programu (fragmenty omniorb), należy zamiast powyższych bibliotek dołączyć ich debbugowalne wersje: omniorb405_rtd.lib, omnidynamic405_rtd.lib, omnithread30_rtd.lib Dla kompilacji ze statycznymi wersjami bibliotek omniorb i omnithread, makra powinny wyglądać nieco inaczej: _WINSTATIC zaś dołączane biblioteki zamiast: omniorb405_rt.lib, omnidynamic405_rt.lib omnithread30_rt.lib powinno być: omniorb4.lib, omnidynamic4.lib i omnithread.lib Uruchom aplikacje 1. Upewnij się, że ścieżka systemowa PATH zawiera ścieżkę dostępu do katalogu bibliotek DLL z dystrybucji omniorb: C:\omniORB-4.0.5\bin\x86_win32\ 2. Podobnie zapewnij dostęp do wykonywalnych plików z j2sdk. 3. Wystartuj serwis nazw: start e:\omniorb-4.0.5\bin\x86_win32\omninames.exe -logdir. -start 3020 - ORBsupportBootstrapAgent 1 Uwaga: jeśli przy pierwszym uruchomieniu w bieżącym katalogu znajdują się logi wygenerowane wcześniej przez omninames, należy je usunąć. 4. Uruchom jednego serwera: a) dla Javy: start java -classpath. -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory - Djava.naming.provider.url=iiop://localhost:3020 HelloServer b) dla omniorb: start omnihellointerface_server.exe -ORBInitRef nameservice=corbaloc:iiop:localhost:3020/nameservice 5. Uruchom klienta: a) dla Javy: start java -classpath. -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory - Djava.naming.provider.url=iiop://localhost:3020 HelloClient b) dla omniorb: start omnihellointerface_client.exe -ORBInitRef nameservice=corbaloc:iiop:localhost:3020/nameservice 9