Přejít k navigační liště

Zdroják » Různé » Java na webovém serveru: SOAP webové služby

Java na webovém serveru: SOAP webové služby

Články Různé

Dnes navážeme na předchozí díl o RESTful webových službách a budeme se věnovat klasickým webovým službám (web services) využívajícím protokol SOAP. Jedná se svým způsobem o konkurenční technologie, které obě umožňují implementovat API pro naši aplikaci. Na konci tohoto dílu proto naleznete doporučení, kdy kterou z nich zvolit.

Původní význam zkratky SOAP je Simple Object Access Protocol, ale dnes se často vykládá spíše jako SOA Protokol – tedy protokol pro architekturu orientovanou na služby. V následujícím textu budu SOAP používat jako zkratku pro webové služby postavené nad tímto protokolem (ne jen pro protokol samotný) a podobně REST pro webové služby nad ním postavené.

Další důležitou zkratkou, kterou je třeba zmínit, je WSDL – Web Services Description Language  – což je XML formát sloužící k popisu služeb. Funguje jako určitá formalizovaná (a strojově čitelná) dokumentace toho, jaké metody (operace) služba nabízí, jaké mají parametry a návratové hodnoty a dalších metadat.

Specifikace a implementace

Podobně jako v případě RESTu i zde u klasických webových služeb máme v Javě specifikaci (JSR 224 – JAX-WS) a několik implementací (referenční Metro nebo např. CXF od Apache).

Jednoduchý příklad

Jako obvykle si nejprve si aktualizujeme zdrojové kódy naší aplikace pomocí Mercurialu:

$ hg pull
$ hg up "12. díl"

Případně je můžete stáhnout jako bzip2 archiv přes web. Pro dnešní příklad jsem vytvořil další webový modul ( nekurak.net-ws), kde naleznete ukázku webové služby.

Opět začneme tím nejjednodušším příkladem. Vytvoříme si službu, která má jeden textový parametr a vrací také textový parametr. Službu implementujeme jako třídu v rámci webového projektu ( nekurak.net-ws), kterou opatříme anotacemi.

@WebService
public class Pokus {
    @WebMethod
    public String pozdrav( String koho) {
    return "Ahoj, " + koho + "!";
    }
}

Jednoduché, že? Ve zdrojových kódech (třída cz.frantovo.nekurak.ws.Pokus) naleznete další anotace, které slouží např. k přejmenování metod nebo jmenných prostorů (ale nejsou nezbytně nutné).

Po přidání anotací se nám v Netbeans automaticky aktivuje druhý zobrazovací režim  – můžeme se na službu dívat jednak jako na zdrojový kód (Source) nebo si přepnout na její vizuální ztvárnění (Design):

Java SOAP

V levém panelu také vidíte nabídku volně dostupných webových služeb – můžete si do tohoto seznamu přidávat další a dívat se na nabízené operace.

Vytvořenou službu si můžeme otestovat pomocí webového rozhraní, které je poskytované frameworkem a nachází se na adrese: /pokusnaSluzba?Tes­ter. WSDL popis služby pak nalezneme na adrese: /pokusnaSluzba?WSDL

Podobně jako v minulém dílu o RESTu, i zde můžeme k otestování použít nástroj cURL. Skript na vyzkoušení služby naleznete ve zdrojových kódech v adresáři /test/ws.

Požadavek na webovou službu vypadá takto (posílá se jako POST na URL služby):

<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:pozdravOsobu xmlns:ns2="pokusNS">
            <jmenoOsoby>Franto</jmenoOsoby>
        </ns2:pozdravOsobu>
    </S:Body>
</S:Envelope>

A služba nám vrátí následující odpověď:

<?xml version='1.0' encoding='UTF-8'?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Body>
        <ns2:pozdravOsobuResponse xmlns:ns2="pokusNS">
            <return>Ahoj, Franto!</return>
        </ns2:pozdravOsobuResponse>
    </S:Body>
</S:Envelope>

