Sunteți pe pagina 1din 13

Servicii web bazate pe arhitectura REST

Cuprins

1 Introducere
2 Arhitecturi de servicii web

3 Principii REST

4 Dezvoltarea unui serviciu web bazat pe arhitectura REST

5 Concluzii

6 Referine

Introducere
Representational State Transfer (REST) este un stil arhitectural software pentru sisteme
hipermedia distribuite, cum ar fi world wide web. Termenul a fost folosit pentru prima dat n
lucrarea de doctorat "Architectural Styles and the Design of Network- based Software
Architectures" scris de Roy Fielding, unul din principalii autori a specificaiilor protocolului
HTTP.
REST se refer strict la o colecie de principii arhitecturale ntr-o reea care subliniaz felul n
care resursele sunt definite i adresate. ntr-un context mai puin riguros, REST descrie orice
interfa care transmite date prin HTTP fr un nivel adiional de mesagerie cum ar fi SOA sau
folosirea sesiunilor prin cookie-uri HTTP. Este posibil s dezvoltm sisteme software n
concordan cu stilul arhitectural REST fr s folosim HTTP i fr s interacionm pe World
Wide Web. De asemenea, este posibil s dezvoltm un sistem software care s foloseasc HTTP
i XML care s nu respecte principiile REST, urmnd n schimb modelul arhitectural RPC
(remote procedure call).

Arhitecturi de servicii web


n momentul de fa se evideniaz trei tipuri de arhitecturi pentru serviciile web: arhitectura
REST, arhitectura RPC i un hibrid ntre REST i RPC.
n serviciile web care se bazeaz pe arhitectura REST, informaiile despre metoda apelat sunt
date de metoda HTTP folosit, iar argumentele metodei sunt date de URI-ul folosit. Combinaia
este puternic, astfel din prima linie a unei cereri HTTP fcut unui serviciu web n manier
REST (GET /reports/open-bugs HTTP/1.1) ar trebui s nelegem ce dorete clientul s fac.
Restul cererii sunt doar detalii. Dac metoda HTTP nu corespunde cu metoda pe care o apeleaz
clientul, atunci serviciul web nu este RESTful. La fel dac argumentele nu sunt date de URI. Ne
vom referi la arhitectura REST n detaliu atunci cnd vom prezenta principiile REST.
1

Un serviciu web n stil RPC accept un envelope (asemntor cu plicul unei scrisori) n care se
regsesc date de la client i trimite un envelope similar napoi. Numele metodei i argumentele
sunt trimise prin acest element envelope. Fiecare serviciu web bazat pe RPC definete un nou
vocabular. Programele funcioneaz ntr-o manier asemntoare, de fiecare dat cnd scriem un
program, definim funcii cu nume diferite. n contrast, serviciile web RESTful partajeaz un
vocabular comun dat de metodele HTTP (sau WEBDAV, sau orice interfa uniform standard) .
Fiecare obiect al unui serviciu bazat pe REST rspunde unei aceeai interfee standard.
Protocolul XML-RPC pentru servicii web reprezint cel mai evident exemplu al arhitecturii
RPC, cu toate c este un protocol depit. De exemplu, un serviciu XML-RPC care te las s
caui un spaiu XWiki este asemntor unui limbaj de programare. Apelezi o funcie
(lookForXWikiSpace) cu anumite argumente (Blog) i obii o valoare de ntoarcere (un
rspuns). Informaiile despre metod (numele funciei) i argumentele sunt puse ntr-un
document XML.
<?xml version="1.0" ?>
<methodCall>
<methodName>lookForXWikiSpace</methodName>
<params>
<param><value><string>Blog</string></value></param>
</params>
</methodCall>

