background image

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

background image

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

>

background image

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).

background image

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.

background image

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

>

background image

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.