Klienta k webové službě si můžete napsat v libovolném programovacím jazyce (což je taky jeden z důvodů zavádění webových služeb – nezávislost na platformě a integrace v heterogenních prostředích), ani k tomu nepotřebujete pracovat přímo s XML – existuje řada knihoven, které vám umožní překlad na objekty a metody daného jazyka. Pokud budete chtít psát klienta ve Flashi, jistě se vám bude hodit článek, který zde na Zdrojáku nedávno vyšel: Flex 4: Webové služby.

Praktická ukázka

Google nabízí zajímavou službu zvanou Geocoding, která umožňuje zjištění zeměpisných souřadnic na základě poštovní adresy. To se nám velice hodí – nemůžeme totiž chtít po uživatelích, aby k podniku ručně zadávali GPS souřadnice, ale když zadají adresu, můžeme si tyto souřadnice dopočítat (resp. požádat o to Google).

Vytvoříme si tedy službu, která projde podniky, které dosud nemají nastavené souřadnice, a na základě dat od Googlu je doplní.

Kostra služby vypadá následovně:

package cz.frantovo.nekurak.ws;
import javax.jws.WebMethod;
import javax.jws.WebService;
/**
 *
 * @author fiki
 */
@WebService(serviceName = "podnikSluzba", targetNamespace = "podnikNS", portName = "podnikPort")
public class PodnikWS {
    /**
     * Projde podniky, které nemají vyplněné souřadnice,
     * a pokusí se je doplnit na základě poštovní adresy podniku.
     * @return počet podniků, u nichž jsme doplnili souřadnice
     */
    @WebMethod(operationName = "dopocitejSouradnicePodleAdres")
    public int dopocitejSouradnice() {
    …
    }
}

Operace nemá žádné vstupní parametry, jedná se o jednoduchou proceduru. Budeme ji volat v pravidelných intervalech (např. pomocí cronu a nástroje cURL).

Požadavek si připravíme do souboru požadavek.xml:

<?xml version="1.0" encoding="UTF-8"?>
<S:Envelope xmlns:S="http://schemas.xmlsoap.org/soap/envelope/">
    <S:Header/>
    <S:Body>
        <ns2:dopocitejSouradnicePodleAdres xmlns:ns2="podnikNS"/>
    </S:Body>
</S:Envelope>

A můžeme službu volat pomocí obyčejného cURL z příkazové řádky, aniž bychom potřebovali nějaké složité nástroje nebo cokoli programovat:

curl -s  -H "Content-Type: text/xml"  -d @požadavek.xml http://nekurak.frantovo.cz/nekurak.net-ws/podnikSluzba

Poznámka k architektuře

Naše aplikace (databáze hospod) je příliš jednoduchá na to, aby se v ní našlo smysluplné využití pro technologie, jako jsou REST nebo SOAP služby  – berte je proto prosím jako ukázku technologie – věřím, že ve svých složitějších aplikacích a systémech pro tyto technologie uplatnění najdete

Úlohy, jako doplňování souřadnic k podnikům, by bylo lepší řídit událostmi (PUSH) místo provádění periodických operací (PULL). Po přidání podniku by bylo lepší vytvořit požadavek na dohledání souřadnic a ten vložit do fronty (např. JMS) a zpracovat ho asynchronně (aby uživatel nemusel čekat, než externí služba vrátí výsledek). Rovněž volání pomocí klasického unixového cronu by bylo lepší nahradit technologií, kterou poskytuje samotný aplikační server (např. plánovač Quartz). Ale pro tyto pokročilejší technologie zatím v tomto seriálu nebyl prostor.

Kdy zvolit REST a kdy SOAP