Documentul XML este plasat nr-un element envelope i transferat serverului. Elementul
envelope este o cerere HTTP ce conine o metod, un URI, i antete HTTP. Documentul XML se
schimb n funcie de ce metod apeleaz clientul, dar elementul envelope, reprezentat de cererea
HTTP rmne neschimbat. Nu conteaz ce schimbri apar cu baza de date a serviciului, URI-ul
rmne s spunem http://www.xwiki.org/rpc i metoda HTTP este mereu POST. Altfel spus, un
serviciu XML-RPC ignor majoritatea funcionalitilor HTTP, expune un singur URI i suport
o singur metod pe acest URI (POST). Dac am dori s transformm acest exemplu astfel nct
s respecte principiile REST, am expune URI-ul http://www.xwiki.org/spaces/00598491,
informaia despre metoda apelat ar fi coninut de metoda HTTP, GET fiind echivalent n acest
scenariu cu lookForXWikiSpace. Argumentele sunt coninute n URI, astfel un astfel de ipotetic
serviciu RESTful ar putea expune un numr mare de URI-uri: unul pentru fiecare spaiu. De data
aceasta, elementul envelope este gol, cererea HTTP GET nu conine nici un fel de corp.
Arhitectura hibrid REST-RPC descrie serviciile web care nu sunt nici bazate pe REST i nici nu
sunt servicii pure RPC. Aceste servicii sunt, de obicei, create de ctre programatori care tiu
multe despre cum se contruiete o aplicaie web real, dar nu cunosc att de bine principiile
REST.
Dac ne ndreptm atenia spre serviciul web Flickr, observm c am putea avea un URI:
http://www.flickr.com/services/rest?api_key=xxx&method=flickr.photos.search&tags=dog. Dei
acest URI conine cuvntul rest, observm c folosete HTTP ca element envelope, acest lucru
fiind caracteristic serviciilor RPC. Cu toate acestea, argumentele sunt transmise prin URI
(fotografii cu eticheta dog) la fel ca orice alt serviciu bazat pe arhitectura REST. Problema este
faptul c numele metodei se afl de asemenea n URI (search for photos). ntr-un serviciu web
RESTful, informaia despre metoda apelat ar fi fost transmis prin metoda HTTP (GET), i ce
ar fi rmas ar fi devenit argumente.
2

Un alt principiu REST pe care arhitectura REST-RPC l ncalc este faptul c, de multe ori,
metoda HTTP nu corespunde cu metoda apelat. Astfel, API-ul web Flickr cere clienilor s
foloseasc HTTP GET chiar i atunci cnd ncearc s modifice date de pe server. Pentru a terge
o poz de pe Flickr trebuie s facem o cerere GET pentru un URI care include
method=flickr.photos.delete. O astfel de cerere ncalc i sigurana metodei GET.
Muli programatori dezvolt servicii web ca i cum ar dezvolta aplicaii web, i ajung s dezvolte
servicii web bazate pe arhitectura hibrid REST-RPC. Iar existena acestui tip de arhitectur a dus
la mult confuzie.

Principii REST
Resurse
Un concept important care ine de arhitectura REST este existena resurselor. n mod uzual o
resurs este o entitate care poate fi stocat ntr-un computer i poate fi reprezentat printr-un ir
de bii: un document, un rnd dintr-o baz de date, sau rezultatul rulrii unui algoritm. O resurs
poate s fie i un obiect fizic cum ar fi un mr, un concept abstract cum ar fi curaj, dar
reprezentrile unor astfel de resurse sunt de cele mai multe ori dezamgitoare. Fiecare resurs are
ataat un identificator global (un URI). Pentru a manipula resursele, componentele reelei
(clienii i serverele) comunic printr-o interfa standardizat (de exemplu HTTP) i schimb
reprezentri ale resurselor (documentele care transport informaiile). De exemplu, o resurs care
este un cerc ar putea accepta i returna o reprezentare care specific un centru i o raz, formatat
n SVG, dar poate accepta i returna o reprezentare care specific trei puncte diferite situate pe
cerc, separate prin virgul.
Iat cteva posibile resurse:

Versiunea 2.0.1 a unui release software


Ultima versiune a unui release software

O hart rutier a Braovului

Cteva informaii generale despre leadership

Urmtorul numr prim dup 1024

Urmtoarele cinci numere prime dup 1024

Valoarea vnzrilor pentru trimestrul al patru-lea din 2005

Relaia dintre dou cunotine: Florin i Rzvan

URI
Orice resurs trebuie s aib cel puin un URI. URI-ul este numele i adresa resursei. Dac o
informaie nu are un URI, nu este o resurs i nu putem spune c se afl pe Web.
3

URI-urile trebuie s fie descriptive. Trebuie s existe o coresponden intuitiv ntre un URI i o
resurs. Iat cteva exemple bune de URI-uri pentru resursele introduse mai devreme:

http://www.xwiki.com/enterprise/releases/2.0.1.tar.gz
http://www.xwiki.com/enterprise/releases/latest.tar.gz

