48
Inżynieria
oprogramowania
www.sdjournal.org
Software Developer’s Journal 3/2006
XFire w akcji
W
ebserwisy okazały się długo oczekiwaną
odpowiedzią na potrzebę komunikacji po-
między rozproszonymi systemami tworzo-
nymi na różnych platformach i przy użyciu różnorod-
nych języków programowania. Dzięki użyciu powszech-
nie akceptowanych standardów bazujących na języku
XML (SOAP, WSDL,UDDI), możliwa stała się wymia-
na informacji oraz usług nie tylko pomiędzy aplikacja-
mi działającymi na platformach J2EE i Microsoft .NET,
ale także napisanymi praktycznie w dowolnym języku
jak C++, Pascal, Cobol ,a nawet językami skryptowymi
jak Perl, Python czy PHP.
Nie bez znaczenia także dla tak szybkiego rozwo-
ju tej technologii jest fakt, iż webserwisy są luźno po-
wiązane z aplikacją, której logikę udostępniają, tzn. ich
obecność praktycznie nie wpływa na istniejące kom-
ponenty, umożliwiając stopniowe, fragment po frag-
mencie, integrowanie ich z istniejącą funkcjonalnością.
Dzięki takiemu podejściu udostępnienie istniejącej logi-
ki za pomocą webserwisów możliwe jest bez ponosze-
nia dużych nakładów na modyfikacje aplikacji oraz ze
zminimalizowanym ryzykiem niepowodzenia.
Dzięki tym cechom webserwisy umożliwiają zinte-
growanie praktycznie dowolnych aplikacji, w jeden du-
ży rozproszony system, eliminując często konieczność
wprowadzania niezwykle kosztownych w utrzymaniu
systemów pośrednich, dopasowujących metody komu-
nikacji poszczególnych aplikacji. Duże korporacje zwią-
zane z internetem dość szybko dostrzegły możliwości
płynące z wykorzystania webserwisów i rozpoczęły
udostępnianie swoich usług z wykorzystaniem tej tech-
nologii. Do takich firm zaliczają się miedzy innymi: Go-
ogle, Amazon, Ebay,Yahoo oraz Allegro.
O poziomie zainteresowania wykorzystaniem tej
technologii może świadczyć fakt, iż w chwili obecnej
50,000 programistów zarejestrowanych jest w progra-
mie webserwisów firmy Amazon. Firma eBay może po-
chwalić się natomiast 8.000 firm oraz indywidualnych
programistów biorących udział w jej programie oraz
600 aplikacjami wykorzystującymi jej API, generujący-
mi około 40% wszystkich transakcji.
Problemy
z dostępnymi narzędziami
Przeszukując zasoby sieci internet bez trudu moż-
na znaleźć narzędzia ułatwiające tworzenie web-
serwisów, wymieniając chociażby najbardziej po-
pularne:
• JAX-WS oraz JAX-RPC firmy Sun:
http://java.sun.com/webservices/jwsdp/index.jsp,
• Axis 1.x
http://ws.apache.org/axis,
• XFire
http://xfire.codehaus.org,
• WASP:
http://www.systinet.com/products/systinet_server,
• WebLogic Web Services
http://e-docs.bea.com/wls/docs81/webserv/
Jednak wybranie odpowiedniego programu spełnia-
jącego naszego oczekiwania, nie jest sprawą prostą.
Każdy z nich umożliwia wyeksponowanie logiki naszej
aplikacji jako webserwisu, jednak również każdy z nich
posiada pewne wady, które mogą zniechęcić lub nawet
uniemożliwić jego użycie. Na początku należy więc za-
stanowić się jakie cechy powinno posiadać narzędzie
z którym będziemy pracować:
• łatwość użycia – dzięki czemu skróci się czas po-
trzebny na stworzenie aplikacji,
• wysoka wydajność – dzięki czemu będziemy mo-
gli obsłużyć większą ilość użytkowników bez ko-
nieczności dokupowania kolejnych kosztownych
serwerów,
Tomasz Sztelak
Autor od 2002r. tworzy aplikacje oparte na platformie
J2EE dla sektora bankowego. Jest również członkiem
zespołu tworzącego bibliotekę XFire.
Kontakt: tsztelak@gmail.com
Rysunek 1.
Architektura webserwisów
���������
�������
�����������
������
���������
�������
������������
�������
����
���������
����
������
�������
�����������������
������
����������
�������
���������������
�������
Rysunek 2.
Opis serwisu w formacie WSDL
Software Developer’s Journal 3/2006
• spójne API – zapewniające łatwiejsze utrzymanie oraz
większy komfort pracy przy nim,
• niska cena – dzięki której szybciej zwrócą się koszty in-
westycji.
Niestety większość wymienionych narzędzi nie spełniania po-
wyższych wymogów. Małe i średnie firmy na ogół nie mogą po-
zwolić sobie na zakup komercyjnych rozwiązań takich jak bardzo
dobre np. WASP czy Weblogic Server. W wielu wypadkach rów-
nież wydajność tych rozwiązań pozostawia wiele do życzenia,
głownie ze względu na przetwarzanie komunikatów SOAP z wy-
korzystaniem modelu DOM, opierającego się na tworzeniu do-
kumentu będącego reprezentacją przetwarzanego XMLa, z któ-
rego dopiero w następnej kolejności tworzony jest odpowiadają-
cy danym XML obiekt logiki aplikacji. Podejście takie powoduje
poza spadkiem wydajności, również intensywne zużywanie pa-
mięci, gdyż każdy obiekt przechowywany jest w pamięci dwu-
krotnie, a drzewo przechowujące elementy dokumentu czasami
zajmuje kilkakrotnie więcej pamięci niż same dane . Z tym pro-
blemem boryka się między innymi Axis 1.x ( chociaż Axis 2 opie-
rać się będzie już na znacznie wydajniejszym modelu przetwa-
rzania XMLa Stax, umożliwiającym przetwarzanie danych stru-
mieniowo, na zasadzie iteratora) oraz JAX-RPC. Niewiele na-
rzędzi przejmuje się również łatwością użycia, wymagając czę-
Listing 1.
Struktura katalogów aplikacji
xfire
-
WEB-INF/
-
classes/
– klasy serwisu
-
META-INF/
-
xfire/
-
services.xml
– definicja serwisu
.-
lib/
– biblioteki wymagane przez kod
serwisu
web.xml
Listing 2.
Plik web.xml
<
?xml version=
"1.0"
encoding=
"ISO-8859-1"
?
>
<
!DOCTYPE web-app
PUBLIC
"-//Sun Microsystems,
Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"
>
<
web-app
>
<!--Definicja servletu obsługjącego żądania SOAP -->
<
servlet
>
<
servlet-name
>
XFireServlet
<
/servlet-name
>
<
display-name
>
XFire Servlet
<
/display-name
>
<
servlet-class
>
org.codehaus.xfire.transport.http.XFire
ConfigurableServlet
<
/servlet-class
>
<
/servlet
>
<!-- Mapowanie servletu XFire na wszystkie adresy
rozpoczynające się od /services/* -->
<
servlet-mapping
>
<
servlet-name
>
XFireServlet
<
/servlet-name
>
<
url-pattern
>
/services/*
<
/url-pattern
>
<
/servlet-mapping
>
<
/web-app
>
50
Inżynieria
oprogramowania
www.sdjournal.org
Software Developer’s Journal 3/2006
sto skomplikowanej konfiguracji, dodatkowych kroków w trakcie
instalacji lub udostępniając niewygodne API, wydłużając przez
to znacznie czas potrzebny na zrozumienie narzędzia oraz stwo-
rzenie aplikacji.
Dlaczego XFire?
XFire powstał jako odpowiedź na serie problemów, które napo-
tkał autor projektu podczas prób stworzenia webserwisu przy
użyciu dostępnych (m.in. wymienionych wcześniej) narzędzi. Ce-
lem było stworzenie darmowego narzędzia wolnego od wspo-
mnianych wad oraz zapewniającego wydajność komercyjnych
rozwiązań, posiadającego następujące cechy:
• niska cena - XFire jest narzędziem całkowicie darmowym
rozpowszechnianym wraz z kodem źródłowym,
• wysoka wydajność - jednym z podstawowych założeń pro-
jektu była wysoka wydajność rozwiązania, dlatego też archi-
tektura została całkowicie oparta na przetwarzaniu XMLa
przy użyciu bardzo wydajnego modelu StAX, umożliwiają-
cego inkrementalne przetwarzanie komunikatów oraz powo-
dującego minimalne wykorzystanie pamięci. Dodatkowo do
projektu wprowadzony został własny mechanizm mapowa-
nia komunikatów XML na obiekty Javy (zwany Aegis), będą-
cy jednym z najwydajniejszych rozwiązań tego typu obec-
nie dostępnych. Najlepszym zobrazowaniem korzyści pły-
nących z powyższych rozwiązań, są wyniki testów wydajno-
ściowych, które pokazują iż w zależności od rozmiaru komu-
nikatu SOAP silnik XFire jest od 2 do 5 razy szybszy od naj-
popularniejszego obecnie na rynku Axisa 1.x,
• spójne API – XFire posiada bardzo przejrzystą i intuicyj-
na, komponentową architekturę (http://xfire.codehaus.org/
Architecture), dzięki czemu w ciągu bardzo krótkiego czasu
możliwe jest zrozumienie zasad jego funkcjonowania.
• łatwość użycia - jednym z najważniejszych czynników
decydujących o sukcesie produktu jest czas potrzebny do
stworzenia danej aplikacji, dlatego też jednym z najważ-
niejszych celów projektu była jak największa łatwość je-
go użycia. Zostało to osiągnięte poprzez wprowadzenie
prostej i spójnej architektury oraz maksymalne uproszcze-
nie instalacji oraz konfiguracji (umożliwiającej jednak jed-
nocześnie wprowadzanie złożonych rozwiązań), o czym
przekonać się na poniższym przykładzie.
Webserwis w 5 min
Tworzenie strony serwerowej: Do stworzenia webserwisu po-
trzebujemy: dowolnego serwera aplikacji (np. Tomcat 5.x: http://
tomcat.apache.org), dystrybucji XFire ( np. xfire-all-1.0-M6.zip lub
nowsza, która można pobrać ze strony: http://xfire.codehaus.org/
Download) oraz dowolnego IDE Javy (np. Eclipse: http://
www.eclipse.org). Aby zbudować nasz webserwis, należy utwo-
rzyć odpowiednią strukturę katalogów aplikacji, tak jak przedsta-
wia to Listing 1. Następnie musimy skopiować do katalogu biblio-
tek naszej aplikacji (WEB-INF/lib) następujące pliki: xfire-all-1.0-
SNAPSHOT.jar, stax-api-1.0.jar, wsdl4j-1.4.jar, xerces-2.4.0.jar,
xml-apis.jar, jdom-1.0.jar ,annogen-0.1.0.jar, qdox-1.5.jar, xbean-
spring-2.0-SNAPSHOT.jar,spring-1.2.4.jar, stax-1.1.2-dev.jar
Początkowa konfiguracja biblioteki XFire nie różni się zasad-
niczo od innych narzędzi tego typu, należy zdefiniować punkt do-
Listing 3.
Interfejs klasy implementującej funkcjonalność
aplikacji
package pl.sdj.petstore;
public
interface
PetStore
{
// kup zwierzę o zadanej nazwie
long
buyPet
(
String
name
)
;
//sprawdź status zamówienia
String
getOrderStatus
(
long
orderId
)
;
}
Listing 4.
Implementacja funkcjonalności aplikacji
package pl.sdj.petstore.impl;
import pl.sdj.petstore.PetStore;
public
class
PetStoreImpl
implements
PetStore
{
public
String
getOrderStatus
(
long
orderId
)
{
// mamy tylko "mysz" w magazynie
if
(
orderId
==
"mysz"
.
hashCode
())
{
return
"zamowiony"
;
}
return
"nieznany"
;
}
public
long
buyPet
(
String
name
)
{
// zwroc hashcode jako identyfikator zlecenia
return
(
name
==
null
?
-
1
:
name
.
hashCode
())
;
}
Przydatne linki
• zbiór specyfikacji
http://www.w3.org/2002/ws/
• strona domowa XFire
http://xfire.codehaus.org
• serwis poświęconych webserwisom
http://webservices.xml.com/
• zbiór artykuł dotyczących webserwisów
http://webservices.oreilly.com/
• serwis poświęconych webserwisom
http://webservices.org/
• strona domowa organizacji zajmującej się rozwojem standar-
dów webserwisów
http://www.oasis-open.org
• organizacja promująca przenośność implementacji webserwisów
http://www.ws-i.org/
• strona domowa pakietu Axis
http://ws.apache.org/axis
Webserwis
Zbiór samo-opisujących się (przy pomocy języka WSDL) obiektów,
dostarczających dane oraz usługi w niezależny od platformy spo-
sób ( dzięki użyciu opartemu na formacie XML protokołowi SOAP),
udostępnionych z użyciem ustandaryzowanych protokołów komuni-
kacji (jak HTTP, JMS).
51
Webserwisy: XFire w akcji
www.sdjournal.org
Software Developer’s Journal 3/2006
Listing 6.
Struktura pliku konfiguracyjnego
stępu (w postaci servletu), który będzie odpowiedzialny za prze-
chwytywania żądań klientów i przekazywanie ich do właściwych
klas. W tym celu musimy stworzyć plik web.xml naszej aplikacji
o zawartości przedstawionej na Listingu 2.
Od tego mementu wszystkie żądania odnoszące się do
adresów rozpoczynających się w przypadku serwera Tom-
cat (przy założeniu iż serwer pracuje na domyślnym porcie,
a nasza aplikacji skonfigurowana pod nazwą XFire) od http://
localhost:8080/xfire/services, będą traktowane jako żądania
webserwisu i przekazywane do serwletu XFire.
Następnie musimy utworzyć klasy implementujące funk-
cjonalność naszej aplikacji, w postaci interfejsu (Listing 3)
oraz jego implementacji (Listing 4).
Kolejnym krokiem procesu konfiguracji jest wskazanie,
które klasy naszej aplikacji powinny być udostępnione jako
webserwisy. W tym celu należy utworzyć plik services.xml
w katalogu META-INF/xfire o zawartości przedstawionej na Li-
stingu 5, w którym poszczególne znaczniki mają następujące
znaczenie:
•
name
– jest nazwą pod jaką serwis będzie dostępny (np.
http://localhost:8080/xfire/services/PetStore ),
•
namespace
– przestrzeń nazw serwisu,
•
serviceClass
– klasa interfejsu definiująca metody serwisu,
•
implementationClass
– klasa implementująca serwis,
Po zbudowaniu naszej aplikacji i zainstalowaniu na serwe-
rze, mamy już w pełni działający webserwis. Aby upew-
nić się że wszystko działa poprawnie w oknie przeglądar-
ki wpisujemy następujący adres http://localhost:8080/xfire/
Listing 5.
Konfiguracja serwisu - plik META-INF/xfire/
services.xml
<
beans xmlns=
"http://xfire.codehaus.org/config/1.0"
>
<
service
>
<
name
>
PetStore
<
/name
>
<
namespace
>
http://www.sdj.pl
<
/namespace
>
<
serviceClass
>
pl.sdj.petstore.PetStore
<
/serviceClass
>
<
implementationClass
>
pl.sdj.petstore.impl.PetStoreImpl
<
/implementationClass
>
<
/service
>
<
/beans
>
<
beans xmlns=
"http://xfire.codehaus.org/config/1.0"
>
<!-- Definicja globalnych (uruchamianych dla wszystkich
zdefiniowanych serwisów) klas przetwarzających
komunikaty przychodzące,
zwracane oraz powiadomienia
o błędach. -->
<
xfire
>
..
<
inHandlers
><
handler handlerClass=
""
/
>
<
/inHandlers
>
<
outHandlers
><
handler handlerClass=
""
/
>
<
/outHandlers
>
<
faultHandlers
><
handler handlerClass=
""
/
>
<
/faultHandlers
>
<
/xfire
>
<!-- Definicja serwisu -->
<
service
>
<!-- Nazwa serwisu -->
<
name
/
>
<!-- Interfejs definiujący które metody będą udostępnione
jako webserwisy -->
<
serviceClass
/
>
<!-- Klasa implementująca serwis -->
<
implementationClass/
>
<!-- Przestrzeń nazw używana w komunikatach SOAP -->
<
namespace
/
>
<!-- Klasa fabryki odpowiedzialna za utworzenie obiektu
serwisu.
Można wskazać własną klasę fabryki, która
wykona dodatkowe czynności w trakcie tworzenie obiektu
lub wskazać iż chcemy zdefiniować nasz serwis za
pomocą annotacji podając jedną z predefiniowanych
fabryk: commons-attributes lub jsr181 (http://
xfire.codehaus.org/JSR+181+Service) -->
<
serviceFactory/
>
<!-- Definiuje sposób budowania komunikatów SOAP: „wrapped”
lub „document” -->
<
style/
>
<!-- Wersja specyfikacji SOAP: 1.1 (domyślnie) lub 1.2 -->
<
soapVersion
/
>
<!-- Zmienne ustawiane na obiekcie serwisu. Dzięki nim
możliwe jest np. zabronienie generowania opisu WSDL po
wpisaniu w przeglądarce
adresu serwisu zakończonego
„?wsdl”. -->
<
properties
>
<
property key=
"key"
>
value
<
/property
>
<
/properties
>
<!-- Definicja klas przetwarzających komunikaty
przychodzące,
zwracane i powiadomienia o błędach. -->
<
inHandlers
><
handler handlerClass=
""
/
>
<
/inHandlers
>
<
outHandlers
><
handler handlerClass=
""
/
>
<
/outHandlers
>
<
failtHandlers
>
<
handler handlerClass=
""
/
>
<
/faultHandlers
>
Słownik terminów
• SOAP (Simple Object Access Protocol) – oparty na formacie
XML protokół umożliwiający wywoływanie zdalnych metod,
• WSDL (Web Services Description Language) - język opisu
właściwości webserwisu,
• UDDI (Universal Description, Discovery and Integration) – de-
finiuje sposób rejestrowania oraz odnajdywania webserwisów,
• StAX (Streaming API for XML) – metoda przetwarzania da-
nych XML polegająca na inkrementalnym pobieraniu ich z
parsera (ang. Pull-parsing),
• DOM (Document Object Model) – metoda przetwarzania da-
nych XML polegająca na obrabianiu drzewa węzłów zbudo-
wanego na podstawie tych danych.
52
Inżynieria
oprogramowania
www.sdjournal.org
Software Developer’s Journal 3/2006
services/PetStore?wsdl, pod którym powinniśmy zobaczyć
XMLowy opis naszego serwisu w formacie WSDL.
Powyższy przykład pokazuje możliwość stworzenia
w pełni działającego serwisu, przy użyciu dosłownie kilku li-
nii konfiguracji, jednak pomimo prostoty, konfiguracja XFi-
re umożliwia wpływanie praktycznie na każdy aspekt dzia-
łania aplikacji. Podstawowy format konfiguracji umożliwia
zdefiniowanie następujących elementów, przedstawionych
na Listingu 6.
Teraz, kiedy wiemy, że serwis działa oraz znamy trochę
więcej możliwości konfiguracyjnych, możemy wzbogacić je-
go funkcjonalność np. o funkcje ograniczającą zdolność wy-
woływania jego metod tylko do klientów łączących się z za-
danego adresu IP. Taką funkcjonalność otrzymać można
wykorzystując tzw. „handlery”, czyli klasy, których kod bę-
dzie wykonywany przy każdym wywołaniu metod serwisu.
Obiekty handlerów możemy zarejestrować dla wszystkich
komunikatów przychodzących (
inHandlers
– wywołań me-
tod), wychodzących (
outHandlers
– rezultatów wywołania
metod) oraz powiadomień o błędach (
faultHandlers
– prze-
kazujących informacje o błędzie który wystąpił w trakcie wy-
wołania metody). Klasy te możemy rejestrować zarówno dla
pojedynczego serwisu jak i globalnie, dla wszystkich zdefi-
niowanych serwisów. Dodatkowo mogą one być umieszcza-
ne na różnych etapach (zwanych fazami, zdefiniowanymi
w klasie
Phase
) przetwarzania komunikatu, a więc nasza lo-
gika może zostać „wpięta” w moment parsowania komunika-
tu (
PARSE
), wybierania serwisu do którego ma zostać prze-
kazany komunikat (
DISPATCH
) , tuż przed wywołaniem meto-
dy serwisu (
PRE-INVOKE
) lub też w dowolnym innym punkcie,
który potrzebujmy wykorzystać. Dzięki takiej elastyczności
bez większych problemów możemy do naszej aplikacji do-
dać funkcjonalność szyfrowania lub cyfrowego podpisywa-
nia komunikatów SOAP, autentykacji użytkownika lub wer-
sjonowania API naszego serwisu.
Klasa naszego handlera może wyglądać tak jak zostało to
przedstawione na Listingu 7.
Najważniejszą częścią kodu jest metoda „invoke”, która
wykonywana jest przy przetwarzaniu każdego komunikatu.
W metodzie tej z żądania HTTP (HTTPServletRequest) po-
bierany jest adres IP klienta wywołującego metodę serwisu, a
następnie porównywany z adresem IP dozwolonym dla dane-
go serwisu, zdefiniowanym w pliku konfiguracyjnym. Metoda
getPhase
decyduje, w którym miejscu łańcucha przetwarzania
komunikatu zostanie umieszczona nasza klasa (Przetwarza-
nie komunikatów przychodzących składa się z następujących
faz:
TRANSPORT
,
PARSE, PRE _ DISPATCH
,
DISPATCH
,
POLICY
,
USER
,
PRE _ INVOKE, SERVICE
).
Aby móc testować powyższy kod wewnątrz naszego
IDE, do bibliotek aplikacji musimy dodać plik servletapi-
2.3.jar z dystrybucji XFire. Następnie nasza klasa musi zo-
stać zarejestrowana w serwisie jako
handler
, poprzez doda-
nie poniższego wpisu do pliku
services.xml
(Listing 8). Po
zbudowaniu aplikacji, możemy być pewni, iż nikt niepożą-
dany nie będzie miał dostępu do naszej, z „takim trudem”
stworzonej funkcjonalności.
Tworzenie klienta
Przykładowym klientem naszego serwisu będzie prosta aplika-
cja konsolowa. Do jej uruchomienia potrzebujemy następujących
bibliotek, dostarczonych z dystrybucją pakietu: commons-disco-
very-0.2.jar, commons-logging-1.0.4.jar, log4j-1.2.8.jar, wsdl4j-
1.5.1.jar, jdom-1.0.jar, servletapi-2.3.jar, stax-1.1.2-dev.jar,stax-api-
1.0.jar, xerces-2.4.0.jar, xfire-all-1.0-SNAPSHOT.jar, xml-apis.jar,
Listing 7.
Implementacja klasy handlera
package pl.sdj.handlers;
import org.codehaus.xfire.MessageContext;
import org.codehaus.xfire.handler.AbstractHandler;
import org.codehaus.xfire.transport.http.
XfireServletController;
public
class
IPRestrictionHandler
extends
AbstractHandler
{
public
void
invoke
(
MessageContext
ctx
)
throws
Exception
{
// pobierz adres zdalnego klienta
String
remoteIp
=
XfireServletController
.
getRequest
()
.
getRemoteAddr
()
;
// pobierz dozwolny adres klienta
String
allowedIP
=
(
String
)
ctx
.
getService
()
.
getProperty
(
"allowedIP"
)
;
System
.
out
.
println
(
"Proba wywolania metody:"
+
ctx
.
getInMessage
()
.
getAction
()
+
" z adresu "
+
remoteIp
)
;
// porownaj adresy
if
(
!
remoteIp
.
equals
(
allowedIP
)){
// jezeli adresy nie sa rowne przerwij przetwarzanie
// komunikatu
throw
new
XFireException
(
"Twój adres IP nie należy
do dozwolonych"
)
;
}
}
// okresla w którym miejscu łańcucha wywołań należy
// umieścić nasz handler
public
String
getPhase
() {
return
Phase
.
USER
;
}
}
Listing 8.
Rozszerzona konfiguracja serwisu
<
beans xmlns=
"http://xfire.codehaus.org/config/1.0"
>
<
service
>
<
name
>
PetStore
<
/name
>
<
namespace
>
http://www.sdj.pl
<
/namespace
>
<
serviceClass
>
pl.sdj.petstore.PetStore
<
/serviceClass
>
<
implementationClass
>
pl.sdj.petstore.impl.PetStoreImpl
<
/implementationClass
>
<
properties
>
<
property key=
"allowedIP"
>
127.0.0.1
<
/property
>
<
/properties
>
<
inHandlers
>
<
handler handlerClass=
"
pl.sdj.handlers.IPRestrictionHandler"
/
>
<
/inHandlers
>
<
/service
>
<
/beans
>
53
Webserwisy: XFire w akcji
www.sdjournal.org
Software Developer’s Journal 3/2006
Listing 9.
Implementacja klienta serwisu
public
class
XfireClient
{
private
static
final
String
NAME
=
"PetStore"
;
private
static
final
String
NAMESPACE
=
"http://www.sdj.pl"
;
private
static
final
Class
SERVICECLASS
=
PetStore
.
class
;
private
static
final
String
SERVICE_ADDRESS
=
"http://127.0.0.1:8080/xfire/services/PetStore"
;
private
PetStore
service
;
public
void
init
()
{
Service
serviceModel
=
new
ObjectServiceFactory
()
.
create
(
SERVICECLASS
,
NAME
,
NAMESPACE
,
null
)
;
try
{
service
=
(
PetStore
)
new
XfireProxyFactory
()
.
create
(
serviceModel
,
SERVICE_ADDRESS
)
;
}
catch (MalformedURLException e)
{
throw
new
RuntimeException
(
"Niepoprawny adres
serwisu:"
+
e
.
getMessage
())
;
}
}
public
void
buyPet
()
throws
Exception
{
System
.
out
.
println
(
"Kupuje 'mysz'"
)
;
long
orderId
=
service
.
buyPet
(
"mysz"
)
;
System
.
out
.
println
(
"Identyfikator zakupu to:"
+
orderId
)
;
String
status
=
service
.
getOrderStatus
(
orderId
)
;
System
.
out
.
println
(
"Status zlecenia zakupu:"
+
status
)
;
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
XFireClient
client
=
new
XFireClient
()
;
client
.
init
()
;
client
.
buyPet
()
;
}
}
W następnej kolejności tworzony jest obiekt pośrednika
(
XFireProxy
), odpowiedzialnego za delegowanie wywołań me-
tod do zdalnego serwisu. Jako parametry, należy podać zde-
finiowany wcześniej serwis oraz adres serwisu, z którego me-
tody chcemy wywołać. Od tego momentu możemy pracować
ze zdalnym serwisem dokładnie tak samo jak używamy lokal-
nych obiektów.
Po uruchomieniu kodu klienta, na konsoli powinniśmy
otrzymać wynik podobny do przedstawionego w Listingu 10.
Co dalej?
Oczywiście możliwości, które oferuje biblioteka XFire są dużo
większe niż opisany powyżej przykład, zarówno pod wzglę-
dem łatwości użycia jak i oferowanej funkcjonalności. Najcie-
kawsze cechy biblioteki XFire:
• XFire niezwykle łatwo integruje się z popularnymi konte-
nerami jak Spring , PiccoContainer czy Loom, dzięki te-
mu za pomocą kilku linii kodu możliwe jest udostępnienie
serwisu lub stworzenie klienta (http://xfire.codehaus.org/
Container+Support),
• serwis może zostać zdefiniowany za pomocą anotacji Ja-
va 1.5 lub ich odpowiednika
commons-attributes
(http://
xfire.codehaus.org/JSR+181+Annotations),
• zależnie od potrzeb czy wymagań biznesowych XFire
pozwala na zastosowanie rożnych bibliotek służących
do mapowania obiektów Javy na format XML (ang. Data
binding ) jak Aegis, XMLBeans, Jaxb 1.1 i 2.0,
• poza transportem opartym na protokole HTTP, możli-
we jest również wykorzystanie komunikacji z użyciem ko-
munikatów JMS oraz asynchronicznego protokołu XMPP/
Jabber,
• XFire może zostać również osadzony wewnątrz dowol-
nej aplikacji, która dzięki temu może funkcjonować ja-
ko silnik SOAP, dostarczając np. swojej własnej metody
konfiguracji.
Cały czas trwają również prace nad dodawaniem nowych
możliwości oraz lepszym wsparciem dla opracowanych
standardów, między innymi takich jak WS-Security (odpo-
wiedzialnych za szyfrowanie, podpis cyfrowy wymienianych
wiadomości) czy WS-Policy (umożliwiających uzgodnienie
wymagań oraz możliwości obu stron komunikacji).
Jeżeli jednak zdarzy się sytuacja, że biblioteka XFire
nie posiada funkcjonalności, której potrzebujecie, nic nie
stoi na przeszkodzie, aby poprosić o jej dodanie. Na pew-
no znajdzie się ktoś, kto wysłucha prośby, a w większości
przypadków zaimplementuje to tak szybko jak tylko to moż-
liwe. Z zespołem XFire skontaktować się można poprzez
grupy dyskusyjne, kanał IRC (http://xfire.codehaus.org/
Support) lub dodając wpis z propozycją zmiany do systemu
zgłaszania błędów JIRA (http://jira.codehaus.org/secure/Br
owseProject.jspa?id=10750). n
Listing 10.
Wynik wywołania klienta
Kupuje 'mysz'
Identyfikator zakupu to :3367187
Status zlecenia zakupu :zamowiony
javamail-1.3.2.jar, commons-httpclient-3.0-rc3.jar, commons-co-
dec-1.3.jar oraz klasa interfejsu naszego serwisu
PetStore
, przed-
stawiona na Listingu 9.
Najbardziej interesującą częścią powyższego kodu
jest metoda
init
, w której utworzony zostaje obiekt serwi-
su, przy pomocy którego, będziemy się odwoływać do je-
go zdalnej instancji. Musi on zostać zainicjowany dokład-
nie takimi samymi wartościami jak jego odpowiednik po
stronie serwera, a więc za parametry należy podać odpo-
wiedniki następujących wpisów z pliku konfiguracyjnego
servies.xml
:
ObjectServiceFactory().create(<serviceClass>,<name>,<namespace>,
properties);
gdzie parametr properties umożliwia przekazanie dodatków
parametrów jak wersja protokołu SOAP czy sposobu genero-
wania komunikatów.