Jak již bylo řečeno v úvodu, webové služby postavené na REST principu a ty využívající SOAP protokol, jsou do jisté míry konkurenční technologie. Při návrhu aplikace tak budete muset volit jednu z nich (případně používat obě). Existují dvě základní kritéria, podle kterých se můžeme rozhodovat:

  • Logický pohled – vycházíme z „obchodní“ podstaty řešené úlohy, rozhodujeme se podle toho, zda pracujeme spíše se zdroji nebo spíše voláme procedury.
  • Pragmatičtější pohled – ohlížíme se více na technologii a řídíme se např. tím, jak snadno se k ní dá napsat klient, nebo jaká metadata lze ke službě přiřadit. A to i za cenu ústupků v logice rozhraní.

V principu lze všechny služby řešit jak SOAPem, tak RESTem. V případě SOAP služeb jednoduše implementujeme služby, které odpovídají CRUD operacím. Jelikož jsou SOAP služby dostatečně obecná technologie, je tento přístup možný a není problém mít procedury pro vytváření, načítání, aktualizování a mazání objektů. Nevýhodou je jistá „nestandardizo­vanost“ takto definovaného API: je jen na nás, zda si jednotlivé akce pojmenujeme jako ulož(), založ(), save(), put() nebo třeba insert(). Programátor volající tyto služby musí použít WSDL, aby věděl jak se která operace jmenuje.

Oproti tomu REST používá HTTP operace, které mají pevně definovaný význam (GET, PUT, POST, DELETE). Ovšem obsah sdělovaných zpráv (např. formát XML nebo JSON dat) často nebývá formálně (strojově čitelně – jako v případě WSDL) specifikován a je třeba použít dokumentaci nebo se jednoduše podívat na data, která služba vrací. Existuje popisný formát WADL, který by měl být tím, čím je WSDL pro SOAP služby, ale jedná se o poměrně mladou záležitost (oproti WSDL) a někteří vývojáři ho odmítají s tím, že není potřeba nebo že jde proti filosofii RESTu.

Pokud chceme implementoval libovolnou (i procedurální – RPC) službu pomocí REST služeb, lze to  – jen jsme trochu omezeni jednoduchostí RESTu a tím, že je určen k provádění CRUD operací a ne libovolných procedur. Tato omezení je možné obejít dvěma způsoby:

  • Vstupní parametry procedury zakódujeme do URL (GET parametry) a REST služba nám vrátí výsledek. Např. si požádáme o „zdroj“ /kalkulacka/secti/?a=123&b=456 a na serveru se provede procedura sčítání a vrátí nám výsledek formou „zdroje“ (ať už XML, prostý text nebo třeba JSON).
  • Pomocí dvou požadavků: jelikož předchozí způsob neumožňuje vkládat jako vstupní parametry složitější struktury (jsme omezeni jen na data typu klíč=hodnota, která se vejdou do URL), vytvoříme si jakýsi pseudozdroj, který službě předáme (POST) a ta nás následně odkáže na jiný pseudozdroj, který si stáhneme druhým HTTP požadavkem (GET) a v něm nalezneme výsledek procedury.

Jak je vidět, technologie je možné si z velké míry „ohnout“ a použít i k úlohám, ke kterým nejsou primárně určené. Co zvolit, vám nebudu obecně radit, záleží na konkrétním zadání. REST oceníte zejména na webu, protože implementovat pro něj klienta např. v Javascriptu je výrazně snadnější. A i u newebových aplikací, kde se pracuje se zdroji (nad kterými provádíme CRUD operace), oceníte elegantnost RESTu. Výhodou SOAPu naopak je přirozenější tvorba procedurálních služeb a možnost propracovanější strojově čitelné specifikace služby (WSDL).

Např. Google od veřejného SOAP API upustil a používá REST – a to i pro typicky procedurální úlohy typu převeďAdresuNaSouřadnice()  – viz jeho Geocoding Service. Zatímco jinde, kde se nepoužívají jen javascriptoví klienti, zase oceníte možnost silného typování SOAPu a možnost využití technologií jako je UDDI pro katalogizaci služeb a zvládání rozsáhlejších systémů.

Závěr