http://www.harti.ro/harta/rutiera/Romania/Brasov

http://en.wikipedia.org/wiki/Leadership

http://www.example.com/nextprime/1024

http://www.example.com/next-5-primes/1024

http://www.example.com/vanzari/2005/T4

http://www.example.com/relatii/Florin;Rzvan

URI-urile trebuie s aib o structur, adic s varieze ntr-un mod predictibil. Nu putem merge la
caut/leopard pentru resursa leopard i la vreau-s-tiu-despre/leu pentru leu. Dac un client
cunoate structura URI-urilor unui serviciu, i poate crea propriile puncte de intrare n acel
serviciu, i obine informaii ntr-un mod eficient.
Dup definiie, dou resurse nu pot fi aceleai. Dac acest lucru s-ar ntmpla am avea o singur
resurs. Cu toate acestea, la un moment dat, dou resurse pot avea aceeai reprezentare. Dac
release-ul curent este 2.0.1, atunci http://www.xwiki.com/enterprise/releases/2.0.1.tar.gz i
http://www.xwiki.com/enterprise/releases/latest.tar.gz s-ar referi la acelai fiier pentru o
perioad. Dar ideeile din spatele acestor dou URI-uri sunt diferite: primul URI este numele unei
anumite versiuni, iar al doilea URI este numele unei versiuni care n momentul respecti este cea
mai recent. Sunt dou concepte diferite, deci dou resurse diferite.
Adresabilitate
O aplicaie este adresabil dac expune aspecte interesante legate de setul su de date ca i
resurse. Cum resursele sunt expuse prin URI-uri, o aplicaie adresabil expune un URI pentru
orice informaie care s-ar putea dovedi de folos. De obicei, se ajunge la un numr foarte mare de
URI-uri.
Adresabilitatea este una din cele mai bune caracteristici ale unei aplicaii web. Permite clienilor
s foloseasc aplicaii web n feluri la care dezvoltatorii nu s-au gndit. Urmnd acest principiu
n dezvoltarea unui serviciu web, utilizatorii serviciului vor beneficia de mai multe avantaje ale
REST. Din acest motiv serviciile REST-RPC sunt att de comune: combin adresabilitatea cu
modelul programrii bazat pe apeluri de funcii.
Din pcate, multe aplicaii web nu respect principiul adresabilitii. Acest lucru se ntmpl n
special n cazul aplicaiilor care folosesc AJAX n mod extensiv. De exemplu, din punctul de
4

vedere al utilizatorilor, exist un singur URI pentru Gmail: https://mail.google.com/. Orice


aciune am face nu vom vedea un alt URI. Resursa emailurile despre REST nu este adresabil,
chiar dac are un URI: https://mail.google.com/mail/?q=REST&search=query&view=tl.
Problema este c utilizatorul nu este consumatorul sitului web. Situl web este de fapt un serviciu
web, iar adevratul consumator este un program JavaScript care ruleaz n browserul web.
Serviciul web Gmail este adresabil, dar aplicaie web Gmail care folosete acest serviciu nu este
adresabil.
Fr stare
Lipsa strii se traduce prin faptul c orice cerere HTTP se ntmpl ntr-o izolare complet.
Atunci cnd un client face o cerere HTTP, include informaiile necesare pentru ca serverul s
ndeplineasc acea cerere. Serverul nu se bazeaz niciodat pe cereri precedente.
Mai practic, putem considera lipsa strii n termeni de adresabilitate. Adresabilitatea ne oblig s
expunem orice informaie util ca i resurs cu un URI propriu. Pentru a respecta principiul lipsei
strii trebuie s definim ca resurse i strile posibile pe care le poate avea serverul. Clientul nu
trebuie s aduc serverul ntr-o anumit stare pentru a-l face mai receptiv unei anumite cereri.
Pentru a nelege mai bine, putem lua ca exemplu un motor de cutare. Cnd facem o cutare pe
Google nu obinem toate rezultatele ci doar o list cu primele zece rezultate, care corespund cel
mai bine interogrii. Pentru a obine mai multe rezultate trebuie s facem o nou cerere.
Urmtoarele pagini pe care le obinem sunt stri diferite ale aplicaiei, i au propriul URI: http://
www.google.com/search?q=REST&start=10. Putem transmite aceast stare a aplicaiei, putem s
i facem cache, sau o putem aduga la bookmarkuri, la fel cum putem face cu orice alt resurs
adresabil. Aceast aplicaie este fr stare deoarece fiecare cerere este total deconectat de
celelelalte. Un client poate cere resursele de mai multe ori, n orice ordine. Poate s cear pagina
doi a listei cu rezultate, nainte s cear prima pagin, iar pentru server nu va avea nici o
importan.
Serverul nu trebuie s i fac griji c o conexiune ar putea expira, pentru c nici o interaciune
nu dureaaz mai mult dect o singur cerere. De asemenea, serverul nu trebuie s cunoasc
"unde" se afl fiecare client n aplicaie, deoarece clienii trimit toate informaiile necesare cu
fiecare cerere. Clientul nu va face niciodat o aciune ntr-un directoriu nedorit, deoarece serverul
a inut anumite stri fr s anune clientul.
Lipsa strii aduce i noi funcionaliti. Este mai uor s distribui o aplicaie fr stare pe mai
multe servere. Deoarece dou cereri nu depind niciodat una de cealalt, pot fi tratate de dou
servere diferite fr s comunice ntre ele. Acest aspect imbuntete scalabilitatea aplicaiei.
Pentru ca un serviciu s fie adresabil trebuie s disecm datele aplicaiei n seturi de resurse. n
schimb, HTTP este un protocol fr stare, astfel lipsa strii n serviciul nostru este implicit.
Reprezentri

