java.rmi.RemoteException
Transkrypt
java.rmi.RemoteException
Plan wykładu 1. Interfejsy w Javie. 2. Zdalne wywołanie metod (Remote Method Invocation). ● architektura RMI, ● przykładowa aplikacja korzystająca z RMI, przekazywanie parametrów, ● dystrybucja programu rozproszonego. 3. XML (eXtensive Markup Language). ● wprowadzenie, zastosowania, przykłady, ● specyfikacje DTD (Document Type Definition). 4. SOAP (Simple Object Access Protocol) ● struktura wiadomości, ● zdalne wywołanie metody z wykorzystaniem SOAP, ● przykłady. 1 Plan wykładu 1. XML (eXtensive Markup Language). ● wprowadzenie, ● zastosowania, ● przykłady, ● specyfikacje DTD (Document Type Definition). 2. SOAP (Simple Object Access Protocol) ● struktura wiadomości, ● zdalne wywołanie metody z wykorzystaniem SOAP, ● przykłady. 2 Interfejsy w Javie Interfejs (Interface) jest zbiorem metod, które mogą być implementowane przez dowolną klasę. Interfejs deklaruje metody natomiast nie zawiera ich implementacji. Klasa implementująca interfejs musi zawierać implementację każdej z metod wchodzących w skład interfejsu. Podstawowe różnice pomiędzy interfejsem i klasą abstrakcyjną w Javie: ● interfejs nie może implementować żadnej z metod, klasa abstrakcyjna może zawierać implementację. ● dowolna klasa może posiadać maksymalnie jedną nadklasę oraz implementować dowolnie wiele interfejsów. ● interfejsy nie są związane hierarchią klas – dowolny zbiór klas może implementować ten sam interfejs. 3 Interfejsy w Javie Przykład zastosowania interfejsów: public class Product{ protected String name; protected float price; protected int stackSize; } public void setName(String s){ this.name = s; } public String getName(void){ return this.name; } ... Obiekty będące instancjami klasy Product mogą zawierać informacje o dowolnych rodzajach produktów. W niektórych sytuacjach korzystne może być operowanie na posortowanych zbiorach takich obiektów. 4 Interfejsy w Javie Do rozwiązania zadania można użyć interfejsów np: public interface Comparable{ public int compareTo(Object o); } Interfejs Comparable zawiera jedną metodę, której argumentem jest dowolny obiekt. Metoda zwraca liczbę całkowitą. Umawiamy się, że: x < y jeśli x.compareTo(y) < 0, x = y jeśli x.compareTo(y) = 0, x > y jeśli x.compareTo(y) > 0, 5 Interfejsy w Javie W kolejnym kroku piszemy ogólną metodę sortującą: public class Sorter{ public static sort(Comparable[] cArray){ int i, j; Object tmp; for(i=0; i<cArray.length(); i++){ for(j=1; j<cArray.length()-i; j++){ if (cArray[j-1].compareTo(cArray[j])>0) tmp = cArray[i]; cArray[i] = cArray[j]; cArray[j] = tmp; } //for } //for }// sort }// class 6 Interfejsy w Javie Aby wykorzystać Sorter dla produktów wprowadzamy nową klasę: public class PriceSortedProduct extends Product implements Comparable{ ... int compareTo(Object obj){ Product p = (Product)obj; if (this.price < p.price) return -1; else if (this.price > p.price) return 1; else return 0; } ... } Klasa implementująca interfejs Comparable musi zawierać kod dla metody int compareTo(Object). W programie wykorzystującym sortowanie produktów powinny znaleźć się linie: PriceSortedProduct[] pArray; ... Sorter.sort(pArray); ... 7 Interfejsy w RMI Program klienta Program serwera interfejs implementacja Architektura RMI opiera się na zasadzie rozdziału kodu zawierającego definicję (specyfikację) oraz implementację określonej funkcjonalności. Definicja jest zapisana pod postacią interfejsu. Implementacja jest wyrażona w ramach klasy. Interfejsy w Javie nie zawierają kodu wykonywalnego. 8 Interfejsy w RMI Usługa interfejs Program klienta Usługa pośrednik Program serwera komunikacja RMI Usługa implementacja RMI wykorzystuje dwie klasy implementujące wspólny interfejs. Pierwsza z nich zawiera właściwy kod wykonywalny i jest umieszczona na serwerze. Druga z klas jest pośrednikiem pomiędzy klientem i zdalną usługą na serwerze i działa w ramach programu klienta. 9 Architektura RMI Usługa RMI jest zbudowana z trzech abstrakcyjnych warstw. Program klienta Program serwera Stubs & Skeletons Stubs & Skeletons Warstwa referencyjna Warstwa referencyjna Warstwa transportowa Pierwsza warstwa (Stubs & Skeletons) przechwytuje wywołania metod by przekazać je do warstwy referencyjnej, która jest odpowiedzialna za zrealizowanie połączenia z odpowiednim serwerem, poprzez które nastąpi realizacja usługi RMI. Warstwa transportowa służy do przesłania danych.10 Architektura RMI Warstwa Stub & Skeleton jest przykładem zastosowania tzw. wzorca projektowego Proxy. W tym wzorcu obiekt w jednym kontekście jest reprezentowany przez inny obiekt – proxy – w innym kontekście. Proxy wie jak przekazywać wywołania metod pomiędzy współdziałającymi obiektami. Intefejs Obiekt +request() PierwotnyObiekt +request() pierwotnyObiekt Proxy +request() 11 Architektura RMI W RMI klasa Stub pełni rolę Proxy. Implementacja klasy po stronie serwera jest odpowiednikiem ObiektPierwotny. Skeleton jest klasą pomocniczą dla protokołu RMI. Jest ona bezpośrednio odpowiedzialna za przesyłanie i odbieranie komunikatów poprzez połączenie RMI. Skeleton współpracuje ze Stub'em; odczytuje parametry wywołania, kontaktuje się ze zdalnym obiektem aby wywołać odpowiednią metodę, odbiera zwracaną wartość i przekazuje ją do Stub'a. Począwszy od wersji 1.2 SDK klasy Skeleton są zbędne, ponieważ RMI używa innego mechanizmu realizującego ich dotychczasowe funkcje. Są one niezbędne jeżeli program ma być kompatybilny z wcześniejszymi wersjami Javy (do 1.1). 12 Architektura RMI Warstwa referencyjna (Remote Reference Layer) definiuje i wspiera semantykę używaną przez połączenie RMI. Dostarcza obiekt RemoteRef, który reprezentuje implementację wywoływanego, zdalnego obiektu. Aby wywołać zdalną metodę Obiekt Stub używa w obiekcie RemoteRef metody invoke(). Pierwotnie (do wersji 1.1) zdalny obiekt musiał istnieć i być zarejestrowany w rejestrze RMI zanim klient mógł się z nim połączyć. Klient mógł się łączyć tylko z jednym zdalnym obiektem w jednej chwili. Obecnie (od wersji 1.2) obiekty mogą znajdować się w stanie uśpienia. Istnieje możliwość innych sposobów połączeń RMI (np. Jeden klient kontaktuje się jednocześnie z wieloma serwerami i akceptuje jedynie pierwszy z odebranych wyników). 13 Architektura RMI Warstwa transportowa udostępnia połączenie pomiędzy wirtualnymi maszynami Javy (JVM). Połączenia RMI korzystają z transmisji strumieniowej TCP/IP. JRE JRE system operacyjny Warstwa sieciowa (TCP/IP) JRE JRE system operacyjny Warstwa sieciowa (TCP/IP) 14 Architektura RMI Do komunikacji RMI wykorzystuje przeważnie dwa rodzaje protokołów. Pierwszy z nich to JRMP (Java Remote Method Protocol) – do wersji 1.2. Począwszy od wersji 1.3 używa się IIOP (Internet Inter-ORB Protocol). Warstwa transportowa RMI ma zapewniać odpowiednią obsługę połączeń. Przykładowo, jeśli aplikacja chce korzystać z kilku równoczesnych połączeń natomiast konfiguracja sieci dopuszcza tylko jedno połączenie, warstwa transportowa RMI udostępnia kilka wirtualnych połączeń w ramach jednego połączenia TCP/IP. 15 Architektura RMI Wyszukiwanie zdalnych obiektów może odbywać się za pośrednictwem różnych usług. Najpopularniejsze to JNDI (Java Naming and Directory Interface) oraz RMI Registry. Udostępnienie przez serwer usługi RMI za pomocą RMI Registry przebiega w kilku krokach: ● stworzenie lokalnego obiektu implementującego usługę, ● wyeksportowanie obiektu do systemu RMI, ● utworzenie usługi oczekującej na zgłoszenia klientów, ● zarejestrowanie nazwy usługi w RMI Registry. 16 Architektura RMI Do zarejestrowania usługi można użyć klasy java.rmi.Naming. Klasa ta zawiera metodę bind(): public static void bind(String name, Remote obj) throws AlreadyBoundException, MalformedURLException, RemoteException name – ciąg w formacie: rmi://nazwa_serwera[:numer_portu]/nazwa_usługi nazwa_serwera – adres IP lub nazwa zarejestrowana w serwerach DNS, numer_portu – domyślnie 1099 – standardowy port dla RMI Registry, nazwa_usługi – nazwa pod jaką zarejestrowano usługę. obj – rejestrowany obiekt. W przypadku błędu zwracany jest jeden z wyjątków: java.rmi.AlreadyBoundException – wykorzystywana nazwa, java.rmi.RemoteException – nie można się skontaktować z serwerem, java.net.MalformedURLException – niewłaściwy adres URL. java.rmi.AccessException – operacja niedozwolona, 17 Architektura RMI Klient do wyszukania usługi poprzez RMI Registry używa klasy java.rmi.Naming i metody lookup(): public static Remote lookup(String name) throws NotBoundException, MalformedURLException, RemoteException name – URL w formacie analogicznym jak w metodzie bind(): rmi://nazwa_serwera[:numer_portu]/nazwa_usługi Metoda zwraca referencję do obiektu java.rmi.Remote. W przypadku błędu zwracany jest jeden z wyjątków: java.rmi.NotBoundException – nieznana nazwa, java.rmi.RemoteException – nie można się skontaktować z serwerem, java.rmi.AccessException – operacja niedozwolona, java.net.MalformedURLException – niewłaściwy adres URL. 18 Aplikacja korzystająca z RMI W celu stworzenia aplikacji korzystającej z RMI należy: 1. Napisać i skompilować kod opisujący interfejsy. 2. Napisać i skompilować kod klas implementujących zaprojektowane interfejsy. 3. Wygenerować za pomocą narzędzia rmic pliki klas Stub i Skeleton dla klas implementujących. 4. Napisać kod programu realizującego usługę. 5. Napisać kod klienta RMI. 6. Zainstalować i uruchomić system RMI (RMI Registry). 19 Krok 1: Interfejsy Program umożliwia przeprowadzenie podstawowych działań na liczbach całkowitych. Operacje te będą wykonywane z wykorzystaniem RMI - klient wysyła argumenty działania do serwera i odbiera wynik. Plik Calculator.java public interface Calculator public long add(long a, public long sub(long a, public long mul(long a, public long div(long a, } extends long b) long b) long b) long b) java.rmi.Remote { throws java.rmi.RemoteException; throws java.rmi.RemoteException; throws java.rmi.RemoteException; throws java.rmi.RemoteException; Interfejs musi rozszerzać java.rmi.Remote. Ponieważ każda zdalna metoda może potencjalnie zwrócić wyjątek java.rmi.RemoteException, więc musi on być zadeklarowany. Kompilacja: javac Calculator.java 20 Krok 2: Implementacja Plik CalculatorImpl.java public class CalculatorImpl extends java.rmi.server.UnicastRemoteObject implements Calculator { } // Implementacja musi zawierać konstruktor ponieważ utworzenie obiektu // może zwrócić wyjątek java.rmi.RemoteException public CalculatorImpl() throws java.rmi.RemoteException { super(); } public long add(long a, long b) throws java.rmi.RemoteException { return a + b; } public long sub(long a, long b) throws java.rmi.RemoteException { return a - b; } public long mul(long a, long b) throws java.rmi.RemoteException { return a * b; } public long div(long a, long b) throws java.rmi.RemoteException { return a / b; } 21 Krok 2: Implementacja Klasa CalculatorImpl używa java.rmi.server.UnicastRemoteObject, który definiuje niereplikowalny zdalny obiekt, którego referencje są ważne jedynie w trakcie działania usługi. Klasa UnicastRemoteObject umożliwia połączenia typu punt–punkt z wykorzystaniem transmisji strumieniowej poprzez TCP. Rozszerzenie klasy UnicastRemoteObject nie jest obowiązkowe. Zdalne obiekty powinny jedynie rozszerzać java.rmi.server.RemoteObject. Wtedy dodatkową częśc kodu realizowaną przez UnicastRemoteObject należy zaimplementować własnoręcznie. Kompilacja: javac CalculatorImpl.java 22 Krok 3: Stub i Skeleton Używając klasy CalculatorImpl należy wygenerować automatycznie klasy Stub i Skeleton. W tym celu korzysta się z polecenia: rmic [opcje] klasa np. rmic CalculatorImpl W wyniku jego działania w bieżącym katalogu pojawią się dwa nowe pliki: Calculator_Stub.class Calculator_Skel.class (od wersji 1.2) 23 Krok 4: Kod serwera Program serwera tworzy zdalny obiekt i rejestruje go w systemie RMI. Plik CalculatorServer.java import java.rmi.Naming; public class CalculatorServer { public CalculatorServer() { try { Calculator c = new CalculatorImpl(); Naming.rebind("rmi://localhost:1099/CalculatorService", c); } catch (Exception e) { System.out.println("Problem: " + e); } } } public static void main(String args[]) { new CalculatorServer(); } 24 Krok 5: Kod klienta Przykładowy program kliencki mógłby wyglądać następująco. Plik CalculatorClient.java import import import import java.rmi.Naming; java.rmi.RemoteException; java.net.MalformedURLException; java.rmi.NotBoundException; public class CalculatorClient { public static void main(String[] args) { try { Calculator c = (Calculator)Naming.lookup ("rmi://remotehost/CalculatorService"); System.out.println( c.sub(4, 3) ); System.out.println( c.add(4, 5) ); System.out.println( c.mul(3, 6) ) System.out.println( c.div(9, 3) ); }catch (Exception e) { System.out.println("Problem:" + e); } } } 25 Krok 6: Uruchomienie Kompilacja klienta i serwera: javac CalculatorClient.java javac CalculatorServer.java Uruchomienie: rmiregistry java CalculatorServer java CalculatorClient Pomimo, że program jest uruchomiony na jednym komputerze, to do komunikacji między trzema Wirtualnymi Maszynami Javy wykorzystywany jest protokół TCP/IP. 26 Przekazywanie parametrów Przekazywanie parametrów wywołania metod jak również wyników przez nie zwracanych odbywa się w sposób niezależny od platformy i architektury komunikujących się komputerów. Sposób przekazywania parametrów zależy od ich typu. Istnieją trzy rodzaje parametrów używanych w aplikacjach rozproszonych RMI . 1. Proste typy danych (int, float, ...) – przekazywane przez wartość. 2. Obiekty – przekazywane przez wartość, przed przesłaniem wykonywana jest serializacja, po odebraniu deserializacja. 3. Zdalne obiekty ● w wyniku Naming.lookup() – przez referencję. 27 Przekazywanie parametrów ● w wyniku działania zdalnej metody – przykład: // program klienta // BankManager bm; Account a; try { bm = (BankManager)Naming.lookup("rmi://BankServer/BankManagerService"); a = bm.getAccount( "Jan Kowalski" ); ... // kod używający obiektu Account } catch (RemoteException re) { } Metoda getAccount() działa po stronie serwera i zwraca lokalną referencję. public Account getAccount(String accountName) { ... // wyszukanie odpowiedniego obiektu AccountImpl ai = ... // utworzenie nowej referencji do tego obiektu return ai; // zwrócenie referencji } ai jest lokalną referencją do zdalnego obiektu. 28 Przekazywanie parametrów Gdy metoda zwraca lokalną referencję do zdalnego obiektu RMI nie zwraca tego obiektu. Zamiast niego do zwracanego strumienia danych jest wstawiany inny obiekt (jego obiekt proxy). Kiedy taki obiekt jest przesyłany między serwerem i klientem dwie Wirtualne Maszyny Javy używają swoich własnych kopii plików definiujących klasę tego obiektu. W związku z tym zmienne statyczne są aktualizowane niezależnie po stronie klienta i serwera – nie są przekazywane przez RMI. 29 Dystrybucja programów wykorzystujących RMI Pliki dostępne dla serwera: definicje zdalnych interfejsów (Calculator.class), ● implementacje zdalnych interfejsów (CalculatorImpl.class), ● klasy Skeletons dla klas implementujących (Calculator_Skel.class) do wersji 1.1, ● klasy Stub dla klas implementujących (Calculator_Stub.class), ● klasy programu serwera (CalculatorServer.class) ● Pliki dostępne dla klienta definicje zdalnych interfejsów (Calculator.class), ● klasy Stub dla klas implementujących (Calculator_Stub.class), ● klasy obiektów zwracanych klientowi przez serwer , klasy programu klienta (CalculatorClient.class), ● 30 Dystrybucja programów wykorzystujących RMI Istnieje kilka podstawowych sposobów dystrybucji aplikacji rozproszonej: 1. Closed – wszystkie potrzebne pliki dla klienta i serwera są dostępne lokalnie. 2. Server based – program klienta wraz z potrzebnymi klasami jest w całości ładowany z serwera (applet) 3. Client dynamic – program klienta ładuje odpowiednie klasy z lokalizacji wskazanej przez serwer. 4. Server dynamic – program serwera ładuje odpowiednie klasy z lokalizacji wskazanej przez klienta. 5. Bootstrap client – cały kod klienta jest ładowany z sieci. 6. Bootstrap server – cały kod serwera jest ładowany z sieci. 31 Podsumowanie Protokół NFS umożliwia zdalny dostęp do plików. Za jego pomocą wielu użytkowników może jednocześnie korzystać ze wspólnych zasobów plikowych. Pomimo, że koncepcja plików w NFS'ie bazuje na rozwiązaniach znanych z systemów UNIX może on być używany także w ramach innych systemów. Specyfikacja NFS opiera się na modelu RPC i wykorzystuje XDR. Wywoływanie zdalnych metod w Javie jest technologią analogiczną do RPC w języku C. Odpowiednikiem zdalnego programu w RPC jest zarejestrowany, zdalny obiekt. Jego metody odpowiadają zdalnym procedurom w RPC. RMI jest podstawą dla innych technologii (np. Enterprise Java Beans)wykorzystywanych do tworzenia współczesnych rozwiązań biznesowych opartych na języku Java. 32 XML - wprowadzenie XML (eXtensive Markup Language) jest tekstowym językiem znaczników. Współcześnie jest on używany do wymiany danych między programami działającymi w środowisku sieciowym. Podobnie jak HTML do opisu danych używa tagów (identyfikatorów otoczonych nawiasami „<” i „>”, np. „<tag>”). W przeciwieństwie do HTML'a tagi służą raczej do identyfikacji danych a nie do określenia sposobu ich prezentacji. <message> <to>[email protected]</to> <from>[email protected]</from> <subject>coś o XML'u</subject> <text> Ciekawe to czego to jest potrzebne. </text> </message> 33 XML – puste tagi Najważniejsza różnica pomiędzy XML i HTML polega na przestrzeganiu hierarchicznego formatu dokumentu w pierwszym przypadku: ● dla każdego tagu musi istnieć tag zamykający: (<text>...</text>), ● tag <text> może być zamknięty tylko przez </text>, ● tagi nie zawierające treści można zapisywać w postaci <text/>. <message> <text> Dobrze </text> </message> <message> <text/> </message> <!-- Dobrze (komentarz) --> <message> <text> Źle </message> </text> <message> <text> Źle </message> 34 XML – tagi i atrybuty Tagi mogą posiadać atrybuty – dodatkową informację zawartą wewnątrz tagu: <message to=”[email protected]” from=”[email protected]” subject=”coś o XML'u”> <text> Ciekawe do czego to jest potrzebne. </text> </message> Używanie atrybutów i tagów wewnętrznych jest niemal równoważne tzn. wiadomości (messages) opisywane przez dwa przedstawione dokumenty XML są takie same. Wybór sposobu opisu uzależniony jest od upodobania i konkretnej sytuacji. 35 XML – nagłówek Każdy dokument XML rozpoczyna się (opcjonalnym) nagłówkiem. W najprostszej wersji wygląda on następująco: <?xml version=”1.0”?> Często jednak zawiera on dodatkowe informacje, np. <?xml version=”1.0” encoding=”ISO-8859-1” standalone=”yes”?> ● version – określa wersję XML wykorzystywaną do opisu danych, ● encoding – kodowanie znaków wewnątrz dokumentu. Domyślnie UTF-8 (tzw. compressed unicode). ● standalone – określa, czy dokument jest zależny od jakiś zewnętrznych dokumentów. 36 Zastosowania XML Jest wiele powodów dla których warto używać XML'a. Niektóre z nich: ● format tekstowy – można wykorzystać dowolny edytor tekstowy do obsługi dokumentu XML, ● identyfikacja (opis) danych – główny nacisk na strukturę danych a nie na sposób ich prezentacji, ● prosta konwersja do formatów korzystających ze styli – możliwość łatwego zdefiniowania przekształceń dokument XML w formaty określające sposób prezentacji dokumentu (HTML, PDF, TeX, RTF), ● modularność – poszczególne moduły mogą być używane wielokrotnie ● odwołania do innych dokumentów, ● hierarchiczna struktura – pozwala zwykle na szybsze przeszukiwanie dokumentu. 37 Zastosowania XML Podstawowe zastosowania XML'a. ● tradycyjne przetwarzanie danych – dane zapisane w formacie XML są przetwarzane przez odpowiedni program, ● programowanie opisane dokumentami (document-driven programming) – sposób działania programu jest opisany w dokumencie XML, który opisuje używane obiekty, logikę biznesową, interfejs użytkownika. Na podstawie tych informacji aplikacja jest tworzona „w locie”, ● archiwizacja – fundament dla document-driven programming. Odpowiednio skonfigurowane komponenty mogą zostać zapisane do późniejszego wykorzystania, ● powiązywanie (binding) – dokument opisujący strukturę XML'a (DTD) może być wykorzystany do budowy szkieletu aplikacji przetwarzającej dane. 38 XML - przykład <?xml version='1.0' encoding='utf-8'?> <!-- A SAMPLE set of slides --> <slideshow title="Przykładowy pokaz slajdów" date="24.01.2005" author="Anonim" > <!-- TITLE SLIDE --> <slide type="all"> <title>Obudź się!</title> </slide> <!-- OVERVIEW --> <slide type="tech"> <title>Przegląd</title> <item>Dlaczego <em>XML</em> jest wspaniały</item> <item/> <item>Technologia <em>SOAP</em> z załącznikami</item> </slide> </slideshow> 39 XML - DTD Aby poprawnie zinterpretować dane zapisane w XML'u korzysta się ze specyfikacji zapisanej w plikau DTD (Document Type Definition). Dzięki temu program analizujący dokument XML (parser) potrafi sprawdzić formalną poprawność pliku oraz utworzyć odpowiednie obiekty. I tak: <!ELEMENT slideshow (slide+)> mówi, że element slideshow zawiera z co najmniej jedną strukturę slide. Kwalifikatory: ● ? – zero lub jedną, ● * – zero lub więcej, ● + – jedną lub więcej. 40 XML - DTD <!ATTLIST slideshow title date author > CDATA CDATA CDATA #REQUIRED #IMPLIED "unknown" określa trzy atrybuty pojawiające się w tagu slideshow. Każdy z nich jest typu CDATA – (nieparsowalne) pole tekstowe. Podanie title jest wymagane w przeciwieństwie do date i author. Jeśli date nie zostanie podana wartość tego atrybutu jest określona przez aplikację przetwarzającą dane. W przypadku braku określenia pola author zostanie mu przypisana domyślna wartość „unknown”. Inny często używany typ to #PCDATA – parsowalne pole tekstowe. 41 XML - DTD <!ELEMENT slide (title, item*)> <!ATTLIST slide type (tech | exec | all) #IMPLIED Struktura slide składa się z title oraz dowolnej liczby obiektów item. Każdy slide może posiadać atrybut type przybierający jedną z trzech wartości: tech, exec, all. Warto zwrócić uwagę, że dokument ani dokument XML ani odpowiadający mu DTD nie zawiera interpretacji odpowiadającej tym trzem stałym wartościom. 42 XML - DTD Przykładowy plik DTD dla pokazanego wcześniej dokumentu mógłby wyglądać następująco: <?xml version='1.0' encoding='us-ascii'?> <!-- DTD dla przykładowego pokazu slajdów --> <!ELEMENT slideshow (slide+)> <!ATTLIST slideshow title CDATA #REQUIRED date CDATA #IMPLIED author CDATA "unknown" > <!ELEMENT slide (title, item*)> <!ATTLIST slide type (tech | exec | all) #IMPLIED > <!ELEMENT title (#PCDATA)> <!ELEMENT item (#PCDATA | item)* > 43 SOAP SOAP (Simple Object Access Protocol) jest ogólnym protokołem do przesyłania wiadomości (messages). Jest też standardem wykorzystywanym obecnie do komunikacji z usługami sieciowymi (web services). Wiadomość to dokument w formacie XML, który może być przesyłany za pośrednictwem dowolnego, popularnego protokołu z warstwy zastosowań (najczęściej HTTP lub HTTPS). SOAP jest wykorzystywany w ramach architektury orientowanej na usługi, umożliwiając przekształcenie aplikacji rozproszonej na usługi SOAP, które mogą być zdalnie wywołane za pomocą dowolnego urządzenia. 44 Schemat działania komunikatów SOAP System żądający usługi Wiadomość SOAP (dokument XML) 1 Aplikacja kliencka 5 2 System udostępniający usługi Serwer HTTP Strona JSP, ASP, PHP,CGI 3 Serwer SOAP 4b Obiekt COM, CORBA, ... 4a Zdalne wywołanie procedury 45 Wiadomość SOAP Podstawową jednostką komunikacji pomiędzy klientem SOAP a serwisem udostępniającym usługi jest wiadomość SOAP. Wiadomość SOAP część główna MIME (text/xml) Koperta SOAP Nagłówek SOAP pozycja pozycja załącznik załącznik ... załącznik Treść SOAP pozycja pozycja 46 Wiadomość SOAP Przykładowa postać wiadomości SOAP: <?xml version="1.0" encoding="UTF-8" ?> <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:xsd="http://www.w3.org/1999/XMLSchema"> <SOAP-ENV:Body> <ns1:doGoogleSearch xmlns:ns1="urn:GoogleSearch" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <key xsi:type="xsd:string">00000000000000000000000000000000</key> <q xsi:type="xsd:string">Learning Wireless Java</q> <start xsi:type="xsd:int">0</start> <maxResults xsi:type="xsd:int">10</maxResults> <filter xsi:type="xsd:boolean">true</filter> <restrict xsi:type="xsd:string" /> <safeSearch xsi:type="xsd:boolean">false</safeSearch> <lr xsi:type="xsd:string" /> <ie xsi:type="xsd:string">latin1</ie> <oe xsi:type="xsd:string">latin1</oe> </ns1:doGoogleSearch> </SOAP-ENV:Body> </SOAP-ENV:Envelope> 47 Klient SOAP import import import import java.net.*; javax.xml.soap.*; javax.xml.transform.*; javax.xml.transform.stream.*; public class SoapClient { public static void main(String args[]) { try { // Utwórz połączenie SOAPConnectionFactory scf = SOAPConnectionFactory.newInstance(); SOAPConnection connection = scf.createConnection(); SOAPFactory sf = SOAPFactory.newInstance(); // Stwórz wiadomość MessageFactory mf = MessageFactory.newInstance(); SOAPMessage message = mf.createMessage(); // Stwórz części wiadomości SOAPPart soapPart = message.getSOAPPart(); SOAPEnvelope envelope = soapPart.getEnvelope(); SOAPBody body = envelope.getBody(); 48 Klient SOAP // Wstaw treść wiadomości StreamSource msg = new StreamSource(new FileInputStream ("c:/request.xml")); soapPart.setContent(msg); /* alternatywnie Name bodyName = sf.createName("getPrice", "ns1", "urn:xmethods-BNPriceCheck"); SOAPBodyElement bodyElement = body.addBodyElement(bodyName); Name name = sf.createName("key"); SOAPElement key = bodyElement.addChildElement(name); key.addTextNode("00000000000000000000000000000000"); */ // Wyświetl wysyłaną kopertę System.out.println("SOAP Request Sent:"); message.writeTo(System.out); // Ustaw punkt docelowy URL endpoint = new URL ("http://api.google.com/search/beta2"); // Wyślij wiadomość SOAPMessage response = connection.call(message, endpoint); // Zamknij połączenie connection.close(); 49 Klient SOAP // Wyświetl odpowiedź System.out.println("SOAP Response Received:"); // Utwórz transformer TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); // Odbierz obpowiedź Source content = response.getSOAPPart().getContent(); // Wyświetl odpowiedź w konsoli StreamResult result = new StreamResult(System.out); transformer.transform(content, result); System.out.println(); } } } catch(Exception e) { System.out.println(e.getMessage()); } 50 Załączniki SOAP Załączniki w wiadomości SOAP są umieszczane w sposób identyczny jak w wiadomościach email. ... </SOAP-ENV:Envelope> --MIME_boundary Content-Type: image/tiff Content-Transfer-Encoding: base64 Content-ID: <[email protected]> ...Base64 encoded TIFF image... --MIME_boundary Content-Type: image/jpeg Content-Transfer-Encoding: binary Content-ID: <[email protected]> ...Raw JPEG image.. --MIME_boundary-- 51 Załączniki SOAP Dostęp do załączników w odebranej wiadomości można uzyskać posługując się instancją klasy AttachmentPart: ... java.util.Iterator iterator = message.getAttachments(); while (iterator.hasNext()) { AttachmentPart attachment = (AttachmentPart)iterator.next(); String id = attachment.getContentId(); String type = attachment.getContentType(); System.out.print("Attachment " + id + " has content type " + type); if (type == "text/plain") { Object content = attachment.getContent(); System.out.println("Attachment " + "contains:\n" + content); } } ... 52 Dodatkowe możliwości Funkcjonalność SOAP zawiera dodatkowo kilka nieomawianych tu elementów. Najważniejsze z nich to: 1. Atrybuty w nagłówku – określają sposób przetwarzania wiadomości przez odbiorcę. Umożliwiają one m. in.: identyfikację klienta, zarządzanie tranzakcjami, itp. 2. Obsługa błędów – w przypadku błędu klient otrzymuje kopertę SOAP zawierającą: kod błędu, opis błędu, nazwę usługi, która zwróciła błąd, szczegóły błędu. 53 Podsumowanie SOAP umożliwia jednorodny mechanizm dostępu do zdalnych usług. Jego działanie opiera się na wiadomościach zapisanych w formacie XML, które są wymieniane między klientem a serwerem za pomocą jakiegokolwiek protokołu warstwy zastosowań. Dzięki temu aplikacja kliencka może być napisana w dowolnym języku programowania, który umożliwia nawiązanie połączenia z serwerem SOAP. Istnieje możliwość zbudowania serwera SOAP, który umożliwi dostęp do zdalnych obiektów wykorzystujących dowolną z wcześniej omówionych technologii (RMI, CORBA, COM, RPC). 54