You are on page 1of 20

Web servisi Java vs .

NET
Tomislav Jakupi
Koprivnica, 07.11.2009

Uvod u Web servise


World Wide Web Consortium (http://www.w3.org) definira Web servis (Web service) kao softverski sustav koji podrava funkcionalnu interakciju meu raunalima preko mree. Suelje takvog sustava opisano je u raunalu prijateljskom formatu (WSDLu - Web Services Description Language). Ostali sustavi komuniciraju s Web servisom na nain propisan spomenutim opisom, koristei SOAP (Simple Object Access Protocol) preko HTTPa i uz serijalizaciju XMLa. Unato danoj definiciji W3Ca koja je dosta konkretna, openito moemo rei da je izraz 'Web servis' jo uvijek dosta neodreen, nedovoljno definiran i njegovo znaenje se jo uvijek razvija. No kada govorimo o Web servisima u naelu govorimo o klijentima i serverima koji najee komuniciraju preko HTTPa (Hypertext Transfer Protocol) odnosno Weba. Moemo rei da su Web servisi zapravo Internet APIji (Application Programming Interfaces) ili distribuirane aplikacije kojima se pristupa preko mree i koji se izvravaju na udaljenom raunalu na kojem Web servis egzistira, a mogu im pristupiti razni ureaji (npr. raunalo, mobitel itd.). Tu moemo spomenuti i druge poznate pristupe koji imaju slinu funkcionalnost kao npr. OMGova (Object Management Group) Common Object Request Broker Architecture (CORBA), Microsoftov Distributed Component Object Model (DCOM) ili Sunov Java Remote Method Invocation (RMI). Web servisi se mogu podjeliti u grubo u dvije skupine: Web servisi bazirani na SOAPu opisani su definicijom W3Ca RESTful (REpresentational State Transfer) Web servisi u zadnje vrijeme dobivaju na popularnosti. Ovakvi Web servisi su bolje usklaeni s HTTPom i Web preglednicima, budui da koriste standardne POST, PUT, GET i DELETE HTTP metode. Ne zahtjevaju XML (odnosno SOAP) za komunikaciju ni WSDL opise. Podjela nije u potpunosti jasna, budui da su Web servisi bazirani na SOAPu zapravo specijalni sluaj RESTful Web servisa. Originalno SOAP je znaio Simple Object Access Protocol, no verzijom 1.2 znaenje akronima je naputeno i sada je samo SOAP. Zbog slinosti akronima mogli bismo ga zamjeniti sa Service Oriented Architecture (SOA) Protokolom. SOA nije jednostavan pojam i kasnije emo ga detaljnije opisati, ali to god to bilo, moemo zakljuiti iz samog naziva da su servisi okosnica S(ervice)OA pristupa razvoja aplikacija. Pomou SOAP baziranih servisa moemo implementirati SOA koncepte, gdje je osnova komunikacije poruka, a ne operacija. Dakle, SOAP i SOA su razliite stvari, ali njihova povezanost postoji. U uobiajenom scenariju razmjene poruka (ili tzv. uzorku razmjene poruka (message exchange pattern MEP) gdje imamo zahtjev (request) i odgovor (response), na nioj razini apstrakcije, klijentove SOAP biblioteke alju SOAP poruku kao zahtjev za uslugom (service request), a na strani Web servisa SOAP biblioteke alju SOAP poruku odgovora (service response). U ovom scenariju, klijentu i Web servisu SOAP infrastruktura je praktiki nevidljiva i moemo rei nebitna, ali osigurava uspjenu komunikaciju.

Klijent Web servisa

SOAP Web servis

Zahtjev za uslugom SOAP Biblioteke Odgovor SOAP Biblioteke

Za razliku od SOAP baziranih Web servisa koje karakterizira postojanje standarda (odrava ga W3C), mnogo skupova alata i softverskih biblioteka, REST bazirani Web servisi nisu standardizirani i nemaju toliko alata niti softverskih bibilioteka. REST se smatra svojevrsnim protuotrovom za rastuu sloenost SOAP baziranih Web servisa. Osim vjerojatno za vrijeme testiranja, klijent SOAP ili REST baziranih Web servisa je najee aplikacija bez grafikog suelja koja moe biti napisana u bilo kojem programskom jeziku ili razvijena u bilo kojem razvojnom okruenju. Transparentnost s obzirom na programski jezik je klju i najvanija karakteristika servisa. Ako je Web servis napisan u Javi, a koristi ga aplikacija napisana u Perlu, mora postojati posrednik koji e neutralizirati razlike u tipovima podataka izmeu razliitih programskih jezika. Tu dolaze na scenu XML tehnologije kao tehnologije za opis podataka i razmjenu dokumenata, a preuzimaju zadau posrednika. Kod SOAP servisa SOAP poruke (zahtjev i odgovor) su XML dokumenti. Kod REST Web servisa klijent moe poslati standardni HTTP zahtjev, a dobiti isti XML ili SOAP dokument kao odgovor. Karakteristike koje odjeljuju Web servise od ostalih distribuiranih softverskih sustava, poput spomenutih CORBAe, DCOMa ili RMIa su: Otvorena infrastruktura Web servisi su bazirani na HTTP, XML i ostalim protokolima koji su poznati i prihvaeni Transparentnost s obzirom na programski jezik Modularni dizajn Web servisi se trebaju razvijati modularno, tako da se na temelju postojeih servisa mogu generirati novi Iz navedenog lako moemo doi do zakljuka zato uope trebamo Web servise. Prvi i najoitiji odgovor je interoperabilnost softverskih sustava na razliitim raunalima i platformama, pisanim u razliitim programskim jezicima, te njihova dostupnost standardnim i opepoznatim komunikacijskim protokolima. Web servisi su dakle distribuirani sustavi koji (obino) komuniciraju preko HTTPa, ali mogu komunicirati i preko ostalih poznatih protokola. Sadraj komunikacije je strukturirani tekst, odnosno XML dokumenti, koji se mogu analizirati, transformirati, spremati ili obraivati na druge naine. Ako se ukae potreba kada sustav zahtijeva veu efikasnost, Web servisi mogu isporuiti i podatke u binarnom obliku. Naposlijeku, podruje Web servisa je u konstantnom razvoju, a stvarni svijet je mjesto gdje se Web servisi razvijaju upravo sada, pa je vano znati neto o ovoj temi.

Web servisi u Javi


Java platforma podrava razvoj Web servisa kroz JAX-WS (Java API for XML-Web Services), bilo da se radi o SOAP ili REST baziranim Web servisima. Takoer treba spomenuti projekt Jersey dodatno samo za razvoj REST baziranih Web servisa, slubeno nazvan JAX-RS (Java API for XML-RESTful Web Services). JAX-WS je dio Metro Web Services Stacka, ili krae Metro. Osnovni dio Metroa je sadran u Java 6 Standard Ediciji. Meutim, Metro sadri puno vie nego je ukljueno u Java 6 SE, pa se moe i zasebno skinuti (https://wsit.dev.java.net). Takoer, Metro je integriran u Sunovu aplikacijskom serveru pod imenom GlassFish. Uzevi u obzir reeno, Web servis moe biti razvijen kao dio jednog od sljedeih scenarija: Samo Java SE okruenje koja nam omoguava brzo i jednostavno postavljanje Web servisa i klijenata. Preduvjet je Java 6 SE SDK. Java u kombinaciji s punom verzijom Metroa ova platforma nam omoguuje koritenje naprednijih mogunosti Metroa koji nisu dio Java 6 SE platforme. U kombinaciji s punom verzijom Metroa, moemo koristiti i Java SE verziju 5. Tomcat Web kontejner radi se o samostalnom Java Web kontejneru koji nam omoguuje postavljanje Web servisa slino kao i obinih servleta, JSP ili JSF stranica. Aplikacijski posluitelj kao npr. GlassFish postavljanjem Web servisa unutar GlassFish aplikacijskog servera servisu omoguujemo interakciju s drugim komponentama u vieslojnoj Java EE arhitekturi (JMS, JNDI, EIS slojem, EJBima itd.). JAX-WS specifikacija omoguuje da se jednom razvijeni Web servis moe postaviti u bilo kojem od navedenih scenarija. Za potrebe izlaganja mi emo razviti Web servis samo koristei Java SE okruenje.

Web servisi u .NETu


Od izdavanja .NET Frameworka verzije 3.0 Microsoft je uveo novi nain razvoja Web servisa pomou skupa alata WCF (Windows Communication Foundation). Do tog trenutka nije bio jednostavan zadatak razvijati takve aplikacijske komponente koje e meusobno komunicirati porukama upravo zbog injenice to je Microsoft nudio vie tehnologija za tu namjenu, izmeu ostalog ASP.NET Web Services, Web Service Enhancements 3.0 (WSE), MSMQ, Enterprise Services, .NET Remoting, te System.Messaging namespace. Upravo zbog toga to je programeru na raspolaganju mnogo tehnologija, svaka sa svojim pozitivnim i negativnim stranama, teko odluiti koju odabrati u odreenoj situaciji. U tu svrhu je napravljen WCF. WCF je zapravo cjelovita jedinstvena platforma koja omoguuje izradu ranije spomenutih SOA aplikacija, odnosno servisa kao osnove SOA arhitekture.

Service Oriented Architecture


SOA (Service Oriented Architecture) je arhitektura neovisna o platformi orjentirana servisima baziranim na principu razmjene poruka. Kao rezultat toga unutar sustava se razmjenjuju poruke, a te iste poruke se mogu koristit unutar drugih sustava koji bi inae meusobni bili nespojivi. Kada gledamo unatrag, moemo uoiti postpuno sazrijevanje prema SOA modelu. Osamdesetih godina prolog stoljea dogodila se revolucija u obliku objektno-orjentiranog modela, gdje je sve bilo objekt. S dolaskom objektno-orjentiranog modela, njegovi principi su iroko prihvaeni kao pravi nain modeliranja entiteta u domeni razvoja aplikacijskih sustava. Devedesetih godina je napravljen jo jedan korak naprijed, a to je tzv. componentoriented model odnosno model orjentiran komponentama. Ovaj model omoguio je uahurivanje usko povezanih objekata unutar neovisnih komponenata. Nedugo zatim je napravljen iskorak prema SOA modelu i to zbog toga to su se developeri i arhitekti sreli sa potrebom da komponente distribuiraju tako da budu dostupne onima kome su potrebne bez obzira na razlike u platformi, arhitekturi itd.. Preduvjet za ovakav sustav je uspjena razmjena poruka izmeu meusobno nekomaptibilnih strojeva, a uz to poruke trebaju ukljuiti nekakve dodatne podatke (metadata) koji opisuju nain na koji se poruke mogu koristiti. Jedan od osnovnih principa SOA pristupa jest da su granice prilikom razvoja strogo postavljene. To znai da izvori podataka, programska logika ili entiteti koriste suelja da bi preko njih podatke ili usluge pruili vanjskom svijetu. Suelja dakle omoguuju da se sakrije unutarnje funkcioniranje servisa prema vanjskom svijetu, a isto tako omoguuju da se unutarnja logika promjeni bez ikakvog utjecaja na korisnike servisa. Servisi su autonomni entiteti. Pojedinani servisi se auriraju neovisno jedni od drugih. To znai da sustav, koji je sastavljen od vie servisa, ne aurira se kao cjelina, ve se pojedini servisi auriraju neovisno i ne trebaju ekati jedni na druge. Servisi su bazirani na ugovorima, odnosno svi servisi imaju svoj ugovor koji definira to je potrebno da bi klijenti konzumirali objavljene usluge (obino se realizira kroz WSDL dokumente) i klijenti moraju prihvatiti taj ugovor da bi mogli koristiti servis. Ugovore nadopunjuju sheme (schemes) koje detaljno definiraju podatke koji se alju kao argumenti servisu ili vraaju kao rezultati obrade.

Osnove XML
XML (Extensible Markup Language) je jezik odnosno specifikacija koja daje niz pravila za kodiranje elektronikih dokumenata. Ciljevi specifikacije su jednostavnost, openitost i upotrebljivost preko Interneta. Format podataka je tekstualan s jakom podrkom za koritenje Unicode-a, pa tako i za sve jezike diljem svijeta. Iako su primarni fokus XMLa dokumenti, iroko je rasprostranjen u prikazu svih oblika podataka, pa tako i kod Web servisa. Osnovne sastavnice XML dokumenta su: oznake (markup) i sadraj. Oznake uvijek poinju s '<' i zavravaju s '>', ili poinju s '&' i zavravaju s ';'. Sve ostalo je sadraj. Oznake moemo podijeliti u: oznake (u uem smislu) tag-ovi (<test>, </test> ili <test />), elemente (<element>sadraj</element>), atribute (<element atribut=vrijednost>sadraj</element>), deklaracije (<?xml version="1.0" encoding="UTF-8" ?>). XML dokument mora biti dobro oblikovan (well-formed) za to postoji niz pravila, od kojih nabrajamo samo vanija: (1) dokument sadri samo ispravno kodirane dozvoljene Unicode znakove, (2) u sadraju se ne pojavljuju rezervirani znakovi (>, <, ;, &), (3) poetni, zavrni i prazni tagovi moraju biti ispravno ugnjeeni, ne smije nedostajati tag ili se preklapati, (4) nazivi tagova su osjetljivi na velika i mala slova, (5) postoji samo jedan korjenski root element koji sadri sve ostale. Uz to to mora biti dobro oblikovan, XML dokument moe biti i valjan (valid). U tom sluaju mora postojati dodatna datoteka u obliku DTDa (Document Type Definition) ili XML Schema-e u kojem se nalazi toan opis strukture dokumenta u specifinom formatu. DTD je najstariji jezik za opis strukture XML dokumenta. Njegov nasljednik je XML Schema, odnosno XSD (XML Schema Definition). XSD je mnogo moniji od DTDa, posebno zato to mu je sustav za opis tipova podataka mnogo iri i bogatiji, omoguuje postavljanje detaljnijih ogranienja na XML dokumente, a osim toga XSD dokumenti su formatirani kao XML dokumenti pa se i lake obrauju. XML namespace-i koriste se za jedinstveno imenovanje elemenata i atributa u XML dokumentu. Jedna XML instanca (dokument) moe sadravati imena elemenata ili atributa iz vie razliitih XML vokabulara (skupova dokumenata). Namespace-i spreavaju koliziju naziva elemenata i atributa, odnosno omoguuju postojanje istih naziva unutar razliitih vokabulara i njihovo paralelno koritenje. Namespace se u dokumentu definira atributom xmlns, odnosno xmlns:klju, a vrijednost atributa je obino URI (Uniform Resource Identifier). Kljuem se onda kasnije naznauju elementi i atributi koji pripadaju konkretnom namespace-u na nain klju:element ili klju:atribut. Namjena URIa nije da bi se dohvatio nekakv dokument, to se moda moe zakljuiti budui da se uglavnom radi o Web adresama, ve da jednoznano identificira namespace na nain itljiv ljudima, ali opet da smanji mogunost pojave istih identifikatora. U daljnjim primjerima esto emo se susretati s XML namespace-ima.

Implementacija Web servisa u Java tehnologijama


Za prikaz principa kod razvoja Web servisa razvit emo jednostavan SOAP Web servis koristei samo Java 6 platformu koja ima ugraenu podrku za ve spomenuti Java API for XML-Web Services, odnosno JAX-WS. Pratei najbolju praksu za razvoj Web servisa implementacija se sastoji od dva dijela: suelje Web servisa - SEI (Service Endpoint Interface) implementacija Web servisa SIB (Service Implementation Bean) Web servis emo implementirati u obliku obine Java klase (POJO Plain Old Java Object) Suelje Web servisa SEI
package servisi.primjer1; import import import import javax.jws.WebService; javax.jws.WebMethod; javax.jws.soap.SOAPBinding; javax.jws.soap.SOAPBinding.Style;

@WebService @SOAPBinding(style = Style.RPC) public interface VremenskiServer { @WebMethod String getVrijeme(); }

Objanjenje: anotacija @WebService naznauje da je Java suelje SEI (Service Endpoint Interface). Anotacija @WebMethod naznauje da je metoda suelja getVrijeme() operacija servisa koju e klijenti moi pozivati. @SOAPBinding anotacija definira nain funkcioniranja servisa i postavke u WSDLu, odnosno sporazumu kojega moraju prihvatiti svi klijenti koji ele koristiti servis. Style.RPC koja nam trenutno najbolje odgovara, a o emu emo detaljnije govoriti kasnije. Implementacija Web servisa SIB
package servisi.primjer1; import java.util.Date; import javax.jws.WebService; @WebService(endpointInterface = "servisi.primjer1.VremenskiServer") public class VremenskiServerImpl implements VremenskiServer { public String getVrijeme() { return new Date().toString(); } }

Objanjenje: anotacija @WebService i njena varijabla endpointInterface u ovom sluaju slue za povezivanje SIB (Service Implementation Bean) sa sueljem (SEI). Web metoda se ne naznauje posebno.

Nakon to smo implementirali SEI i SIB moramo objaviti Web servis kako bi ga klijenti mogli koristiti. Objavu vrimo na sljedei nain:
Endpoint.publish("http://127.0.0.1:9876/vrijeme", new VremenskiServerImpl ());

Statika metoda publish klase javax.xml.ws.Endpoint uzima dva argumenta. Prvi argument je adresa na kojoj emo objaviti na servis i preko koje e klijenti pristupati servisu. Adresa, kao to je vidljivo sadri IP adresu (ili naziv) servera, port i proizvoljnu putanju /vrijeme. Drugi argument je instanca naeg SIBa. WSDL ovog Web servisa ne moramo sami pisati ve se on automatski generira i moemo mu pristupiti preko adrese http://127.0.0.1:9876/vrijeme?wsdl gdje moemo usput i testirati servis. Klijentski kod moemo generirati automatski pomou alata wsimport koji dolazi kao dio Java 6 SE SDK paketa. Nalazi se obino u direktoriju C:\Program Files\Java\ jdk1.6.0_14\bin. Kao argument programu stavljamo datoteku WSDLa na temelju kojega alat generira suelje servisa (SEI) i kod potreban za pozivanje udaljenih operacija servisa.

WSDL
U poslovnom svijetu ugovor je obvezujui sporazum izmeu dvije ili vie strana koji specificira isporuku dobara ili usluga za neku cijenu. U svijetu servisa vrijedi zapravo isto, odnosno to je sporazum izmeu dvije ili vie strana koji specificira razmjenu poruka i uvjete koje poruke moraju zadovoljavati. Taj ugovor u svijetu servisa predstavlja WSDL dokument. On daje vane informacije o krajnjim tokama servisa, operacijama servisa i tipovima podataka vezanim za te operacije. Sada emo malo pogledati strukturu WSDL na naem primjeru:
<?xml version="1.0" encoding="UTF-8" ?> <definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="http://primjer1.servisi/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://primjer1.servisi/" name="VremenskiServerImplService"> <types /> <message name="getVrijeme" /> <message name="getVrijemeResponse"> <part name="return" type="xsd:string" /> </message> <portType name="VremenskiServer"> <operation name="getVrijeme" parameterOrder=""> <input message="tns:getVrijeme" /> <output message="tns:getVrijemeResponse" /> </operation> </portType>

<binding name="VremenskiServerImplPortBinding" type="tns:VremenskiServer"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" /> <operation name="getVrijeme"> <soap:operation soapAction="" /> <input> <soap:body use="literal" namespace="http://primjer1.servisi/" /> </input> <output> <soap:body use="literal" namespace="http://primjer1.servisi/" /> </output> </operation> </binding> <service name="VremenskiServerImplService"> <port name="VremenskiServerImplPort" binding="tns:VremenskiServerImplPortBinding"> <soap:address location="http://127.0.0.1:9876/vrijeme" /> </port> </service> </definitions>

Korjenski element WSDL dokumenta je definitions element. WSDL daje definicije grupirane u sljedee sekcije: Sekcija types nije obavezna, sadri definicije sloenih tipova podataka ako postoje i to najee u obliku XSDa (XML Schema Definition). Ovaj dio moemo jo nazvati i podatkovnim ugovorom (data contract). Ova sekcija dakle sadri ili ukazuje na vanjski XSD. Ako je sekcija prazna, kao to je u naem primjeru, servis koristi samo jednostavne tipove podataka kao to je i xsd:string. Sekcija messages definira poruke koje se pojavljuju kod servisa. Poruke sadre tipove podataka definirane u prethodnoj sekciji, ili ako je ona prazna, sadre standardne tipove podataka. Nadalje, redoslijed poruka (kasnije definiran u sekciji portType) ukazuje na to kakav je uzorak funkcioniranja servisa. Naznaene su, iz gledita servisa, ulazne (input) i izlazne (output) poruke. Ako je redoslijed poruka in / out, tada se radi o standardnom request/response uzorku, a ako je redoslije obrnut radi se o tzv. solicit/response uzorku u kojem servis inicira komunikaciju, a klijent alje odgovor. Sekcija portType prezentira servis kao imenovane operacije, a svaka operacija opisana je jednom ili vie poruka. Operacije nose ime kao metode oznaene anotacijom @WebMethod. U naem primjeru u odjeljku portType grupirane su operacije koje Web servis nudi, u naem sluaju to je jedna operacija getVrijeme deklarirana u suelju Web servisa (SEI), a implementirana u SIBu. Odjeljak portType je zapravo slian SEIu po tome to daje apstraktni prikaz operacija koje nudi servis, bez implementacije koja se nalazi na drugom mjestu. Za svaku operaciju definirani su elementi input i output s atributom message, a predstavljaju (ranije definirane u sekciji messages) ulazne, odnosno izlazne poruke za konkretnu operaciju servisa. Kod izvravanja te su poruke SOAP dokumenti. O redoslijedu poruka smo govorili u sekciji messages. Sekcija binding u ovom dijelu se konkretiziraju WSDL definicije. Kao to je portType srodan suelju servisa, tako je binding srodan implementaciji servisa. Kao to SIB daje konkretne informacije o servisu, tako i sekcija binding ima istu funkciju u WSDLu. Ova je sekcija najkompliciranija jer mora dati implementacijske detalje servisa prethodno apstraktno definiranog u sekciji portType, a to su: (1) transportni protokol koji e se koristiti za slanje i primanje SOAP poruka. U aplikacijskom sloju (OSI model) to moe biti HTTP ili SMTP 9

(Simple Mail Transport Protocol). HTTP je daleko najpopularniji. WSDL u naem primjeru sadri sljedeu liniju koja definira transportni protokol: <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" />. Sljedea stvar koju treba definirati je (2) style atribut. On moe poprimiti dvije vrijednosti i to: document ili rpc. Ako drugaije ne specificiramo vrijednost parametra je uvijek document, zbog ega smo u kodu eksplicitno definirali kao rpc (sjetimo se linije: @SOAPBinding(style = Style.RPC)). Ako je stil document poruke sadre cjelovite (XML) dokumente (kao npr. narudbe), dok rpc implicira da e poruka sadravati ili parametre ili povratne vrijednosti obrade (kao to je u naem primjeru sluaj). Na kraju moramo definirati (3) format podataka u SOAP porukama (use atribut soap:body elementa). Postoje dvije mogunosti: literal i encoded. literal implicira da je informacija u poruci doslovno onakva kao to je definirano u XML shemi u types sekciji. encoded implicira da je informacija u poruci dodatno kodirana SOAP pravilima kodiranja ili nekim drugim pravilima kodiranja. Sekcija service specificira jednu ili vie krajnjih toaka (endpoint) na kojima su dostupne operacije servisa. Krajnje toke su specificirane u obliku port elemenata, a za svaki port elemenat imamo prateu definiciju bindinga, te preko bindinga i definiciju portType-a (suelja).

Budui da je WSDL ugovor koji klijent mora prihvatiti da bi mogao koristiti Web servis, on je osnova za izradu klijenta. Iz WSDLa klijent moe zakljuiti osnovne informacije, ukljuujui i tipove podatake, koje e mu trebati za pristup i koritenje servisa. Iz naeg WSDLa klijent moe zakljuiti da imamo operaciju getVrijeme, koja ne oekuje argumente i vraa znakovni niz kao rezultat. Svaki programski jezik nudi alat koji moe generirati kod za pristup pojedinom servisu iz WSDL dokumenta. Kod Jave taj alat se zove wsimport. Klijent Web servisa
package servisi.primjer1; import javax.xml.namespace.QName; import javax.xml.ws.Service; import java.net.URL; class VremenskiKlijent { public static void main(String args[ ]) throws Exception { URL url = new URL("http://localhost:9876/vrijeme?wsdl"); QName qname = new QName("http://primjer1.servisi/", "VremenskiServerImplService"); Service service = Service.create(url, qname); VremenskiServer eif = service.getPort(VremenskiServer.class); System.out.println(eif.getVrijeme()); } }

Objanjenje: prvi korak je definiranje URL adrese WSDLa za na servis. URL objekt e nam kasnije biti potreban za definiranja reference prema servisu. Nakon toga nam je potrebno XML kvalificirano ime Web servisa (XML namespace) u obliku objekta Qname iji konstruktor prihvaa dva argumenta i to URI Web servisa i ime Web servisa; oboje je definirano u WSDLu. Razlika izmeu pojma URL (Uniform Resource Locator) i URI (Uniform Resource Identifier) je u tome to URL obavezno specificira lokaciju, a URI ne 10

nuno. Kada imamo URL i kvalificirano ime Web servisa moemo deklarirati objekt klase Service pomou statike metode create koja kao argumente uzima spomenute objekte. Ovaj objekt predstavlja na servis kao resurs. On moe imati jednu ili vie krajnjih toaka (port-ova). (Jedina) krajnja toka naeg servisa je objekt tipa VremenskiServer, to je u kodu zapravo Java suelje servisa SEI. Objekt kreiramo metodom getPort naeg objekta service. Iako objekt ima tip Java suelja u kojem je definiran samo predloak metoda, sam objekt sadri sve to mu je potrebno za pozivanje operacija koje su definrane u WSDLu u odjeljku portType, a o tome se brine metoda getPort. Nakon toga moemo pozvati nau operaciju kao metodu svakog drugog objekta.

SOAP poruke
Sada emo pogledati to se dogaa ispod haube, odnosno kakve poruke razmjenjuju klijent i Web servis. Budui da smo napravili SOAP bazirani Web servis razmjenjuju se SOAP poruke. SOAP inae dolazi u dvije verzije 1.1 i 1.2. Razlike su u pravilu minorne za programera Web servisa. Struktura standardne SOAP poruke prikazana je na sljedeoj slici: SOAP Poruka
(Opcionalno) SOAP zaglavlje

SOAP Omotnica

(Obavezno) SOAP tijelo

(Opcionalni) SOAP privici

SOAP omotnica (Envelope) je korjenski element SOAP poruke.


<?xml version="1.0"?> <soap:Envelope xmlns:soap="http://www.w3.org/2001/12/soap-envelope" soap:encodingStyle="http://www.w3.org/2001/12/soap-encoding"> ... </soap:Envelope>

Ovaj element definira XML dokument kao SOAP poruku. Element Envelope sadri najee dva atributa i to: xmlns:soap="http://www.w3.org/2001/12/soap-envelope" ovaj atribut mora uvijek biti prisutan. Ovdje definiramo namespace pod kljuem soap (moe biti i

11

neki drugi, npr. soapenv, S). To je klju koji emo kasnije koristiti kao prefiks elementima i atributima koji pripadaju SOAP vokabularu. Iz URI-a vidimo da se jasno radi o SOAPu. soapenv:encodingStyle="http://www.w3.org/2001/12/soap-encoding" ovaj atribut se moe i ne mora pojaviti i definira tipove podataka koritene u dokumentu. U ovom primjeru odabrano je standardno SOAP kodiranje, definirano URI-em.

SOAP zaglavlje (Header) ako postoji mora biti prvi element u SOAP omotnici i definira aplikaciji specifine informacije o SOAP poruci. U elementima unutar SOAP zaglavlja mogu se pojaviti tri karakteristina atributa: soap:mustUnderstand, soap:actor i soap:encodingStyle. mustUnderstand moe imati vrijednost 0 ili 1, moe se primjeniti na sam Header element ili elemente koje sadri, a znai da li je primatelj duan (1) ili ne (0) obraditi, odnosno prepoznati dotini element i sve to je sadrano u njemu. actor atribut se koristi za adresiranje elemenata specifinom primatelju, budui da ista SOAP poruka moe proi preko nekoliko toaka na svom putu. Vrijednost atributa je URI. encodingStyle ima jednaku primjenu kao i kod SOAP omotnice. SOAP tijelo poruke (Body element) sadri konkretnu SOAP poruku namjenjenu krajnjoj toci. Elementi i atributi koje Body element sadri mogu biti kvalificirani raznim namespace-ima. Body element moe opcionalno sadravati jedan Fault element u kojem su naznaene greke. U naem primjeru klijent alje poruku zahtjeva u obliku HTTP zahtjeva u ijem tijelu je SOAP poruka.
POST http://127.0.0.1:9876/vrijeme HTTP/1.1 Accept-Encoding: gzip,deflate Content-Type: text/xml;charset=UTF-8 SOAPAction: "" User-Agent: Jakarta Commons-HttpClient/3.1 Host: 127.0.0.1:9876 Content-Length: 222 <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:prim="http://primjer1.servisi/"> <soapenv:Header/> <soapenv:Body> <prim:getVrijeme/> </soapenv:Body> </soapenv:Envelope>

HTTP zahtjev ima svoj karakteristini format. Prva linija zahtjeva definira HTTP metodu, u ovom sluaju je to POST metoda, to je uobiajeno za zahtjeve koji se alju dinamikim resursima i Web servisima. U ovom sluaju je POST obavezan i ne moemo korisiti GET metodu. Razlog je taj to u tijelu HTTP zahtjeva aljemo SOAP poruku, a to nam omoguuje samo POST metoda, za razliku od GET metode koja ne sadri tijelo tijelo. Nakon toga, u prvoj liniji slijedi adresa resursa i verzija HTTP protokola. Nakon prve linije slijede HTTP zaglavlja, odnosno parovi kljueva i vrijednosti odvojenih dvotokom (:). Redoslijed zaglavlja nije bitan. Ponekad HTTP zahtjev moe imati Accept klju s raznim vrijednostima. Ova zaglavlja slue tome da obavijeste primatelja (Web servis) koje formate odgovora je poiljatelj (klijent Web servisa) spreman prihvatiti. Format je opisan MIME (Multiple Internet Mail Extension) kombinacijama tipova i podtipova odvojeno kosom crtom (npr. text/xml zna i

12

da je prihvatljiv bilo kakav XML dokument; application/soap znai da je prihvatljiv SOAP dokument). Klju SOAPAction se esto moe nai u HTTP zaglavljima zahtjeva prema Web servisima i vrijednost moe biti prazna, ali ovdje moe biti i operacija Web servisa koju pozivamo. Na strani Web servisa se HTTP zahtjev obrauje na nain da se izdvoji SOAP dokument, iz njega se izdvoji identifikator operacije Web servisa koju klijent poziva, poziva se konkretna metoda u programskoj logici Web servisa i na temelju rezulata te metode se formira HTTP poruka odgovora koja sadri SOAP poruku. U nastavku slijedi poruka odgovora iz naeg primjera.
HTTP/1.1 200 OK Transfer-encoding: chunked Content-type: text/xml;charset="utf-8" <?xml version="1.0" ?> <S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"> <S:Body> <ns2:getVrijemeResponse xmlns:ns2="http://primjer1.servisi/"> <return>Sat Oct 31 19:28:53 CET 2009</return> </ns2:getVrijemeResponse> </S:Body> </S:Envelope>

Kao to je reeno odgovor je HTTP poruka odgovora koja u tijelu sadri SOAP poruku odgovora. Prva linija HTTP poruke je statusna linija koja se sastoji od verzije HTTP protokola, statusnog koda i prateeg teksta. '200 OK' znai da je klijentov zahtjev uspjeno obraen. Slijedi nekoliko linija zaglavlja. SOAP poruka u tijelu HTTP zahtjeva sadri odgovor Web servisa na klijentov zahtjev u formatu koji e klijentu biti poznat, kako je i predvieno sklopljenim ugovorom meu klijentom i servisom (WSDL).

13

Terminologija WCFa
Implementacija Web servisa pomou WCFa je prilino jednostavna. Za to nam je potreban .NET Framework minimalno verzije 3.0 i Visual Studio 2008 ili pak Visual Studio 2005 plus dodatak .NET Framework 3.0. WCF servis sastoji se od 3 dijela: (1) servisa, (2) jedne ili vie krajnjih toaka (endpoint) i (3) okruenje u kojem pruamo servis. Servis je zapravo klasa napisana u .NET kompatibilnom programskom jeziku. Klasa sadri jednu ili vie metoda koje su dostupne kroz WCF servis. Servis isto tako moe imati jednu ili vie krajnjih toaka koje predstavljaju komunikacijski kanal klijenta prema servisu. Krajnja toka servisa je resurs na mrei kojemu klijenti mogu poslati poruku formatiranu na nain utvren ugovorom sklopljenim izmeu servisa i klijenta. Da bi klijent uspjeno poslao poruku na krajnju toku servisa, treba znati tri elementa koji odreuju krajnje toke. Ove elemente Microsoft naziva akronimom ABC, a to su: A = address, adresa definira mjesto na mrei gdje klijent treba poslati poruku. B = binding, poveznica definira kanal koji se koristi sa komunikaciju s krajnjom tokom. Kanali su vodovi kroz koje prolaze sve poruke unutar WCF aplikacije. Kanal je sastavljen od niza binding elemenata. C = contract, ugovor - definira mogunosti i opcije koje nudi krajnja toka, odnosno operacije koje nudi i format poruka koje zahtijeva. U ugovoru su pojedine operacije povezane s metodama klase koja implementira krajnju toku, a definirani su i parametri koji se alju kao ulaz i izlaz. Ovo isto moemo opisati na sljedei nain: A je gdje, B je kako, a C je to. WCF sustav moemo prikazati sljedeom slikom. Budui da je tok poruka u pravilu obosmjeran, klijenti takoer implicitno predstavljaju krajnju toku.

WCF klijent Krajnja toka C B A Poruke

WCF servis Krajnja toka A B C Krajnja toka A B C Krajnja toka A B C

14

Na kraju, okruenje u kojem pruamo servis je mjesto gdje se servis nalazi kada je u pogonu. Okruenje sainjava aplikacijska domena i proces u kojem servis egzistira na operacijskom sustavu. Domain WCF servisu moe biti bilo koji samostalan proces, Web posluitelj, klijentska desktop aplikacija itd. Da bi servis bilo mogue otkriti dinamiki, servis moe ukljuiti tzv. infrastrukturnu krajnju toku koja se naziva Metadata Exchange (MEX) krajnja toka. Ova toka je dostupna klijentima i preko nje mogu dohvatiti ABCove servisa u obliku WSDL dokumenta. MEX krajnja toka se poziva kada u Visual Studiu dodajemo referencu prema servisu (Add Service Reference) ili kada koristimo alat svcutil.exe za automatsko generiranje klijentskog koda (slian alat ima i Java). MEX krajnja toka, kao to je reeno, vraa WSDL i na temelju njega se automatski generira klijentski kod (proxy klasa s potpisom operacija koje nude krajnje toke) i potrebne konfiguracijske datoteke.

Implementacija SOAP Web servisa pomou WCFa


Na najvioj razini, implementirati Web servis znai napisati kod koji implementira nekakvu mogunost, taj kod postavimo u proces operacijskog sustava, i nakon pokretanja proces eka na zahtjeve i daje odgovore klijentima. U praksi, to znai napisati .NET klase i, slino kao to smo u Java klasama kljuna mjesta naznaili s odgovaraju im anotacijama, tako i ovdje na kljuna mjesta postavimo odgovarajue atribute iz System.ServiceModel namespace-a. Prvo emo implementirati ugovor WCF servisa.
using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.ServiceModel;

namespace WCFServis { [ServiceContract] interface IVremenskiServer { [OperationContract] string getVrijeme(); } }

Objaenjenje: kao i kod Java programskog jezika servis zapoinjem implementacijom suelja odnosno ugovora u dijelu programiranja. Suelje koje predstavlja ugovor naznaujemo atributom [ServiceContract]. S gledita WSDL dokumenta ovaj atribut definira portType element. [OperationContract] atribut oznauje metode koje se mogu pozivati kroz suelje Web servisa. S gledita WSDLa [OperationContract] definira Operation i Message elemente.

15

using using using using

System; System.Collections.Generic; System.Linq; System.Text;

namespace WCFServis { class VremenskiServer : IVremenskiServer { public string getVrijeme() { return new DateTime.UtcNow.ToString(); } } }

Objanjenje: nakon to smo napravili suelje, moramo ga poduprijeti implementacijom poslovne logike. Izraujemo klasu koja implementira suelje gdje konkretiziramo nau metodu koja e biti na raspolaganju klijentima kroz Web servis.
using using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.ServiceModel; System.ServiceModel.Description;

namespace WCFServis { class PokreniVremenskiServer { public static void Main() { ServiceHost serviceHost = new ServiceHost(typeof(VremenskiServer), new Uri("http://127.0.0.1:9876/vrijeme")); serviceHost.AddServiceEndpoint(typeof(IVremenskiServer), new BasicHttpBinding(), ""); ServiceMetadataBehavior behaviour = new ServiceMetadataBehavior(); behaviour.HttpGetEnabled = true; serviceHost.Description.Behaviors.Add(behaviour); serviceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex"); serviceHost.Open(); Console.WriteLine("Pritisni <ENTER> za kraj.\n\n"); Console.ReadLine(); serviceHost.Close(); } } }

Objanjenje: kada smo implementirali servis u potpunosti (suelje i implementacija suelja) moemo pristupiti definiranju krajnje toke. Kao to je ranije prikazano, krajnju toku definiramo akronimom ABC (Address, Binding, Contract). U tu svrhu emo koristiti klasu ServiceHost i prvenstveno metodu AddServiceEndpoint. ServiceHost klasu, odnosno instance te klase, koristimo kada elimo konfigurirati i izloiti servis tako da ga klijenti mogu koristiti, ali bez upotrebe IISa (Internet Information Services). U naem sluaju pri instanciranju ServiceHost objekta koristimo konstruktor koji kao argumente uzima tip

16

servisa (na tip je VremenskiServer) i baznu Web adresu na kojoj emo obznaniti na servis. Sljedei korak je kriranje krajnje toke naeg servisa, gdje koristimo spomenutu metodu AddServiceEndpoint. Mi emo koristiti verziju metode koja kao argumente uzima sljedee tip suelja servisa (Contract), poveznicu (Binding) i na kraju adresu (Address). Tip suelja servisa je jasno naznaen kao tip IVremenskiServer, kao poveznicu (binding) odabiremo objekt tipa BasicHttpBinding koji je osnovni izbor jer funkcionira sa veinom sustava koji implementiraju XML Web servise i ima ugraenu svu potrebnu funkcionalnost za takve sluajeve. Adresu u naem sluaju ostavljamo praznu jer elimo da krajnja toka preuzme baznu adresu definiranu kroz ServiceHost objekt. Metodom Open, ServiceHost objekta startamo proces servisa koji sada eka zahtjeve klijenata. Ovako postavljeni Web servis ne nudi nikakve informacije za klijente o tome kako koristiti servis, odnosno ne moemo nikako dobiti WSDL servisa na temelju kojega klijent moe doznati detalje o pristupu servisu ili automatski generirati klijentski kod i konfiguracijske datoteke za pristup servisu. U tu svrhu, kako smo ranije istaknuli, trebamo dodati MEX krajnju toku. Dio koda koji dodaje MEX krajnju toku, istaknut je u prethodnom primjeru razliitom bojom. Prvo dodajemo objekt tipa ServiceMetadataBehavior naem ServiceHost objektu, odnosno dodajemo novu funkcionalnost (ili ponaanje) servisu na temelju kojega e servis mo i ponuditi WSDL klijentima. Nakon toga, eksplicitno dodajemo MEX krajnju toku koja ima ugovor tipa IMetadataExchange, poveznica je standardna MEX HTTP poveznica (binding), a adresa je simbolino mex. Do MEX krajnje toke moemo sada pristupiti preko adrese: http://127.0.0.1:9876/vrijeme?wsdl. Vano je uoiti da smo na ServiceMetadataBehavior objekt modificirali tako da smo omoguili koritenje HTTP GET metode (HttpGetEnabled = true) to znai da emo naoj MEX krajnjoj toki mo i pristupiti i iz preglednika. Sada je sve spremno za koritenje Web servisa i moemo pristupiti implementaciji klijenta.
using using using using using System; System.Collections.Generic; System.Linq; System.Text; System.ServiceModel;

namespace WCFKlijent { class VremenskiKlijent { static void Main(string[] args) { ChannelFactory<IVremenskiServer> myChannelFactory = new ChannelFactory<IVremenskiServer>(new BasicHttpBinding(), new EndpointAddress("http://127.0.0.1:9876/vrijeme")); IVremenskiServer wcfClient = myChannelFactory.CreateChannel(); string result = wcfClient.getVrijeme(); Console.WriteLine(result); Console.WriteLine("Pritisni <ENTER> za kraj.\n\n"); Console.ReadLine(); } } }

17

Objanjenje: u naem primjeru klijentski dio smo napravili u potpunosti runo kroz kod, a kasnije emo pokazati kako se ovaj postupak moe automatizirati i vidjet emo na in pristupa servisu kombinacijom koda i konfiguracijskih datoteka. Isto kao to i krajnja toka mora definirati ABC, klijent mora znati ABC da bi pristupio servisu i mora ugraditi ove elemente u svoj kod. Adresa servisa je jednostavna. To je adresa na kojoj smo obznanili servis u standardnom formatu. Poveznica krajnje toke definira komunikacijski mehanizam kroz koji je servis izloen, npr. NetTcpBinding, WsHttpBinding ili BasicHttpBinding. Ugovor se precizno definira kroz XML dokument koji servis razumije. Prvi korak ugovora izraava se kroz spomenute atribute [ServiceContract] i [DataContract] kojima naznaujemo dijelove koda u klasi ili suelju, a WCF prevodi taj dio (drugi korak) u XML, odnosno WSDL koji e klijenti moi korisiti, pogotovo ako su razvijeni u drugoj tehnologiji. Dakle, prvi dio implementacije klijenta je osigurati klijentu suelje servisa. Suelje se dijeli izmeu servisa i klijenta. Sintaktiki, C# suelje, odnosno ugovor se razlikuje od WSDLa, ali znaenje im je zapravo isto. Odnosno, oboje precizno opisuje kako pristupiti servisu, koji su nazivi operacija i koji su parametri. Drugi dio je otvoriti kanal prema servisu, a to radimo pomou objekta klase ChannelFactory. U uglatim zagradama specificiramo tip kanala koji elimo, a konstruktor uzima dva parametra, a to su poveznica i to BasicHttpBinding i adresa kao objekt klase EndpointAddress. Kada smo inicijalizirali tvornicu kanala, metodom CreateChannel napravimo kanal koji dobiva tip naeg C# suelja (IVremenskiServer). Sada moemo preko kreiranog objekta tipa IVremenskiServer pozivati metode servisa kao da se zapravo nalaze lokalno. Automatsko generiranje klijentskog koda Postoji i jednostavniji i bri nain koritenja servisa, odnosno razvijanja klijenta Web servisa, a to je automatsko generiranje pomou alata koje nudi gotovo svaka platforma. Automatsko generiranje u .NETu moemo napraviti na dva naina: (1) pomou Visual Studia opcijom Add Web Reference ili pomou alata svcutil.exe koji dolazi s .NET platformom. Oba naina daje iste rezultate i jedini kod koji trebamo napisati na klijentskoj strani u tom sluaju je sljedei:
using using using using System; System.Collections.Generic; System.Linq; System.Text;

namespace WCFKlijentAuto { class VremenskiKlijent { public static void Main() { VremenskiServer.VremenskiServerClient proxy = new VremenskiServer.VremenskiServerClient(); string result = proxy.getVrijeme(); Console.WriteLine(result); Console.WriteLine("Pritisni <ENTER> za kraj.\n\n"); Console.ReadLine(); } } }

18

Kao to vidimo, da bismo uspostavili vezu prema servisu potrebna nam je jedna linija koda. Da bismo to postigli koristimo opciju Add Service Reference.

Jedino to trebamo napraviti je upisati adresu naeg servisa, odabrati predloeni servis, dati mu ime i dalje e sve Visual Studio napraviti za nas. Iza kulisa Visual Studio generira dvije datoteke. Jedna je konfiguracijska datoteka app.config, a druga datoteka je datoteka Reference.cs u kojoj se nalazi kod potreban za koritenje Web servisa, slian onome to smo mi pisali. Ova klasa naziva se jo proxy klasom. U kombinaciji te dvije datoteke dobivamo mogunost jednostavnog spajanja na servis. Isti rezultat smo mogli dobiti koritenjem alata svcutil.exe koji se nalazi obino u direktoriju C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin. Njega koristimo na sljedei nain: svcutil http://127.0.0.1:9876/vrijeme?wsdl -config:app.config -out:generatedProxy.cs Adresa je obavezna, dok ostale opcije nisu obavezne.

19

Popis literature
Martin Kalin, Java Web Services: Up and Running, 1st Edition, O'Reilly Media, Inc., USA, 2009. Steve Resnick, Richard Crane, Chris Bowen, Essential Windows Communication Foundation, Addison-Wesley, USA, 2008. Bill Evjen, Scott Hanselman, Devin Rader, Professional ASP.NET 3.5 SP1 Edition in C# and VB, Wiley Publishing, Inc., USA, 2009. http://www.wikipedia.org

20