Dnes jsme si ukázali druhý způsob, jak lze vytvořit webové API pro naši aplikaci. V obou případech (REST i SOAP) se jedná o webové technologie, které projdou přes obvyklé firewally a které stojí nad HTTP protokolem. Příště si trochu odpočineme od náročných technologií a budeme se zase trochu věnovat samotné aplikaci a rozvoji jejích funkcí, které jsme teď trochu zanedbávali.

Odkazy

Komentáře

Subscribe
Upozornit na
guest
10 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
peter

Dovolim si okomentovat casti clanku, ktore nie su podla mna vhodne napisane a bolo by lepsie, keby sa v clanku nevyskytli aby sa dalej nesirili dezinformacie. Nepojdem do detailov, ktore som uz popisal v:
http://zdrojak.root.cz/clanky/java-na-webovem-serveru-piseme-rest-api/nazory/8426/
http://zdrojak.root.cz/clanky/java-na-webovem-serveru-piseme-rest-api/nazory/8425/
http://zdrojak.root.cz/clanky/java-na-webovem-serveru-piseme-rest-api/nazory/8430/
http://zdrojak.root.cz/clanky/java-na-webovem-serveru-piseme-rest-api/nazory/8437/

> V následujícím textu budu SOAP používat jako zkratku pro webové služby postavené nad tímto protokolem (ne jen pro protokol samotný) a podobně REST pro webové služby nad ním postavené.

Pouzivat jednu skratku SOAP pre 2 rozne veci v jednom cl, co zodpoveda specofikaciamanku je podla mna nevhodne.
Ak chceme hovorit o SOAP web sluzbach je lepsie pouzit napriklad „SOAP WS“, alebo WS-*. Obdobne pre REST a REST web sluzby.
Prave takymto obskurovanim pojmov totiz dochadza k najvacsim nedorozumeniam.

> Kdy zvolit REST a kdy SOAP. Existují dvě základní kritéria, podle kterých se můžeme rozhodovat: Logický pohled …, Pragmatičtější pohled …

