Web Service – implementacja aplikacji klienta usługi Marek Lewandowski, Paweł Kędziora Politechnika Poznańska [email protected], [email protected] Spis treści: 1 2 3 4 5 Technologia Web Service ........................................................................................... 3 1.1 Definicja Web Service ........................................................................................ 3 1.2 Architektura Web Service................................................................................... 3 1.3 Protokół SOAP ................................................................................................... 4 1.4 Język WSDL ....................................................................................................... 6 1.5 Rejestr UDDI ...................................................................................................... 7 Przykładowa aplikacja ................................................................................................ 8 2.1 Aplikacja standardowa........................................................................................ 8 2.2 Aplikacja – klient Web Service .......................................................................... 9 Klient Web Service ................................................................................................... 11 3.1 Środowiska wspierające tworzenie aplikacji klienta usług sieciowych............ 11 3.1.1 Schemat postępowania.............................................................................. 11 3.1.2 Java ........................................................................................................... 12 3.1.3 Microsoft .NET ......................................................................................... 17 3.1.4 Borland Delphi.......................................................................................... 20 3.1.5 Oracle Forms............................................................................................. 23 3.1.6 Lotus Designer .......................................................................................... 28 3.1.7 Borland C++ Builder ................................................................................ 31 3.1.8 Php ............................................................................................................ 32 3.1.9 C/C++........................................................................................................ 33 3.1.10 Ada............................................................................................................ 34 3.2 Środowiska nie zapewniające wsparcia w procesie tworzenia aplikacji klienta usług sieciowych........................................................................................................... 35 3.2.1 Rozwiązanie manualne ............................................................................. 35 3.2.2 Rozwiązanie półautomatyczne.................................................................. 38 Podsumowanie .......................................................................................................... 39 Literatura:.................................................................................................................. 40 2 1 Technologia Web Service 1.1 Definicja Web Service Web Service to zwarty, samodokumentujący się komponent programowy niezależny od platformy i implementacji dostarczający określonej funkcjonalności. Komponent ten może zostać opublikowany w sieci komputerowej przez swego autora, a następnie odnaleziony i wywołany w trybie zdalnego wykonania przez twórcę aplikacji konsumenckiej. Technologia Web Service wykorzystuje szereg rozwiązań informatycznych, m.in.: - SOAP – służący do przekazywania zdalnych wywołań, WSDL – służący do dystrybucji parametrów połączeń sieciowych, UDDI – służący do rejestracji udostępnianych komponentów usługowych. 1.2 Architektura Web Service Idea działania usługi Web Service została przedstawiona na rysunku 1.2.1. Zarówno aplikacja (Service Requester), żądająca wywołania kodu zdalnego modułu, jak i komponent Web Service (Service Provider) go udostępniający, pobierą interfejs kodu z określonego miejsca w sieci Internet (Service Broker). Zarówno żądanie wywołania zdalnej usługi jak i zwracany rezultat przekazywane są za pomocą komunikatu SOAP (patrz: 1.3 Protokół SOAP). Interfejs kodu przekazywany jest stronom z wykorzystaniem dokumentu WSDL (patrz: 1.4 Język WSDL), który przechowywany jest w bazie danych UDDI (patrz: 1.5 Rejestr UDDI). Rys. 1: Ogólna idea Web Service 3 1.3 Protokół SOAP SOAP (Simple Object/Open Access Protocol) jest protokołem opartym o XML (eXtensible Markup Language), umożliwiającym aplikacjom wymianę komunikatów poprzez protokół sieciowy - zazwyczaj HTTP (HyperText Transfer Protocol). W ogólności, aplikacje wykorzystujące SOAP mogą być zaimplementowane w różnych językach i pracować na różnych platformach. Komunikacja sieciowa może odbywać się na dwa sposoby: - w stylu RPC (Remote Procedure Call) - komunikacji dokumentowej Powyższe tryby komunikacji różnią się formą przekazywania parametrów: w trybie RPC komponentowi przekazywana jest lista parametrów wraz z ich bieżącymi wartościami, a w trybie komunikacji dokumentowej usługa otrzymuje tylko jeden parametr, którym jest dokument XML. Zazwyczaj tryb RPC korzysta z komunikacji synchronicznej, a tryb dokumentowy z komunikacji asynchronicznej. Schemat komunikacji w trybie dokumentowym przedstawiony został na rysunku 1.3.1: Rys. 2: Komunikacja SOAP w trybie dokumentowym. Wywołanie metody przez klienta jest konwertowane do dokumentu XML. Argumenty poddawane są serializacji (konwertowane do ciągu bajtów reprezentowanego heksadecymalnie). Tak zbudowany dokument XML nazywany komunikatem SOAP przekazywany jest z wykorzystaniem protokołu sieciowego do zdalnej usługi, która po deserializacji argumentów uruchamia żądaną metodę i analogicznym algorytmem przekazuje zwrotnie rezultat jej wykonania. 4 Komunikat SOAP składa się z następujących elementów: - element obowiązkowy <Envelope> - oznaczający, iż dokument XML jest komunikatem SOAP, - element opcjonalny <Header> - zawierający informacje nagłówkowe, - element obowiązkowy <Body> - zawierający informacje o żądaniu i odpowiedzi, - element opcjonalny <Fault> - zawierający opis błędów, jakie wystąpiły podczas przetwarzania komunikatu. Poniższy rysunek (rys. 1.3.2) zawiera przykładowy komunikat SOAP żądający wywołania komponentu o nazwie „demo”, zawierającego funkcję multiply (int val1, int val2). Przykład pokazuje przekazanie do funkcji dwóch parametrów multiply (val1 := 3, val2 := 2). Usługa zwraca odpowiedź, również w formacie komunikatu SOAP – wynik iloczynu parametrów val1 i val2. Rys. 3: Przykładowy komunikat - żądanie SOAP. Rys. 4: Przykładowy komunikat – odpowiedź SOAP. 5 1.4 Język WSDL WSDL (Web Service Description Language) jest opisem interfejsu komponentu Web Service. Klient usługi sieciowej może dokonać automatycznej transformacji tego opisu do kodu źródłowego obsługującego komunikację sieciową z komponentem Web Service Proxy w wybranym języku programowania. Opisywana transformacja może mieć charakter statyczny (dokonywana na etapie kompilacji) lub dynamiczny (dokonywana podczas wykonywania aplikacji klienta). WSDL jest językiem znaczników XML służącym do opisu technicznych parametrów połączenia sieciowego aplikacji klienta i komponentu Web Service. Strukturę znaczników dokumentu WSDL przedstawia rysunek 1.4.1: Rys. 5: Struktura znaczników dokumentu WSDL. Znaczniki w dokumencie WSDL: - <definitions> - otacza dokument, - <service>, <port> - definiują adresy punktów dostępowych dla usługi, - <portType> - deklaracja funkcji biznesowych oferowanych przez usługę, - <binding> - określają metody kodowania parametrów wywołania i parametrów zwrotnych usługi. 6 1.5 Rejestr UDDI UDDI (Universal Description, Discovery and Integration) jest specyfikacją bazy danych dostępnych komponentów Web Service. UDDI ma na celu uproszczenie procesu dystrybucji dokumentów WSDL i semantyki komponentów usługowych. Taka baza danych przeszukiwana jest przez autorów aplikacji klientów w celu odnalezienia żądanych komponentów. Bazy danych UDDI deklarują dostępne usługi posługując się trzema poziomami opisu: - White Pages – podstawowe dane kontaktowe dostawcy usługi, - Yellow Pages – lokalizacja usługi w taksonomiach kategoryzacyjnych, - Green Pages – techniczny opis usługi i jej semantyki, wskaźnik do pliku WSDL. Rysunek 1.5.1 przedstawia cykl życia usługi Web Service z punktu widzenia jej deklaracji w UDDI: Rys. 6: Cykl życia usługi Web Service. Cykl życia usługi Web Service: - implementacja komponentu i jego rejestracja w UDDI, - wyszukanie opisu komponentu i implementacja aplikacji klienta, - uruchomienie aplikacji klienta i zdalne wywołanie usługi. 7 2 Przykładowa aplikacja 2.1 Aplikacja standardowa Punktem wyjścia do dalszej analizy jest przykładowa aplikacja (formularz rejestracji wniosku o przyznanie zaliczki alimentacyjnej), której główną formatkę przedstawia poniższy rysunek: Rys. 7: Formularz wprowadzania danych osobowych przykładowej aplikacji. Użytkownik, chcąc poprawnie wypełnić wniosek, wprowadza wymagane dane dotyczące wnioskodawcy. Wsparcie ze strony systemu ogranicza się do udostępnienia użytkownikowi list wyboru z predefiniowanymi wartościami dla pewnych pól 8 (np. obywatelstwo, stan cywilny). Osoba obsługująca program nie ma możliwości weryfikacji poprawności wprowadzanych danych. Nie jest dostępne również ułatwienie polegające na przykład na uzupełnianiu brakujących wartości pól formularza, po wprowadzeniu danych jednoznacznie identyfikujących wnioskodawcę (np. PESEL). 2.2 Aplikacja – klient Web Service Postanowiono rozszerzyć funkcjonalność przykładowej aplikacji o rozwiązania ułatwiające pracę użytkownikowi. Zaimplementowano trzy usługi Web Service: - Weryfikacja danych osobowych bez przekazywania poprawnych danych – celem jest weryfikacja poprawności danych osobowych przekazanych przez użytkownika. Usługa wskazuje jedynie, które informacje nie są poprawne. - Weryfikacja danych osobowych z przekazaniem poprawnych danych - celem jest weryfikacja poprawności danych osobowych przekazanych przez użytkownika. Usługa wskazuje, które informacje nie są poprawne oraz podaje poprawne wartości błędnych danych. - Uzupełnianie danych osobowych – celem jest dostarczenie nowych, nieznanych użytkownikowi wartości danych osobowych. Użytkownik przekazuje dane niezbędne do identyfikacji wnioskodawcy, a usługa wypełnia wszystkie brakujące pola formularza poprawnymi wartościami. Jeżeli identyfikacja wnioskodawcy nie będzie pełna (kilka osób spełniających kryteria wyszukiwania), użytkownikowi zostaną zaprezentowane wszystkie wyniki. Jako przykładowe rozwiązanie zaimplementowano aplikację udostępniającą formularz do wprowadzania danych osobowych oraz zawierającą wywołania powyżej opisanych usług Web Service: Rys. 8: Formularz wprowadzania danych przykładowej aplikacji wykorzystującej usługi Web Service. 9 Rys. 9: Weryfikacja poprawności wprowadzanych danych bez przekazywania poprawnych wartości (pola z błędnymi danymi podświetlone kolorem czerwonym). Rys. 10: Weryfikacja poprawności wprowadzonych danych z przekazaniem poprawnych wartości (pola z błędnymi danymi podświetlone kolorem czerwonym, poprawne wartości wpisane w pola). Rys. 11: Uzupełnianie danych osobowych (formularz z uzupełnionymi danymi; weryfikacja niejednoznaczna: kilka osób spełniających wyniki zapytania – aktywny przycisk następna strona, wciśnięcie którego powoduje prezentację użytkownikowi danych kolejnej osoby). 10 3 Klient Web Service 3.1 Środowiska wspierające tworzenie aplikacji klienta usług sieciowych 3.1.1 Schemat postępowania Wiele środowisk programowania zapewnia programistom wsparcie w procesie tworzenia klientów usług sieciowych (w postaci kreatorów generujących klasy – pieńki usług i klasy – proxy odpowiedzialne za komunikację z dostawcą Web Service, lub w postaci gotowych bibliotek umożliwiających wywoływanie zdalnych usług i prezentację ich rezultatów). Programista może się więc skoncentrować na tworzeniu interfejsu użytkownika i logiki biznesowej aplikacji. Złożony proces implementacji komunikacji z usługą sieciową spoczywa na środowisku programistycznym. Rys. 12: Kolejne kroki tworzenia i działania klienta Web Service w przypadku środowiska z kreatorem szkieletu aplikacji. W poniższych podrozdziałach zaprezentowano kolejne kroki procesów tworzenia klientów usług sieciowych w różnych środowiskach i językach programowania. 11 3.1.2 Java Język Java, najpowszechniej używany i intensywnie rozwijany, zapewnia bardzo dobre wsparcie korzystania z usług Web Service. Aby ułatwić implementację obsługi protokołu SOAP można skorzystać z biblioteki JAX-RPC (Java API for XML-based RPC). Biblioteka ta zapewnia narzędzie (wscompile), które znajduje i odczytuje dokument WSDL, a następnie generuje pieniek (ang. stub) po stronie klienta. Wygenerowane pieńki są klasami i interfejsami języka JAVA, które będą mogły być wywoływane przez programistę. Pieniek stanowi interfejs pomiędzy aplikacją klienta a serwerem – jeśli usługa Web Service znajdująca się na serwerze oferuje metodę filling(), to wygenerowany pieniek, również będzie zawierał metodę o takiej nazwie. Programista chcąc skorzystać z metody filling() usługi sieciowej, wywołuje metodę filling() swojego pieńka, który przejmuje przekazane mu parametry funkcji i zamienia je na żądanie wysyłane do komponentu Web Service. Żądanie wysyłane jest za pomocą protokołu HTTP z wykorzystaniem opisanego wcześniej protokołu SOAP. Tworzenie aplikacji – klientów usług Web Service jest bardzo dobrze wspierane przez praktycznie wszystkie środowiska stworzone dla języka Java (m.in. Eclipse, JDeveloper, NetBeans). Każde z tych środowisk wyposażone jest w kreator tworzenia pieńka usługi Web Service, który krok po kroku przeprowadza programistę przez cały proces: od znalezienia dokumentu WSDL, poprzez generowanie klas i interfejsów usługi zdalnej, aż do stworzenia szkieletu aplikacji klienta. Poniższe ilustracje pokazują przykładowy scenariusz utworzenia klienta usługi Web Service w środowisku JDeveloper. Rys. 13: Wybór Business Tier -> Web Services -> Java Web Service Proxy z menu kontekstowego nowego projektu. 12 Rys. 14: Wskazanie pliku WSDL i pliku mapowań. Rys. 15: Zakończenie pracy kreatora: lista metod udostępnianych przez komponent. 13 Rys. 16: Ostateczna lista plików i pakietów stworzonych podczas generowania klienta usługi Web Service z wykorzystaniem dostępnego pliku WSDL. 14 Rys. 17: Przykładowa funkcja wywołująca (za pomocą pieńka web) zdalną metodę. Wywołanie funkcji filling, wypełniającej dane osobowe w formularzu użytkownika, znajduje się w linii: response = (port.filling(request)); Obiekt port jest instancją klasy WSPServicePortClient, która w swoim konstruktorze (pośrednio – tworząc również kilka innych obiektów) tworzy pieniek usługi sieciowej: public class WSPServicePortClient { private project1.WSPService_PortType _port; public WSPServicePortClient() throws Exception { ServiceFactory factory = ServiceFactory.newInstance(); _port = ((project1.WSPService_Service)factory.loadService(project1.WSPService_Service.c lass)).getWSPServicePort(); } ... } public interface WSPService_Service extends javax.xml.rpc.Service { public project1.WSPService_PortType getWSPServicePort() throws javax.xml.rpc.ServiceException; } public class WSPService_Service_Impl extends oracle.j2ee.ws.client.BasicService implements project1.WSPService_Service { public project1.WSPService_PortType getWSPServicePort() { String[] roles = new String[] {}; HandlerChainImpl handlerChain = new HandlerChainImpl(getHandlerRegistry().getHandlerChain(ns1_WSPServicePort_ QNAME)); handlerChain.setRoles(roles); project1.proxy.runtime.WSPServiceBinding_Stub stub = new project1.proxy.runtime.WSPServiceBinding_Stub(handlerChain); try { stub._initialize(super.internalTypeRegistry); 15 } catch (JAXRPCException e) { throw e; } catch (Exception e) { throw new JAXRPCException(e.getMessage(), e); } return stub; } } Obiekt pieńka zajmuje się wywołaniem funkcji serializujących i deserializujących (przygotowanie i konsumpcja komunikatów SOAP zawierających rezultat działania usługi): { QName type = new QName("http://wsp/service", "filling"); CombinedSerializer serializer = new project1.runtime.Filling_LiteralSerializer(type, DONT_ENCODE_TYPE); registerSerializer(mapping,project1.Filling.class, type, serializer); } public Filling_LiteralSerializer(QName type, boolean encodeType) { super(type, true, encodeType); setSOAPVersion(SOAPVersion.SOAP_11); } Wynik działania przypisywany jest zmiennej response: response = (port.filling(fill)).getResult(); Przykładowy kod odpowiedzialny za konsumpcję rezultatu działania usługi Web Service (wypełnienie odpowiednich pól formularza i, jeśli to wskazane, aktywacja przycisków umożliwiających wyświetlenie danych osobowych większej liczby osób): response = p.filling(); Consument c = new Consument(this); c.filling_consume(resp, turn); … public void filling_consume(WSPMultiResponseVO response, Integer turn) { handleMultiStatus(response, turn); } … private void handleMultiStatus (WSPMultiResponseVO response, Integer turn) { switch (response.getStatus()) { case 1: panel.getField("error_field").setText("WSP_FILLING_UNAUTHORIZED"); break; case 2: panel.getField("error_field").setText("WSP_FILLING_INVALID"); break; case 3: panel.getField("error_field").setText("WSP_FILLING_UNAUTHORIZED_ATR"); break; case 0: getAllAttrValues(response.getAttributes(), turn); break; default: panel.getField("error_field").setText("UNKNOWN_ERROR: "+response.getStatus()); } } … 16 private void getAllAttrValues(AttrValArrayVO[] attrValArrayVOs, Integer turn) { try { if (turn >= attrValArrayVOs.length || turn < 0) { return; } panel.next_page.setEnabled(true); panel.prev_page.setEnabled(true); for (int j=0; j<(attrValArrayVOs[turn].getAttributes()).length; j++) { String name = new String(); String value = new String(); name = (attrValArrayVOs[turn].getAttributes())[j].getAttrName(); value = (attrValArrayVOs[turn].getAttributes())[j].getAttrVal(); JTextField field = panel.getField(name); field.setText(value); } ++turn; if (turn.equals(attrValArrayVOs.length)) { panel.next_page.setEnabled(false); } --turn; if (turn<=0) { panel.prev_page.setEnabled(false); } } catch (Exception e) { System.out.println(e.getMessage()); } } 3.1.3 Microsoft .NET Środowisko .NET firmy Microsoft, podobnie jak opisane w punkcie 2.1 środowiska stworzone do kodowania w języku Java, również bardzo dobrze wspiera programistę podczas tworzenia aplikacji wykorzystujących usługi Web Service. Ogólna idea tworzenia aplikacji klienta jest bardzo podobna do rozwiązania znanego z Javy (użycie kreatora, odnalezienie dokumentu WSDL, oprogramowanie aplikacji klienta, itd). Środowisko .NET umożliwia tworzenie aplikacji klientów we wszystkich (ponad 20) wspieranych przez siebie językach (m.in. Visual C#, Visual Basic, Visual C++, Visual J#).1 Komponent, do którego programista się odwołuje, został napisany w języku Visual Basic. Udostępniona metoda filling() nie przyjmuje parametrów wejściowych, zwraca typ złożony DataSet i wygląda następująco: 1 Oprócz wspomnianych również: APL, Fortran, Pascal, Haskell, Scheme, Curriculum, Mondrian, Perl, Pyton, COBOL, Microsoft JScript®, SmallTalk, Eiffel, Oberon, RPG, Component Pascal, Merkury, Nemerle, Standard ML, Forth, Oz. 17 Rys. 18: Funkcja filling() komponentu Web Service w języku Visual Basic. Poniższe rysunki pokazują przykładowy scenariusz tworzenia klienta usługi Web Service za pomocą języka Visual Basic. Rys. 19: Utworzenie nowego projektu. 18 Rys. 20: Stworzenie formatki. Rys. 21: Wybór opcji WebService Proxy Generator z menu Tools w zakładce Code formatki. 19 Rys. 22: Wskazanie lokalizacji pliku WSDL. Rys. 23: Zakończenie generowania usługi klienta. Rys. 24: Kod wywoływany po wciśnięciu przycisku na formatce w aplikacji klienta. Wywołanie funkcji filling() komponentu Web Service. 3.1.4 Borland Delphi 20 Środowisko Delphi firmy Borland umożliwia, podobnie jak wcześniej omawiane Java i Microsoft .NET, zarówno manualne jak i automatyczne tworzenie aplikacji – klienta korzystającej z usług Web Service. Aby automatycznie wygenerować klienta usługi sieciowej Web Service należy posłużyć się wbudowanym w środowisko Delphi programem WSDL Importer, który krok po kroku przeprowadzi programistę przez wszystkie etapy tworzenia aplikacji korzystającej z komponentu Web Service. Poniższe rysunki pokazują przykładowy scenariusz tworzenia usługi Web Service za pomocą programu WSDL Importer: Rys. 25: Utworzenie nowego projektu typu Web Service (File New Other zakładka WebServices opcja WSDL Importer). Rys. 26: Wskazanie pliku WSDL. 21 Rys. 27: Podgląd wygenerowanego kodu. Po udanym wykonaniu powyższych kroków należy stworzyć klienta, który będzie korzystał z funkcji komponentu, którego dokument WSDL został zaimportowany. Należy stworzyć nową aplikację, dodać do niej elementy: memo, button oraz edit box. Następnie, z zakładki Web Services, należy przeciągnąć na formatkę komponent HTTPRIO. Rys. 28: Wygląd formatki. Komponent HTTPRIO (Remote Invokable Object over an HTTP connection) posiada cztery własności: - URL - Service - WSDLLocation 22 - Port Należy wypełnić tylko pierwszą, bądź pozostałe własności. Poprawne wartości własności zostaną użytkownikowi podpowiedziane (zostały zapamiętane podczas importu dokumentu WSDL). Tak utworzony komponent HTTPRIO zawierać będzie wszystkie metody udostępniane przez usługę Web Service, można zatem przystąpić do etapu programowania z wykorzystaniem zdalnych metod. Zaproponowany scenariusz pokazuje, że automatyczne budowanie klienta usług sieciowych w środowisku Delphi jest nieco bardziej skomplikowane niż wykonywanie analogicznego działania w środowiskach języka Java lub za pomocą platformy .NET firmy Microsoft. Niemniej jednak, jeśli wziąć pod uwagę możliwość manualnego pisania warstwy importującej dokument WSDL i zapewniającej komunikację z usługa sieciową, to wykorzystanie załączonego programu (WSDL Importer) nieporównywalnie usprawnia i ułatwia pracę programisty. Korzystanie z Web Service możliwe jest tylko od wersji Delphi 6. 3.1.5 Oracle Forms Środowisko Oracle Forms pozwala na “stosunkowo łatwą” (jak podaje producent) integrację istniejącej aplikacji Forms z usługą sieciową dzięki użyciu importera Java. Aby wywoływać metody usług sieciowych z aplikacji Forms należy przeprowadzić dwuetapowe postępowanie: utworzyć pieniek usługi Web Service, a następnie wywołać funkcje pieńka z poziomu aplikacji Forms. Poniższe rysunki pokazują kolejność postępowania podczas tworzenia pieńka usługi Web Service za pomocą środowiska JDeveloper: 23 Rys. 29: Wybór Business Tier -> Web Services -> Java Web Service Proxy z menu kontekstowego nowego projektu. Rys. 30: Wskazanie pliku WSDL i pliku mapowań. 24 Rys. 31: Zakończenie pracy kreatora: lista metod udostępnianych przez komponent. Rys. 32: Spakowanie plików projektu do archiwum .jar 25 Należy wykorzystać stworzony pieniek w aplikacji Oracle Forms. Poniższe rysunki wskazują kolejne kroki niezbędne do wykorzystywania usług Web Service w aplikacji Forms: Należy dodać do zmiennej systemowej PATH pełną ścieżkę dostępu do archiwum .jar utworzonego w poprzednim kroku (tworzenie pieńka usługi Web Service za pomocą środowiska JDeveloper): Rys. 33: Modyfikacja zmiennej systemowej PATH. Należy uruchomić środowisko Oracle Forms, stworzyć nowy formularz, oraz wybrać opcję importu klasy Java i zaimportować niezbędne klasy (wcześniej utworzoną klasę pieńka usługi Web Service, java.lang.Float oraz Exception). Kolejnym krokiem jest dodanie przycisku do kanwy i zaprogramowanie wyzwalacza uruchamianego zdarzeniem wciśnięcia przycisku kodem wywołującym metodę usługi Web Service: 26 Rys. 34: Import klasy Java z Oracle Forms. Rys. 35: Dodanie przycisku do kanwy i uruchomienie okna edycji procedury wyzwalanej uruchamianej zdarzeniem wciśnięcia przycisku. 27 Rys. 36: Kod procedury wyzwalanej wywołującej metodę udostępnianą przez usługę Web Service. Korzystanie z usług sieciowych możliwe jest w Oracle Forms od wersji 9i wzwyż. Użytkownik korzystający z Oracle Forms 4.5 oraz Oracle Forms 6i muszą dokonać migracji do wersji Oracle Forms 9i. 3.1.6 Lotus Designer W środowisku Lotus Designer firmy IBM aplikacja – klient usługi sieciowej Web Service może zostać stworzona jako agent oprogramowany w języku Java bądź LotusScript. Środowisko Lotus Designer (w standardowej wersji) nie posiada wbudowanego mechanizmu umożliwiającego programiście konsumpcję usług Web Service (tworzenie i publikacja usług jest jednak możliwa!). Przed stworzeniem klienta komponentu Web Service należy dodatkowo zainstalować: - Java Software Development Kit (JDK) - Apache Axis framework Po zainstalowaniu powyższych elementów należy odnaleźć interesujący dokument WSDL i wskazać go Apacze Axis aby wygenerował pieniek (w języku Java) usługi Web Service. W tym celu należy, w linii poleceń, wpisać następującą komendę: C:\java\consumer>wsd12java.bat http://dokument_wsdl.wsdl 28 Spowoduje to wygenerowanie plików .java, które następnie należy zaimportować do projektu w środowisku Lotus Designer. W celu zaimportowania klas, należy stworzyć bibliotekę Java (Java Library) w sekcji Script Libraries, będącej elementem podrzędnym w stosunku do elementu Shared Code: Rys. 37: Umiejscowienie sekcji Script Libraries w menu bazy danych test_ws w Lotus Domino Designer. Rys. 38: Przyciski tworzenia nowych bibliotek różnych typów w sekcji Script Libraries. Rys. 39: Przycisk Edit Project otwierający okno wyboru klas do zaimportowania. 29 Rys. 40: Okno importu klas (w ogólności: plików). Po udanym imporcie plików należy stworzyć nowego agenta. Nowotworzony agent powinien wykorzystywać klasy klienta Apache Axis, które wchodzą w skład Apache framework i stamtąd powinny być zaimportowane. Należy włączyć do projektu cały plik - archiwum JAR, znajdujący się w katalogu Axis. Należy ponadto skopiować pliki commons-discovery-0.2.jar, commons-logging-1.0.4.jar z katalogu .\Axis\lib do katalogu .\jvm\lib\ext w katalogu Lotus. Aby wprowadzone zmiany zaczęły obowiązywać, należy ponownie uruchomić klienta Lotus. Ostatnim krokiem jest oprogramowanie agenta, np. w następujący sposób: 30 Rys. 41: Przykładowy kod Java agenta Lotus. Zaprezentowane powyżej rozwiązanie dostępne jest dla środowiska Lotus od wersji 7. Użytkownik dysponujący wcześniejszymi wersjami powinien dokonać migracji do najnowszej wersji. Jeśli tego nie dokona, będzie musiał kodować komunikację protokołem SOAP manualnie. 3.1.7 Borland C++ Builder Środowisko C++ Builder firmy Borland dostarcza użytkownikowi program WSDL Importer, który wygląda i działa dokładnie tak samo jak jego odpowiednik wbudowany w środowisko Delphi tego samego producenta (patrz: punkt 2.3 Delphi). Program WSDL Importer dostępny jest od C++ Builder w wersji 6. 31 3.1.8 Php Php (Hypertext Preprocessor / Personal Home Page) nie dostarcza niestety wbudowanego mechanizmu obsługi protokołu SOAP, należy więc zainstalować moduł, który umożliwi aplikacji komunikację za pomocą SOAP. Programista ma do wyboru następujące moduły: - PEAR::SOAP, - NuSOAP, - PHP-SOAP. Pierwsze dwa udostępniają więcej możliwości, lecz są całkowicie napisane w php, a zatem są wolniejsze. PHP-SOAP jest w całości napisany w C, zatem jest najszybsze, lecz PEAR::SOAP jest najprostsze w instalacji i w zupełności wystarczające dla zdecydowanej większości zastosowań. Poniższy przykład prezentuje aplikację korzystającą z dokumentu WSDL udostępnionego przez internetowy sklep amazon.com i wyszukującą książki spełniające odpowiednie kryteria: 1. require_once 'SOAP/Client.php'; 2. $wsdl_url = 'http://dokument_wsdl.wsdl'; 3. $WSDL = new SOAP_WSDL($wsdl_url); 4. $client = $WSDL->getProxy(); 5. $params = array( 6. 'PESEL' => "12345673421", 7. 'IMIE1' => 'Edgar', 8. ... 9. ); 10. $result = $client->filling($params); Objaśnienia: - linia 1 - dołączenie klas z modułu PEAR::SOAP, - linia 2 – wskazanie adresu dokumentu WSDL, - linia 3 – inicjalizacja obiektu SOAP_WSDL poprzez przekazanie mu adresu dokumentu z linii 2, - linia 4 – funkcja getProxy() zwracająca obiekt klienta, - linie 5-9 – uzupełnienie parametrów, - linia 10 – wywołanie funkcji Web Service. Po wywołaniu funkcji cała inicjatywa przekazywana jest do PEAR::SOAP, który konwertuje przekazywane atrybuty do komunikatu SOAP zapisanego w XML i wysyła żądanie do serwera. Zwracana przez komponent wartość konwertowana jest z SOAP do php i zapisywana w zmiennej $result. 32 3.1.9 C/C++ Pracę z usługami Web Service dla języków C/C++ umożliwia pakiet gSOAP dostępny w ramach licencji Open Source. Po zainstalowaniu pakietu programista ma do dyspozycji dwa narzędzia: - wsdl2h – parser WSDL - soapcpp2 – kompilator pieńka i szkieletu aplikacji Parser wsdl2h konwertuje dokument WSDL do pliku nagłówkowego gSOAP specyfikującego usługę sieciową. Specyfikacja ta daje zrozumiały dla C/C++ widok funkcjonalności serwera. Plik nagłówkowy jest następnie przetwarzany przez soapcpp2, który generuje kod pieńka i szkielet aplikacji odwołujących się do usługi Web Service. Schemat działania pakietu gSOAP dla klienta usługi Web Service przedstawia poniższy rysunek: Rys. 42: Schemat działania pakietu gSOAP dla klienta usługi Web Sercive. Aby uzyskać plik nagłówkowy z dokumentu WSDL, należy wpisać w linii poleceń poniższą komendę: wsdl2h -o outfile.h infile.wsdl gdzie infile.wsdl jest adresem dokumentu WSDL, a output.h to ścieżka do pliku wynikowego. Wygenerowanie pieńka i szkieletu aplikacji odbywa się poprzez wpisanie w linii poleceń poniższej komendy: 33 soapcpp2 -c outfile.h gdzie outfile.h jest plikiem powstałym w wyniku działania wsdl2h. Użycie przełącznika „-c” powoduje, że wygenerowany zostanie kod w czystym języku C. Dalszy rozwój aplikacji nie powinien już nastręczać programiście większych trudności – chcąc wywołać funkcję zdalnego komponentu Web Service, wywołuje od odpowiednią metodę wygenerowanego wcześniej pieńka. Wszystkimi trudnościami związanymi z protokołem SOAP oraz komunikacją z usługą zajmuje się gSOAP. Pakiet gSOAP może być stosowany zarówno przez użytkowników systemów operacyjnych z rodziny Windows, jak i Linux. 3.1.10 Ada W celu implementacji klienta usług Web Service w języku Ada można skorzystać z biblioteki AWS (Ada Web Server), rozwijanej przez grupę GNAT i udostępnianej w ramach licencji GNU. Pierwszym krokiem do utworzenia klienta jest wygenerowanie pieńka zawierającego interfejs funkcji usługi sieciowej Web Service, za pomocą funkcji wsdl2aws, której składnia wywołania wygląda następująco: wsdl2aws [options] <file|URL> na przykład: $ wsdl2aws -noskel http://dokument_wsdl.wsdl Przełącznik –noskel wskazuje, iż ma zostać wygenerowany tylko pieniek, bez szkieletu aplikacji. Pełna lista przełączników znajduje się w dokumentacji technicznej biblioteki AWS (patrz: 18 pozycja w rozdziale Literatura). Funkcja wsdl2aws generuje stosunkowo dużą liczbę plików, wśród których znajduje się, najbardziej programistę interesujący, plik pieńka usługi Web Service, a w nim: function filling (parametry) return zwracany_typ; -- Raises SOAP.SOAP_Error if the procedure fails 34 Chcąc wywołać metodę usługi sieciowej, programista wywołuje funkcję pieńka: with Ada.Text_IO; with WSPServicePortClient.Client; procedure filling is use Ada; package LFIO is new Text_IO.Float_IO (Long_Float); begin Text_IO.Put_Line ("Wynik dzialania funkcji filling: "); LFIO.Put (WSPServicePortClient.Client.filling (parametry), Aft => 2, Exp => 0); end filling; 3.2 Środowiska nie zapewniające wsparcia w procesie tworzenia aplikacji klienta usług sieciowych 3.2.1 Rozwiązanie manualne Rys. 43: Kolejność postępowania w procesie tworzenia aplikacji klienta usługi Web Service w przypadku korzystania ze środowiska bez kreatora szkieletu aplikacji. 35 Manualna implementacja klienta usługi sieciowej, bez żadnego wsparcia ze strony środowiska programistycznego, jest procesem żmudnym, lecz jak najbardziej wykonalnym. Programista, korzysta ze zbioru definicji zawartych w dokumencie WSDL. Usługi zdefiniowane są z użyciem sześciu głównych elementów: - types – definicja typów danych używanych do opisu wymienianych komunikatów, - message – abstrakcyjna definicja wymienianych danych, - portType – zbiór abstrakcyjnych operacji, z których każda związana jest z komunikatem wchodzącym i komunikatem (komunikatami) wychodzącymi, - binding – specyfikuje protokół i format danych dla operacji i komunikatów poszczególnych elementów portType, - port – specyfikuje adres wiązania (binding), przez co tworzy pojedynczy punkt docelowy (endpoint), - service – scala zbiór odpowiadających portów. WSDL może opisywać cztery podstawowe możliwości transmisji, które są wspierane przez punkt docelowy (endpoint): - one-way – punkt docelowy otrzymuje komunikat, - request-response – punkt docelowy otrzymuje komunikat i wysyła związaną z nim odpowiedź, - solicit-response – punkt docelowy wysyła komunikat i otrzymuje związaną z nim odpowiedź, - notification – punkt docelowy wysyła komunikat. Zalecane jest korzystanie z pierwszych dwóch transmisji (zdefiniowane są dla nich wiązania) – w dokumencie WSDL odwołanie do nich następuje za pomocą elementu operation. Fragment przykładowego dokumentu WSDL z opisem poszczególnych elementów: <complexType name="WSPRequestVO"> <sequence> <element name="attributes" nillable="true" type="tns:AttrValArrayVO"/> <element name="n" type="int"/> </sequence> </complexType> <complexType name="AttrValArrayVO"> <sequence> <element maxOccurs="unbounded" minOccurs="0" name="attributes" nillable="true" type="tns:AttrValVO"/> </sequence> </complexType> <complexType name="AttrValVO"> <sequence> <element name="attrName" nillable="true" type="string"/> <element name="attrVal" nillable="true" type="string"/> </sequence> </complexType> <complexType name="filling"> <sequence> 36 <element name="WSPRequestVO_1" nillable="true" type="tns:WSPRequestVO"/> </sequence> </complexType> Zauważyć można, iż np. klasa Filling zawiera pole WSPRequestVO_1 typu WSPRequestVO. Klasa WSPRequestVO posiada pola: n (Integer) oraz attributes (AttrValArrayVO). AttrValArrayVO jest tablicą (maxOccurs = „unbounded”) obiektów typu AttrValVO, z których każdy z nich posiada dwa pola: attrName (String) oraz attrVal (String). ... <message name="WSPService_filling"> <part name="parameters" element="tns:filling"/> </message> Transport za pomocą protokołu HTTP, komunikacja „dokumentowa”, komunikaty typu request-response: <binding name="WSPServiceBinding" type="tns:WSPService"> <soap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> ... <operation name="filling"> <soap:operation soapAction=""/> <input> <soap:body use="literal"/> </input> <output> <soap:body use="literal"/> </output> </operation> ... </binding> <service name="WSPService"> <port name="WSPServicePort" binding="tns:WSPServiceBinding"> <soap:address location="adres_serwera_uslug"/> </port> </service> Programista, używając środowiska, które nie zapewnia dostatecznego wsparcia w automatycznym tworzeniu klienta usług sieciowych, musi poświęcić bardzo wiele pracy na analizę udostępnianego dokumentu WSDL – począwszy od parametrów i typów zdalnych funkcji, a na typie komunikacji i strukturze wymienianych komunikatów kończąc. Ponadto oprogramowana musi zostać również warstwa komunikacji (konstrukcja i wysyłanie oraz odbiór i przetwarzanie komunikatów SOAP) z serwerem, na którym znajduje się żądana usługa. 37 3.2.2 Rozwiązanie półautomatyczne Rys. 44: Kolejność postępowania w procesie tworzenia klienta usługi Web Service w przypadku wbudowywania zewnętrznie wygenerowanego modułu w tworzoną aplikację. Korzystanie ze starszych środowisk lub języków programowania, w celu stworzenia klienta Web Service wymaga od programisty w pełni manualnego oprogramowania zarówno procesu wywoływania zdalnych funkcji, jak i opierającej się na wymianie wiadomości (komunikatów) komunikacji z serwerem (patrz rozdział 3.2.2); lub adaptacji modułu udostępnianego (jeśli jest to biblioteka), lub wygenerowanego (jeśli jest to pieniek aplikacji stworzony za pomocą kreatora) w innym środowisku. Rozwiązanie półautomatyczne wydaje się być równie, jeśli nie bardziej, skomplikowane niż w pełni manualne. Programista musi zbudować warstwę pośredniczącą pomiędzy dwoma autonomicznymi aplikacjami, lub wbudować wygenerowany moduł w tworzony przez siebie kod klienta Web Service. Problem może również zostać rozwiązany przez stworzenie z dostępnego, wygenerowanego w innym środowisku modułu, dynamicznie dołączanej biblioteki (ddl), która mogłaby stanowić warstwę pośredniczącą pomiędzy serwerem Web Service a aplikacją klienta. 38 4 Podsumowanie Wydaje się, iż zaistnienie technologii Web Service, diametralnie zmieniło podejście do projektowania i implementacji szeroko pojętych aplikacji internetowych. Niezależność, zarówno od platformy systemowej jak i wykorzystywanej technologii (usługa znajdująca się na serwerze może być napisana w innym języku programowania niż klient!), stanowi największą zaletę Web Service, a niniejsze opracowanie pokazuje, iż nie jest ona obietnicą bez pokrycia. Ze względu na wykorzystywanie istniejących już od pewnego czasu rozwiązań informatycznych (SOAP, UDDI, WSDL), technologia usług sieciowych jest bardzo dobrze opisana swoim standardzie i praktycznie wolna od niedoskonałości nowowprowadzanych technologii. Sporym ułatwieniem dla programisty jest również powszechne wsparcie ze strony producentów środowisk do tworzenia oprogramowania. Wygenerowanie szkieletu aplikacji, modułów odpowiedzialnych za komunikację z usługą sieciową, czy odnalezienie żądanego dokumentu WSDL są dzięki przygotowanym kreatorom procedurami w pełni zautomatyzowanymi. Jeżeli środowisko nie umożliwia skorzystania z kreatora (na przykład w językach C/C++ czy php), programista, wraz z dodatkowymi bibliotekami, otrzymuje zestaw funkcji i komend konsolowych umożliwiających komfortową pracę. Procedura tworzenia klienta usługi sieciowej jest zdecydowanie mniej wygodna, gdy programista nie może skorzystać z gotowych bibliotek i całość kodu napisać samodzielnie (szczególnie uciążliwa jest implementacja komunikacji sieciowej). Przykładem jest język Pascal (autorom nie udało się dotrzeć do żadnej, zarówno płatnej jak i bezpłatnej, biblioteki umożliwiającej zautomatyzowanie procesu tworzenia klienta Web Service) – w takim przypadku zaleca się migrację do innego, najlepiej podobnego, środowiska (np. z Pascala do Delphi). Samodzielne oprogramowanie komunikacji z usługą sieciową jest jednak, co należy podkreślić, jak najbardziej możliwe. Nieocenioną pomocą będzie na pewno dokumentacja techniczna udostępniona chociażby w zasobach internetowych organizacji W3C. 39 5 Literatura: 1. Wykład „Aplikacje Internetowe i Rozproszone” – Politechnika Poznańska, dr hab. inż. Maciej Zakrzewicz, 2. Wykład „Zaawansowane Aplikacje Internetowe” – Uczelnia Online, dr hab. inż. Maciej Zakrzewicz, 3. www.ftponline.com, 4. www.codeguru.pl, 5. www.wikipedia.org, 6. http://www.westwind.com/presentations/dotnetwebservices/DotNetWebServices.asp, 7. http://www.asp.net/webmatrix/guidedtour/section5/createwsclient.aspx, 8. http://www.microsoft.com/poland/developer/net/podstawy/jezyki.mspx#EEH, 9. http://www.devarticles.com/c/a/Delphi-Kylix/Creating-a-Web-Service-Clientwith-Delphi/, 10. http://delphi.about.com/gi/dynamic/offsite.htm?zi=1/XJ/Ya&sdn=delphi&cdn=co mpute&tm=34&f=00&tt=14&bt=1&bts=1&zu=http%3A//bdn.borland.com/borco n2004/article/paper/0%2C1963%2C32219%2C00.html, 11. http://www.e-informatyka.pl/article/show/420, 12. http://www.oracle.com/technology/products/forms/htdocs/Forms_WebService_H ow_To.htm, 13. http://www-128.ibm.com/developerworks/lotus/library/domino-webservices/, 14. Pakiet pomocy środowiska Lotus Designer, 15. Preview of C++ Builder 6 by John Kaster, 16. http://www.onlamp.com/pub/a/php/2003/07/03/php_amazon_soap.html, 17. http://www.cs.fsu.edu/~engelen/soap.html. 18. https://libre.adacore.com/aws/ 40