Atunci cnd mprim aplicaia n resurse, mrim zona de interaciune cu clienii. Utilizatorii i
pot construi un URI potrivit pentru a accesa exact datele de care au nevoie. Dar resursele nu sunt
datele, ci doar ideea arhitectului despre cum s mpart datele. Un server web nu poate transmite
o idee, trebuie s trimit octei, ntr-un anumit format de fiier, care este reprezentarea unei
resurse.
O resurs este o surs de reprezentri, iar o reprezentare este format din date despre starea
curent a unei resurse. Multe resurse sunt ele nsele date (cum ar fi o list de buguri deschise),
deci o reprezentare evident a unor astfel de resurse sunt chiar datele. Serverul ar putea prezenta
lista bugurilor deschise printr-un document XML, o pagin web sau text simplu. Valoarea
vnzrilor din trimestrul al patru-lea poate fi reprezentat numeric sau printr-un grafic. Pentru
orice resurs putem alege ntre mai multe tipuri de reprezentri.
n cazul unor resurse care sunt obiecte fizice, sau alte lucruri care nu pot fi reduse la informaii,
nu trebuie s ne ateptm s avem o fidelitate perfect a reprezentrilor. Adic reprezentrile
unor astfel de resurse sunt alctuite din orice informaii utile despre starea curent a resurselor.
Dac considerm un obiect fizic, cum ar fi un automat de sucuri, avnd ataat un serviciu web.
Scopul serviciului este de a permite clienilor automatului s evite drumurile nenecesare pn la
automat. Folosind acest serviciu, clienii vor ti cnd sucul este rece, i cnd marca lor preferat
de sucuri nu mai este disponibil. Nimeni nu se ateapt ca sucurile s fie disponibilie prin
serviciul web, deoarece obiectele fizice nu sunt date. Dar au anumite date ataate i anume
metadatele. Fiecare slot al automatului poate fi instrumentat astfel nct s cunoasc preul,
temperatura i marca urmtoarei doze de suc. Fiecare slot poate fi expus ca i resurs, ca i tot
automatul de altfel. Metadatele pot fi folosite n reprezentrile resurselor.
Dac un server ofer mai multe reprezentri ale unei resurse, atunci se pune problema cum i d
seama pe care dintre reprezentri o prefer clientul. De exemplu, un comunicat de pres poate s
aibe o versiune n limba englez i o versiune n limba spaniol. Cea mai simpl soluie este s
folosim URI-uri diferite pentru fiecare resurs. Astfel, http://www.example.com/releases/104.en
poate fi reprezentarea n limba englez a comunicatului, iar
http://www.example.com/releases/104.es denot reprezentarea n limba spaniol. Dezavantajul
este faptul c expunem URI-uri diferite pentru aceeai resurs, iar oamenii care vorbesc despre
comunicatul de pres n limbi diferite par ca vorbesc despre lucruri diferite. Alternativa const n
negocierea coninutului. n acest scenariu avem un singur URI expus i anume
http://www.example.com/releases/104. Cnd un client face o cerere ctre acest URI, ofer antete
HTTP speciale care specific ce fel de reprezentri accept.
Interfaa uniform
n spaiul World Wide Web, sunt doar cteva aciuni pe care le poi face cu o resurs. HTTP ofer
patru metode de baz pentru cele mai comune operaii:

Returnarea unei reprezentri a unei resurse: HTTP GET


Crearea unei noi resurse: HTTP PUT unui nou URI, or HTTP POST unui URI existent

Modificarea unei resurse: HTTP PUT unui URI existent


6

tergerea unei resurse: HTTP DELETE

Pentru a obine sau a terge o resurs, clientul trimite o cerere GET sau DELETE asupra
URI+ului resursei. n cazul unei cereri GET, serverul returneaz o reprezentare n corpul
rspunsului. Pentru o cerere DELETE, corpul rspunsului poate conine un mesaj de stare, sau
nimic.
Pentru a crea sau modifica resurse, clientul trimite o cerere PUT care, de obicei, include o
entitate-corp. Entitatea-corp conine propunerea clientului pentru reprezentarea resursei. Ce fel
de date alctuiesc reprezentarea, i n ce format, depinde de serviciu.
ntr-o arhitectur REST, POST este folosit pentru a crea resurse subordonate: resurse sunt n
relaie cu o alt resurs "printe". De exemplu, pentru a crea o pagin wiki ntr-un spaiu XWiki,
trimitem o cerere POST resursei printe, care este spaiul.
Mai avem dou metode HTTP care pot fi folosite ntr-un serviciu web:

Returnarea unei reprezentri format doar din metadate: HTTP HEAD


Verificarea metodelor HTTP suportate de o anumit resurs: HTTP OPTIONS

Pentru ca un serviciu web s fie RESTful nu trebuie s folosim interfaa uniform definit de
HTTP. Metodele HTTP nu sunt cele mai potrivite de fiecare dat. Ceea ce conteaz este s
alegem o interfa care s fie uniform. Dac avem un URI al unei resurse, tim cum obinem
reprezentarea: trimitem o cerere HTTP GET acelui URI. Interfaa uniform face ca dou servicii
s fie la fel de similare cum sunt dou situri web. Fr interfaa uniform, ar trebui s aflm cum
fiecare serviciu web accept i transmite informaii. Regulile ar putea fi diferite chiar i pentru
diferite resurse dintr-un singur serviciu. Fr o interfa uniform, am avea numeroase metode
care ar lua locul lui GET: doSearch, getPage, nextPrime.
Cteva aplicaii extind interfaa uniform HTTP. Cea mai cunoscut este WebDav, care adaug
opt noi metode HTTP, printre care MOVE, COPY i SEARCH. Dac am folosi aceste metode
ntr-un serviciu web nu am viola nici un principiu REST, pentru c arhitectura REST nu impune
folosirea unei anumite interfee uniforme.
Sigurana i idempotena
Dac n dezvoltarea unui serviciu web folosim ca interfa uniform HTTP, obinem dou
proprieti folositoare. Cnd sunt folosite corect, cererile GET i HEAD sunt sigure. Iar cererile
GET, HEAD, PUT i DELETE sunt idempotente.
O cerere GET sau HEAD se face pentru a citi anumite date, nu pentru a schimba ceva pe server.
Clientul poate s fac o cerere GET sau HEAD de zece ori, iar resursa se comport de parc nu
s-ar fi fcut nici o cerere. Faptul c o cerere este sigur se traduce prin faptul c doar se
returneaz o reprezentare a resursei. Un client ar trebui s aibe posibilitatea de a trimite cereri
GET i HEAD asupra unui URI necunoscut, fr s se ntmple ceva nedorit.