Obe kriteria vyzeraju logicky, ale nevychadzaju z podstaty a rozdielov WS-* a RESTu (vid. http://www.practicingsafetechs.com/TechsV1/REST/, http://dmpc.dbp.fmph.uniba.sk/~rybar/it-software/docs/Integracia-SOA-REST.pdf)
– RESTovske WS volime vtedy ak sa jedna o Webovu aplikaciu a Webovu kommunikaciu.
– WS-* volime vtedy, ked nam ide o protokol agnostic interakciu medzi proprietarnymi alebo legacy systemami a zaroven si to zakaznik vyslovne zela (vendor lock :).

> Oproti tomu REST používá HTTP operace, které mají pevně definovaný význam (GET, PUT, POST, DELETE). Ovšem obsah sdělovaných zpráv (např. formát XML nebo JSON dat) často nebývá formálně (strojově čitelně – jako v případě WSDL) specifikován a je třeba použít dokumentaci nebo se jednoduše podívat na data, která služba vrací.

Ako suvisi strojova citatelnost reprezentacii v REST SW so strojovou citatelnostou WSDL?
Ak hovorime o SOAP v tomto kontexte, je potrebne povedat o ktorom s typov SOAP (RPC/literal, Document/literal, …) hovorime (http://www.ibm.com/developerworks/webservices/library/ws-whichwsdl/, http://www.eherenow.com/soapfight.htm). Je to totiz aj otazkou vykonu (http://www.ibm.com/developerworks/webservices/library/ws-soapenc/), co je dovodom, preco sa dnes preferuje SOAP Document/literal, v ktorom sa prenasa dokument a ked si odmyslime SOAP balenie pri tomto type, dostaneme RPC over HTTP (co je dalsia optimalizacia na vykon a prenesene data).

> Oproti tomu REST používá HTTP operace, které mají pevně definovaný význam (GET, PUT, POST, DELETE). Ovšem obsah sdělovaných zpráv (např. formát XML nebo JSON dat) často nebývá formálně (strojově čitelně – jako v případě WSDL) specifikován a je třeba použít dokumentaci nebo se jednoduše podívat na data, která služba vrací.

Ako je spomenute vyssie, pri preferovanom SOAP Document/literal tiez nie je format dokumentu/spravy formalne specifikovany, co nie je nedostatok, ale pozadovana vlastnost.

> Existuje popisný formát WADL, který by měl být tím, čím je WSDL pro SOAP služby, ale jedná se o poměrně mladou záležitost (oproti WSDL) a někteří vývojáři ho odmítají s tím, že není potřeba nebo že jde proti filosofii RESTu.

Nielen ze existenciu WADL odmietaju vyvojari, ale REST definuje sposob ako samopopisnosti sluzienb a teda WADL nema v ponimani RESTu zmysel. Ak sa hovori o existencii WADL v suvislosti s REST, je to dokaz nepochopenia RESTu a znacnej dezinterpretacie prace Roya Fieldinga.

> Pokud chceme implementoval libovolnou (i procedurální – RPC) službu pomocí REST služeb, lze to  – jen jsme trochu omezeni jednoduchostí RESTu a tím, že je určen k provádění CRUD operací a ne libovolných procedur. Tato omezení je možné obejít dvěma způsoby …

Z tejto vety je zrejme, ze autor clanku si dezinterpretuje REST. Nemozno RPC implementovat pomocou REST sluzby! Autor oznacuje pojmom REST nieco co je v skutocnosti HTTP-based RPC interface! Presne o tejto dost zavaznej dezinterpretacii pise sam Fielding na svojom blogu:
„I am getting frustrated by the number of people calling any HTTP-based interface a REST API. Today’s example is the SocialSite REST API. That is RPC. It screams RPC. There is so much coupling on display that it should be given an X rating.“ Roy Fielding (http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven)

> Např. Google od veřejného SOAP API upustil a používá REST – a to i pro typicky procedurální úlohy typu převeďAdresuNa­Souřadnice()  – viz jeho Geocoding Service. Zatímco jinde, kde se nepoužívají jen javascriptoví klienti, zase oceníte možnost silného typování SOAPu a možnost využití technologií jako je UDDI pro katalogizaci služeb a zvládání rozsáhlejších systémů.

Google SOAP API mozno zatial este ocenime, ale nie nadlho – http://googlesystem.blogspot.com/2006/12/googles-soap-search-api-no-longer.html.
Google skratka upustil od SOAP a od roku 2006 preferuje jedine REST API. A Google je spicka v IT a teda predpokladame, ze dobre vedia, preco to robia. My to vieme tiez. :)

Na zaver by som chcel napriek mojim vyhradam autora povzbudit k dalsej praci, lebo ako sa hovori „ucime sa cely zivot“.
Ako dokaz toho, ze aj ini architekti tapaju v rozdieloch WS-* a REST by som uviedol jeden prakticky priklad: http://dmpc.dbp.fmph.uniba.sk/~rybar/it-software/is-it-time-to-change-even-the-architect-not-just-architecture/
Ja sam som do tajomstiev RESTu prenikal dlhe roky a myslim, ze stale sa mam co ucit.

peter

> Ale co vybrat, když jsme na webu a potřebujeme procedurální API?

Zhrnme si to:
– sme na webe
– REST definuje ako ma vyzerat dobre navrhnuta web aplikacia alebo sluzba
Teda ak potrebujeme na webe proceduralne API, chyba je niekde inde. Kde? Hmmm, medzi stolickou a klavesnicou?

> Buď to zprasíme a budeme REST používat tak, jak se nemá (jako RPC)

REST sa neda pouzit ako sa nema. Mozeme pouzit HTTP ako sa nema, ale nie REST!
Mozeme pouzit HTTP RPC API, ale to nema nic s RESTom. Jedina chyba takeho HTTP RPC API je, ze sa nim vzdalujeme od principov Webu a teda RESTu.

> Sorry, ale tohle mi přijde jako vyloženě házení špíny na SOAP webové služby. S proprietárním SW nic společného nemají

Tu som slovom proprietarny myslel specificky pre konkretnu korporaciu, nie urceny pre siroku verejnost alebo internet.

> A „vendor lock-in“?

No co si budeme nahovarat, zazili ako rozne implementacie SOAP, aplikacne kontajneri a verzie spolu nechcu fungovat? O tom, ze napr. B2B klient nevedel spravit klienta k nasmu SW?

> U RESTu jsou strojově čitelná data (zdroje), která mi služba vrátí – ale jak zjistím, jaké má mít služba vstupní parametry nebo URL?

Dobra otazka. To zistim z dokumentacie, alebo dostanem hotovu linku/formular v nejakej reprezentacii. To je ta samopopisnost – poslem kolegovi ktory ma nakodit klienta k sluzbam iba root URL mojich sluzieb a vsetko tam ma – to je REST. Takto to robime realne v praxi ked ma kolega naprogramovat AJAX UI k REST sluzbam (vid. http://prest.sf.net _docs_).
A otazka naspat. WSDL definuje operacie a typy vstupnych a vtstupnych dat, ale kde mam popis, co ktore data znamenaju?

A este maly technicky detail. Uz ste niekedy generovali WSDL pre sluzbu na serverovej strane, ktora bola naprogramovana v dynamicky typovanom jazyku (napr. Python)? Da sa vobec WSDL vygenerovat ked nemame staticky typovany jazyk? Alebo vy ste zatial zili iba v tom jednom svete Javy? Su aj ine svety a ine jazyky a maju na webe rovnako vyznamne postavenie.

Show me the interoperable, full and free implementations
of WS-* in Python, Perl, Ruby and PHP.
You won’t see them, because there’s no intrinsic value
in WS-* unless you’re trying to suck money out of your customers.

    Mark Nottingham, ex BEA, teraz Yahoo!
    http://www.mnot.net/blog/2006/05/10/vendors

> A co ten Geocoding Service a spousta dalších příkladů v jejich API? Opravdu to Google dělá tak dobře a dodržuje striktně filosofii RESTu? Mně spíš přijde, že on si ho taky dost přiohnul, aby šel použít pro procedurální věci. Resp. neměli bychom tomu jeho API říkat REST, ale spíš „HTTP-based RPC interface“?

Ano, nestastne sa vzdaluju od REST. Urcite sa to ich API da spravit cistejsie. Aj chalani v Googli sa maju este co ucit. :)

lzap

Prosím Vás, kde jste přišel na to, že SOAP se „často vykládá spíše jako SOA Protokol“. Pracuji v oblasti SOA několik let, ale toto jsem ještě neslyšel. Naopak existuje (mylný) názor, že pro SOA potřebujeme SOAP. To není pravda. Pokud byste měl nějaký odkaz na „SOA protocol“, rád bych se poučil.

Bohužel JSR 224 není jedinou specifikací v Javě. Celkově je SOAP velmi roztříštěná věc a ve svém důsledku bohužel i komplikovaná. V praxi se často stane, že díky technickým problémům se spolu dva systémy prostě „nebaví“.

Ta dvě kritéria mi připadají dost uměle vytvořená. Technologii obvykle volíme jen tehdy, když vytváříme providera a ještě nevíme, kdo bude naše služby používat. Takto se ale obvykle webové služby nedělají – snad zrovna jen u společností jako je Google.

Pokud tvoříte aplikaci, u které se můžete s consumerem dohodnout, tak se prostě dohodnete. V businessu se obecně dává přednost SOAP. Pokud máte webovou aplikaci a chcete, aby ji lidé mohli „skriptovat“, hodí se víc REST.

Jiří Kosek

Kromě toho, že SOAP není „simple“, tak on není ani „object“ a ani „protocol“. ;-)

lzap

No pěkně to vymyslili pánové tam nahoře…

foxo

Asi si to zatiaľ nikto nevšimol, no obrázok linkuje na URL file:///C:/DO­CUME%7E1/MARTIN%7E1­.MAL/LOCALS%7E1/Tem­p/netbeans-design.png

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.