Bazy danych i inżynieria oprogramowania Wykład 4: Wprowadzenie do OMG CORBA Kazimierz Subieta Instytut Podstaw Informatyki PAN, Warszawa Polsko-Japońska Wyższa Szkoła Technik Komputerowych, Warszawa K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 1 listopad 1999 Wołanie statyczne: krok po kroku (1) interfejsy serwera (klasy obiektów) używając IDL. Interfejsy w 1 Zdefiniuj IDL informują klienta o obiektach, które są w zasięgu ORB, o ich atrybutach, o metodach, które wolno stosować, o parametrach i wyniku tych metod, oraz o wyjątkach, które mogą być powodowane przez metody. 2 Wprowadź definicję interfejsu do repozytorium interfejsów, używając do tego celu specjalnego udogodnienia. Informację tę mogą wykorzystywać programy aplikacyjne np. dla celów wołań dynamicznych. prekompilator do definicji interfejsów w IDL. Typowy prekompilator 3 Zastosuj CORBA wyprowadza co najmniej trzy rodzaje kodu wyjściowego: 1) pniaki klienta dla metod zdefiniowanych w IDL. Pniaki te są używane przez program klienta w celu statycznego dostępu do obiektów. 2) szkielety serwera, określające nagłówki metod (+ inne informacje), które mają być zaimplementowane po stronie serwera. 3) Specyficzną dla danego języka programowania definicję klasy (np w Java lub C++). 1) i 3) nie wymagają dalszych zabiegów, 3) musi być zapełnione kodem. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 2 listopad 1999 Wołanie statyczne: krok po kroku (2) 4Dodaj kod po stronie serwera do szkieletu wyprodukowanego przez wyrażenie IDL. Kod ten implementuje metody zdefiniowane w wyrażeniu IDL. ten kod, używając w tym celu normalnego kompilatora wybranego 5 Skompiluj języka programowania. obiekty serwera w Repozytorium Implementacji. ORB używa tej 6Zarejestruj informacji celem zlokalizowania aktywnych obiektów lub celem wykonania ich aktywacji. Rejestracja obiektów wymaga napisania programu o dość standardowej budowie. instancje obiektów na serwerze. W czasie startu aplikacji, Adapter 7 Utwórz Obiektów znajdujacy się na serwerze może tworzyć obiekty, które będą obsługiwać odległe wołania metod ze strony klienta. CORBA definiuje specjalne strategie Adaptera Obiektów, które są używane do tworzenia i zarządzania tego rodzaju obiektami. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 3 listopad 1999 Wołanie statyczne: krok po kroku (3) 8Zaimplementuj kod aplikacji klienta, która będzie używać obiektów serwera wcześniej zdefiniowanych, zaimplementowanych i utworzonych. 9Skompiluj ten kod używając normalnego kompilatora wybranego języka programowania. Nie zapomnij o dołaczeniu podczas kompilacji pliku z pieńkiem klienta utworzonym z wyrażenia IDL. Podana wyżej procedura jest typowa, ale może mieć wiele odmian. Niektóre kroki mogą być pominięte, np. nie ma potrzeby definiowania wyrazenia IDL, jeżeli zostało ono wcześniej wprowadzone do Interface Repository i został już utworzony wcześniej pieniek klienta. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 4 listopad 1999 Nasz pierwszy program w CORBA: Counter Program jest minimalistyczną aplikacją klient-serwer. Jest to dzialająca aplikacja w Java pod VisiBrokerem. Zakładamy, ze po stronie serwera będzie znajdować się maciupeńki obiekt zawierający licznik (counter). Dostęp do tego obiektu będzie określony poprzez atrybut sum (suma przechowywana w liczniku) oraz przez metodę increment (zwiększ sum o 1). Metoda ta będzie zwracać wartość licznika do klienta. Co będzie robić nasza aplikacja po stronie klienta? 1) Ustawia licznik na zero; 2) Wywołuje metodę increment 1000 razy; 3) Podaje końcową sumę w liczniku; 4) Drukuje odcinek czasu, w którym działał program. 5) Powinien reagować na wyjątki. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 5 listopad 1999 Counter: wyrażenie IDL // count.idl module Counter { interface Count { attribute long sum; long increment(); }; }; Wywołanie prekompilatora: prompt>idl2java count.idl -no_comments -no_tie program VisiBrokera K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 6 nie generuj dodatkowych klas dla delegacji listopad 1999 Counter: klasy i interfejsy Java generowane przez prekompilator count.idl CORBA IDL { { Kompilator idl2java Prekompilator Counter klasa klasa klasa _st_Count CountHelper CountHolder Strona klienta Java K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 7 klasa interfejs klasa _CountImplBase Count _example_Count Strona serwera Java listopad 1999 Jakie to są pliki? _st_count: Pieniek klienta, który ma być skompilowany łącznie z jego aplikacją. Zawiera funkcje szeregujące argumenty metod. CountHelper Jest to klasa Java zapewniająca użyteczne funkcje pomocy dla klientów. (Nie jest na razie dla nas interesująca.) CountHolder Jest to klasa Java umożliwiająca traktowanie obiektów typu Count jako parametrów metod. (Nie jest na razie dla nas interesująca.) _CountImplBase Klasa Java zawierająca szkielet implementacji metod od strony serwera. Zajmuje się roszeregowaniem argumentów metod. Count Interfejs Java automatycznie generowany z wyrażenia IDL. Musimy przewidzieć kod, który zaimplementuje ten interfejs. _example_Count Przykładowa klasa, ustalająca ramowe założenia metod, które musimy wypełnić kodem implementacji. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 8 listopad 1999 Counter: Pieniek klienta generowany automatycznie _st_count: Jest to wewnętrzna implementacja pieńka klienta dla interfejsu Count. Zajmuje się głównie szeregowaniem argumentów wołań do serwera. Nie musimy interesować się tym kodem. Wszystko, co należy z nim zrobić, to skompilować i zlinkować go łącznie z aplikacją klienta. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 9 package Counter; public class _st_Count extends org.omg.CORBA.portable.ObjectImpl implements Counter.Count { public java.lang.String[] _ids() { return __ids; } private static java.lang.String[] __ids = { "IDL:Counter/Count:1.0" }; public int increment() { try { org.omg.CORBA.portable.OutputStream _output = this._request("increment", true); org.omg.CORBA.portable.InputStream _input = this._invoke(_output, null); int _result; _result = _input.read_long(); return _result; } catch(org.omg.CORBA.TRANSIENT _exception) { return increment(); } } public void sum(int sum) { try { org.omg.CORBA.portable.OutputStream _output = this._request("_set_sum", true); _output.write_long(sum); org.omg.CORBA.portable.InputStream _input = this._invoke(_output, null); } catch(org.omg.CORBA.TRANSIENT _exception) { sum( sum ); } } public int sum() { try { org.omg.CORBA.portable.OutputStream _output = this._request("_get_sum", true); org.omg.CORBA.portable.InputStream _input = this._invoke(_output, null); int _result; _result = _input.read_long(); return _result; } catch(org.omg.CORBA.TRANSIENT _exception) { return sum(); } } } listopad 1999 Counter: Szkielet serwera generowany automatycznie _CountImplBase Jest to wewnętrzna implementacja szkieletu serwera dla interfejsu Count. Zajmuje się głównie rozszeregowaniem argumentów wołań do serwera. Nie musimy interesować się tym kodem. Wszystko, co należy z nim zrobić, to skompilować i zlinkować go łącznie z programem serwera. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 10 package Counter; abstract public class _CountImplBase extends org.omg.CORBA.portable.Skeleton implements Counter.Count { protected _CountImplBase(java.lang.String name) { super(name); } protected _CountImplBase() { } public java.lang.String[] _ids() { return __ids; } private static java.lang.String[] __ids = { "IDL:Counter/Count:1.0" }; public org.omg.CORBA.portable.MethodPointer[] _methods() { org.omg.CORBA.portable.MethodPointer[] methods = { new org.omg.CORBA.portable.MethodPointer("increment", 0, 0), new org.omg.CORBA.portable.MethodPointer("_set_sum", 0, 1), new org.omg.CORBA.portable.MethodPointer("_get_sum", 0, 2), }; return methods; } public boolean _execute(org.omg.CORBA.portable.MethodPointer method, org.omg.CORBA.portable.InputStream input, org.omg.CORBA.portable.OutputStream output) { switch(method.interface_id) { case 0: { return Counter._CountImplBase._execute(this, method.method_id, input, output); } } throw new org.omg.CORBA.MARSHAL(); } public static boolean _execute(Counter.Count _self, int _method_id, org.omg.CORBA.portable.InputStream _input, org.omg.CORBA.portable.OutputStream _output) { switch(_method_id) { case 0: { int _result = _self.increment(); _output.write_long(_result); return false; } case 1: { int sum; sum = _input.read_long(); _self.sum(sum); return false; } case 2: { int _result = _self.sum(); _output.write_long(_result); return false; } } throw new org.omg.CORBA.MARSHAL(); } } listopad 1999 Counter: interfejs w Java generowany z IDL Count package Counter; public interface Count extends org.omg.CORBA.Object { public void sum(int sum); public int sum(); public int increment(); } Musimy napisać kod, który zaimplementuje ten interfejs. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 11 listopad 1999 Counter: przykład klasy implementującej interfejs w IDL _example_Count Określany jako “example servant” - usługodawca package Counter; public class _example_Count extends Counter._CountImplBase { public _example_Count(java.lang.String name) { super(name); } public _example_Count() { super(); } public int increment() { // implement operation... return 0; } public void sum(int sum) { // implement attribute writer... } public int sum() { // implement attribute reader... return 0; } } K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 12 listopad 1999 Counter: Główny program serwera // CountServer.java: The Count Server main program Musimy napisać ten program wg pewnego wzorca. Inicjalizuje ORB, inicjalizuje BOA, tworzy obiekt count po stronie serwera i rejestruje ten obiekt w Repozytorium Interfejsów. class CountServer { static public void main(String[] args) { try { // Initialize the ORB org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); // Initialize the BOA org.omg.CORBA.BOA boa = orb.BOA_init(); // Create the Count object CountImpl count = new CountImpl("My Count"); // Export to the ORB the newly created object boa.obj_is_ready(count); // Ready to service requests boa.impl_is_ready(); } catch(org.omg.CORBA.SystemException e) { System.err.println(e); } } } K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 13 listopad 1999 Counter: Szkielet wypełniony implementacją Klasa _CountImplBase jest rozszerzona poprzez klasę CountImpl, stworzoną z przykładu _example_Count. // CountImpl.java: The Count Implementation class CountImpl extends Counter._CountImplBase { // get sum private int sum; public int sum() { return sum; // Constructors } CountImpl(String name) { super(name); // set sum System.out.println public void sum(int val) ("Count Object Created"); { sum = val; sum = 0; } } // increment method public int increment() { sum++; return sum; } Razem klasy _CountImplBase i CountImpl tworzą implementację obiektu po stronie serwera. } K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 14 listopad 1999 Counter: program klienta (nasza aplikacja) ost 21.X // CountClient.java Static Client, VisiBroker for Java class CountClient { public static void main(String args[]) { try { // Initialize the ORB System.out.println("Initializing the ORB"); org.omg.CORBA.ORB orb = org.omg.CORBA.ORB.init(args, null); // Increment 1000 times System.out.println("Incrementing"); for (int i = 0 ; i < 1000 ; i++ ) { counter.increment(); } // Bind to the Count Object System.out.println("Binding to Count Object"); Counter.Count counter = Counter.CountHelper.bind(orb, "My Count"); // Calculate stop time; print out statistics long stopTime = System.currentTimeMillis(); System.out.println("Avg Ping = " + ((stopTime - startTime)/1000f) + " msecs"); System.out.println("Sum = " + counter.sum()); } catch(org.omg.CORBA.SystemException e) { System.err.println("System Exception"); System.err.println(e); } // Set sum to initial value of 0 System.out.println("Setting sum to 0"); counter.sum((int)0); // Calculate Start time long startTime = System.currentTimeMillis(); } } K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 15 listopad 1999 Wołanie dynamiczne: krok po kroku (1) obiekt o jego 1 Spytaj Otrzymasz InterfaceDef definicję interfejsu, wołajac metodę get_interface. obiekt, który opisuje twój obiekt w Repozytorium Interfejsów. 2Poszukaj metody, która cię interesuje, poprzez wywołanie metody lookup_name na otrzymanym obiekcie InterfaceDef. Otrzymasz obiekt typu OperationDef. opis interesującej cie metody, poprzez wywołanie metody describe na 3Odzyskaj obiekcie OperationDef. 4Utwórz pustą listę NVList, poprzez metodę create_list. Lista ta będzie przeznaczona na wartości argumentów twojej metody. 5Zapełń NVlist wartościami argumentów, używając metod add_item i add_value. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 16 listopad 1999 Wołanie dynamiczne: krok po kroku (2) obiekt Request twojego zlecenia, poprzez wywołanie metody create_request. Trzeba zakumonikować dla tej metody: 1) nazwę interesującej cie metody, 2) NVlist, 3) NamedValue w którym będzie zwrócony rezultat metody. 6Utwórz Wywołaj odległą operację, poprzez wywołanie invoke na obiekcie Request. Jest 7 to wywołanie synchroniczne. Rezultat wywołanie pojawi się w obiekcie Request. Wykorzystaj resultat i następnie zwolnij obiekt Request, który dalej jest zbędny. 8 Zwolnij NVlist, poprzez wywołanie zlecenia free, które zwalnia miejsce związane 9z NVlist. Jak widać, zlecenia dynamiczne są dość kłopotliwe. Niektóre czynności są wspomagane przez ORB. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 17 listopad 1999 Protokoły pomiędzy ORB-ami Inter-ORB Protocols Podstawowy cel: współdziałanie pomiędzy ORB-ami wyprodukowanymi przez różne firmy. Wersje poprzedzające 2.0 nie zapewniały tej własności ze względu na brak standardu formatu danych i protokółów dla komunikacji pomiędzy ORB-ami. Bezpośrednie współdziałanie (direct interoperability): jest możliwe gdy ORB-y są umieszczone w tej samej dziedzinie: rozumieją te same referencje do obiektów, ten sam system typów w OMG IDL i te same środki bezpieczeństwa. Współdziałanie bazujące na mostach (bridge-based interoperability): jest potrzebne do komunikacji ORB-ów z różnych dziedzin. Mają one za zadanie odwzorować informację specyficzną dla jednego ORB-u w informację właściwa dla innego. General Inter-ORB Protocol (GIOP) - specyfikuje składnie transferowanej informacji, format komunikatów. Jest prosty i łatwy w implementacji. Internet Inter-ORB Protocol (IIOP) - specyfikuje GIOP poprzez transport TCP/IP. Environment-Specific Inter-ORB Protocols (ESIOP), np. bazujący na OSF DCE. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 18 listopad 1999 Rodzaje usług obiektowych (1) Object Services Usługa w zakresie cyklu życiowego (Life Cycle Service). Definiuje operacje tworzenia, kopiowania, przemieszczania, i usuwania komponentów (obiektów) będących pod kontrolą danej aplikacji zintegrowanej poprzez standard CORBA. Usługa w zakresie trwałości (Persistence Service). Definiuje interfejs do składowania komponentów (obiektów) na trwałych nośnikach, włączając w to obiektowe bazy danych, relacyjne bazy danych i zwykłe pliki. Usługa w zakresie nazywania (Naming Service). Pozwala nadać komponentom (obiektom) nazwy (o hierarchicznej budowie) oraz odzyskać identyfikatory komponentów (obiektów) na podstawie ich nazw. Usługa pozwala przywiązać komponenty (obiekty) do istniejącego nazewnictwa katalogów systemów operacyjnych lub kontekstów nazwowych wg różnorodnych systemów: ISO X.500, OSF DCE, Sun NIS+, Novell NDS, Internet LDAP. Usługa w zakresie zdarzeń (Event Service). Pozwala określić, czy dane komponenty mają reagować (nie reagować) na określone zdarzenia. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 19 listopad 1999 Rodzaje usług obiektowych (2) Object Services Usługa w zakresie współbieżności (Concurrency Control Service). Pozwala zakładać/zdejmować zamki na obiekty (lub inne byty) celem przeciwdziałania kolizjom transakcji lub wątków. Usługa w zakresie transakcji (Transaction Service). Przewiduje koordynację transakcji opartą na dwufazowym potwierdzeniu (2PC) dla prostych i zagnieżdżonych transakcji. Usługa w zakresie związków (Relationship Service). Przewiduje dynamiczne tworzenie/usuwanie powiązań (związków, asocjacji) pomiędzy obiektami, wymuszanie więzów referencyjnych, oraz nawigację od obiektów do obiektów wg zdefiniowanych dla nich związków. Usługa w zakresie udostępniania obiektów na zewnątrz (Externalization Service). Przewiduje wstawianie i odczytywanie danych do/z komponentów (obiektów). K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 20 listopad 1999 Rodzaje usług obiektowych (3) Object Services Usługa w zakresie zapytań (Query Service). Przewiduje dostęp do obiektów poprzez różnorodne języki zapytań, wśród nich SQL-92, nowo powstający standard SQL3, oraz obiektowy język zapytań (standardu ODMG) OQL. Usługa w zakresie licencji (Licensing Service). Usługa pozwala na pomiary użycia komponentów (obiektów) oraz wyliczenie opłat za użycie w ramach sesji, węzła sieci, itd. Usługa w zakresie dodatkowych własności obiektów (Properties Service). Pozwala dynamicznie związać z obiektami dowolne nazwane własności (atrybuty), np. datę utworzenia, datę ostatniej modyfikacji, nazwisko modyfikującego, itd. Usługa w zakresie czasu (Time Services). Przewiduje interfejsy do synchronizowania czasu w środowisku rozproszonym. Pozwala również definiować zdarzenia wyzwalane przez upływ czasu. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 21 listopad 1999 Rodzaje usług obiektowych (4) Object Services Usługa w zakresie ochrony (Security Service). Zapewnia możliwości pełnej ochrony rozproszonych obiektów. Wspomaga autoryzację, sterowanie dostępem, tajność i przeciwdziałanie unikaniu zapłaty (non-repudiation). Zarządza także oddelegowywaniem uwierzytelnień (credentials). Usługa handlowa (Trader Service). Przewiduje odzyskiwanie informacji o obiektach na podstawie ich własności, publikować informacje o serwisach dostarczanych przez obiekty, itd. Usługa w zakresie kolekcji (Collection Service). Przewiduje interfejsy do tworzenia najczęściej spotykanych kolekcji (zbiorów, wielozbiorów, sekwencji, itd.) i manipulacji tymi kolekcjami. Zestaw usług obiektowych jest rozszerzany w planowanym standardzie CORBA 3.0. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 22 listopad 1999 Zasady projektowania usług obiektowych • Oddzielenie interfejsu i implementacji • Referencje do obiektów podlegają kontroli typu poprzez interfejsy • Klienci zależą od interfejsów, a nie od implementacji • Stosowane jest wielo-dziedziczenie interfejsów • Stosowana jest metoda tworzenia podtypów dla rozszerzenia, ewolucji i specjalizacji funkcjonalności • Prostota, elastyczność, generyczność serwisów • Umożliwienie lokalnych i odległych implementacji obiektów Interfejsy wołań zwrotnych (Callback Interfaces) - serwer woła wykonanie usług ze strony klienta - np. przekazywanie danych asynchronicznie do klienta Brak globalnych przestrzeni identyfikatorów zakres identyfikatorów jest zawsze ograniczony do pewnego kontekstu. K.Subieta. Bazy danych i inżynieria oprogramowania, Wykład 4, Folia 23 listopad 1999