Idempotena este o idee un pic mai greu de perceput dect sigurana. Ideea vine din matematic,
unde o operaie este idempotent dac are acelai efect chiar dac o aplici de mai multe ori.
Multiplicarea unui numr cu zero este idempotent: 4 0 0 0 este acela;i lucru cu 4 0. Prin
analogie, o operaie asupra unei resurse este idempotent dac a face o singur cerere este similar
cu a face o serie de cereri identice. A doua cerere i urmtoarele las resursa n aceeai stare pe
care o avea dup prima cerere.
PUT i DELETE sunt idempotente. Dac tergem o resurs, aceasta dispare. Dac facem o nou
cerere DELETE, ea rmne tears. La fel, dac crem o nou resurs cu PUT, i apoi retrimitem
cererea PUT, resursa va rmne la fel i cu aceleai proprieti ca dup creare. Dac folosim PUT
pentru a schimba starea unei resurse, putem retrimite cererea PUT iar starea resursei va rmne
aceeai.
Partea practic a idempotenei este faptul c nu ar trebui s lsm clienii s schimbe starea unei
resurse n termeni relativi. Dac o resurs reine o valoare numeric ca parte din starea resursei,
un client ar putea folosi PUT pentru a seta aceast valoare pe 4, sau 0, sau alt numr, dar nu
pentru a incrementa valoarea. Dac valoarea iniial este 0, dac trimitem dou cereri PUT care
s seteze valoarea la 4, valoarea numeric rmne 4. Dar dac trimitem dou cereri PUT prin
care incrementm valoarea numeric cu 1, atunci valoarea nu va rmne 1, ci va fi 2, ceea ce nu
respect idempotena.
Sigurana i idempotena ofer posibilitatea unui client s fac cereri HTTP sigure pe o reea
nesigur. Dac facem o cerere GET i nu primim nici un rspuns, putem s facem o nou cerere
fr nici o problem. La fel se ntmpl si cu o cerere PUT. Metoda POST, n schimb, nu este
nici sigur i nici idempotent. Dac facem dou cereri POST asupra unei resurse, cel mai
probabil, vom obine dou resurse subordonate, coninnd aceeai informaie.
O greeal comun ntr-un serviciu web care se dorete s respecte principiile REST, este de a
expune operaii nesigure prin metoda GET. API-urile Del.icio.us i Flickr fac aceast greeal.
Atunci cnd facem o cerere GET pe https://api.del.icio.us/posts/delete, nu obinem o
reprezentare, ci modificm datele de pe server.

Dezvoltarea unui serviciu web bazat pe arhitectura REST


Dorim s expunem informaii prezente ntr-o aplicaie XWiki pe o reea (Internet). Alegerea unei
interfete uniform este simpl, dorim ca serviciul s fie folosit de ct mai muli clieni, iar fiecare
limbaj de programare are o librrie HTTP. Deci alegem HTTP, avnd n vedere c HTTP st la
baza Web-ului. Alegerea formatului reprezentrilor este de asemenea uoar, ubicuitatea
librriilor de parsare XML ne ajut n acest sens.
Urmtorul pas este sa realizm arhitectura URI-urilor pentru resursele din XWiki pe care vrem s
le facem disponibile. n acest sens vom folosi "/" pentru a delimita ierarhiile (/spaces/
{spaceName}/pages) i variabile query pentru a transmite parametrii necesari unor algoritmi
/spaces/{spaceName}/pages/{pageName}/comments?author=alex&content=Nice%20article. De
asemenea vom folosi i {} pentru a delimita prile URI-urilor care vor fi convertite n parametri.
8

.../spaces
GET: returneaz

lista spaiilor dintr-un wiki;

.../spaces/{spaceName}
GET: returneaz un spaiu
POST: creaz un spaiu;

(specificat de parametrul spaceName);

DELETE: terge un spaiu;

.../spaces/{spaceName}/pages
GET: returneaz paginile din spaiul

specificat;

.../spaces/{spaceName}/pages/{pageName}
GET: returneaz pagina specificat (pageName) din spaiul specificat (spaceName);
POST: creaz o pagin cu numele "pageName" n spaiul specificat, accept parametrii

query: title, content i parent;

DELETE: terge pagina cu numele "pageName" spaiul specificat;

.../spaces/{spaceName}/pages/{pageName}/history
GET: returneaz lista versiunilor paginii;
.../spaces/{spaceName}/pages/{pageName}/history/{version}
GET: returneaz o versiune specific a paginii;
DELETE: terge versiunea specificat;
.../spaces/{spaceName}/pages/{pageName}/comments
GET: returneaz lista comentariilor din pagina specificat;
POST: creaz un comentariu, accept parametrii query: author

i content;

