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

Podobne dokumenty