.../spaces/{spaceName}/pages/{pageName}/comments/{commentNumber}
GET: returneaz comentariile din pagin;
DELETE: sterge un comentariu din pagin;
.../spaces/{spaceName}/pages/{pageName}/attachments
GET: returneaz lista ataamentelor dintr-o pagin;
.../spaces/{spaceName}/pages/{pageName}/attachments/{attachmentName}
GET: returneaz informaii despre un ataament;
DELETE: terge ataamentul specificat;
.../spaces/{spaceName}/pages/{pageName}/class
GET: returneaz clasa din pagina specificat;
.../spaces/{spaceName}/pages/{pageName}/class/properties
GET: returneaz lista proprietilor clasei;
.../spaces/{spaceName}/pages/{pageName}/class/properties/{propertyName}
GET: returneaz o proprietate a clasei;

.../spaces/{spaceName}/pages/{pageName}/objects
GET: returneaz lista obiectelor din pagin;
.../spaces/{spaceName}/pages/{pageName}/objects/{className}
GET: returneaz lista obiectelor dintr-o pagin, dintr-o anumit clas;
.../spaces/{spaceName}/pages/{pageName}/objects/{className}/{objectNumber}
GET: returneaz un obiect dintr-o pagin, apainnd unei anumite clase;
DELETE: removes the specified object;
.../spaces/{spaceName}/pages/{pageName}/objects/{className}/{objectNumber}/
{propertyName}
GET: returneaz proprietatea unui obiect.

Detalii legate de implementare


Pentru implementare am ales s folosim un framework java simplu i matur: Restlet. Avem
nevoie de un ruter care s fac legtura ntre URI-uri i clasele corespunztoare fiecrei resurse.
Router router = new Router(getContext());
router.attach("/spaces", SpacesResource.class);
router.attach("/spaces/{spaceName}", SpaceResource.class);
router.attach("/spaces/{spaceName}/pages", PagesResource.class);
router.attach("/spaces/{spaceName}/pages/{pageName}", PageResource.class);
router.attach("/spaces/{spaceName}/pages/{pageName}/history",
PageVersionsResource.class);
router.attach("/spaces/{spaceName}/pages/{pageName}/history/{version}",
PageVersionResource.class);
router.attach("/spaces/{spaceName}/pages/{pageName}/comments",
CommentsResource.class);
...........................................................................
...................

Pentru implementarea serviciului nostru am folosit Restlet. Restlet (http://www.restlet.org) este


un framework care permite maparea conceptelor REST n clase Java. Poate fi folosit pentru
implementarea oricrui sistem RESTful, nu doar a serviciilor web.
Conceptul fundamental al Restlet este maparea dintre URI-uri i clasele Java corespunztoare
resurselor. Pentru a nelege ce fel de cod trebuie s scriem pentru a realiza aceste mapri, vom
arunca o privire n clasa RestApplication, mai exact asupra metodei createRoot():
public Restlet createRoot(){
Router router = new Router(getContext());
router.attach("/spaces", SpacesResource.class);
router.attach("/spaces/{spaceName}", SpaceResource.class);
router.attach("/spaces/{spaceName}/pages", PagesResource.class);
router.attach("/spaces/{spaceName}/pages/{pageName}",
PageResource.class);
router.attach("/spaces/{spaceName}/pages/{pageName}/history",
PageVersionsResource.class);

10

router.attach("/spaces/{spaceName}/pages/{pageName}/history/{version}",
PageVersionResource.class);
router.attach("/spaces/{spaceName}/pages/{pageName}/comments",
CommentsResource.class);

.............................................................................
Acest cod ruleaz la crearea unui obiect RestApplication. Se creaz o legtur simpl i intuitiv
ntre clasele resurselor i abloanele URI. Routerul din Restlet va face corespondena ntre URIurile primite de la clieni i abloanele noastre, i va nainta fiecare cerere unei noi instane ale
clasei resursei potrivite. Valorile variabilelor din URI sunt stocate ntr-un dicionar, atribut al
obiectelor de tip Request.
Dac avem un client care face o cerere GET asupra URI-ului
http://localhost:8080/xwiki/rest/spaces/AlexSpace/pages/MyPage. Avem o component care
ascult la portul 8080 i un obiect RestApplication care are un Router i mai multe obiecte Route
care ateapt cereri care vor corespunde unor abloane URI. URI-ul nostru
/spaces/AlexSpace/pages/MyPage se potrivete cu /spaces/{spaceName}/pages/{pageName} i
obiectul Route al ablonului este asociat clasei PageResource. Restlet trateaz cererea instaniind
un nou obiect PageResource i apelnd metoda handleGet. Constructorul clasei PageResource
este reprodus mai jos.
* Constructor.
*
* @param context The parent context.
* @param request The request to handle.
* @param response The response to return.
*/
public PageResource(Context context, Request request, Response response)
{
super(context, request, response);
this.spaceName = (String)
getRequest().getAttributes().get("spaceName");
this.pageName = (String) getRequest().getAttributes().get("pageName");
this.req = request;
getVariants().clear();
getVariants().add(new Variant(MediaType.TEXT_XML));
}

Restlet instaniaz un obiect Request, care conine toate informaiile necesare despre cererea
fcut. Atributele spaceName i pageName sunt luate din URI. Dup ce frameworkul instaniaz
un obiect PageResource, i invoc metoda handle pentru acest obiect. Exist cte o metod
handle pentru fiecare metod HTTP. n cazul nostru se apeleaz PageResource.handleGet, care
nu este definit n PageResource, astfel comportamentul motenit (definit n
Resource.handleGet) se execut. Comportamentul implicit pentru handleGet este de a gasi o
reprezentare a resursei care se potrivete cel mai bine cu nevoile clientului. Clientul i exprim
nevoile prin negocierea coninutului. Restlet observ valorile antetului Accept i alege
reprezentarea potrivit a resursei. n cazul nostru, suportm un singur format de reprezentare
(XML), astfel nu conteaz ce a cerut clientul. n constructor am definit text/XML ca fiind
11

singurul format de reprezentare suportat, iar implementarea metodei getRepresentation este


destul de simpl.
@Override
public Representation getRepresentation(Variant variant)
{
if (variant.getMediaType().equals(MediaType.TEXT_XML)) {
try {
DomRepresentation representation = new
DomRepresentation(MediaType.TEXT_XML);
Document d = representation.getDocument();
Element r = d.createElement(spaceName);
Element pg = d.createElement("page");
r.appendChild(pg);
d.appendChild(r);
XWiki xwiki = xwikicontext.getWiki();
com.xpn.xwiki.api.XWiki apiXwiki = new
com.xpn.xwiki.api.XWiki(xwiki, xwikicontext);
String pageFullName = String.format(FORMAT_STR, spaceName,
pageName);
try {
com.xpn.xwiki.api.Document doc =
apiXwiki.getDocument(pageFullName);
if (doc != null) {
populateXml(d, pg, doc);
} else {
getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
return null;
}
d.normalizeDocument();
return representation;
} catch (XWikiException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
}
}
getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
return null;
}

Aceasta este o singur metod a unei resurse, dar celelalte resurse i celelalte metode HTTP sunt
asemntoare. O cerere DELETE pentru o resurs este mapat unei metode
Resurs.handleDelete i aa mai departe.
n urma cererii fcute mai devreme, serverul ofer urmtoarea reprezentare:
<AlexSpace>
<page>
<title>This is my page</title>
<id>AlexSpace.MyPage</id>
<name>MyPage</name>
<space>AlexSpace</space>

12

<parent/>
<url>/xwiki/bin/view/AlexSpace/MyPage</url>
<content>Don't touch it.</content>
<creationDate>05-Ian-09</creationDate>
<date>05-Ian-09</date>
<contentUpdatedate>05-Ian-09</contentUpdatedate>
<author>XWiki.Admin</author>
<creator>XWiki.Admin</creator>
<lastVersion>1.3</lastVersion>
<tags/>
</page>
</AlexSpace>

Concluzii
Beneficiile utilizrii arhtecturii REST n dezvoltarea serviciilor web sunt multiple. Datorit
faptului c reprezentrile pot fi cache-uite timpul de rspuns al serverului i ncrcarea acestuia
sunt reduse. Scalabilitatea serverului este mbuntit reducndu-se nevoia ca serverul s
menin anumite stri care in de o sesiune. Astfel servere diferite pot fi folosite pentru a trata
diferite cereri dintr-o sesiune.
Codul de pe client este redus deoarece browserul poate fi folosit pentru a accesa orice resurs.
De asemenea, un serviciu web RESTful depinde mai puin de formate proprietare i de
frameworkuri de mesagerie deasupra HTTP.

Referine

Leonard Richardson, RESTful Web Services, O'Reilly, 2007


http://restpatterns.org/

http://rest.blueoxen.net

13

S-ar putea să vă placă și