Využití webových služeb a protokolu SOAP při komunikaci

Jak jsme již naznačili, webové služby umožňují jednoduchou komunikaci mezi aplikacemi ve velmi heterogenním prostředí, protože komunikace je založena na platformě nezávislých standardech – především na jazyce XML a protokolu HTTP. Aplikace si mezi sebou posílají XML zprávy, které přenášejí dotazy a odpovědi jednotlivých aplikací. Celá infrastruktura webových služeb je založena na třech základních technologiích [39]:

Vzájemné vztahy mezi těmito třemi technologiemi jsou zachycené na obrázku 4.1. Ke každé webové službě by měl být k dispozici její formální popis v jazyce WSDL. Z tohoto popisu již jde automaticky vygenerovat soapový požadavek. Ve větších systémech nebo přímo v otevřeném prostředí Internetu se popis služby může zaregistrovat do UDDI registru. Ten slouží jako jakýsi telefonní seznam („zlaté stránky“), který umožňuje vyhledávání služeb s určitými parametry.

Klient, který chce využít webovou službu, získá buď přes UDDI, nebo přímo její popis. Z něj je jasné, jakou strukturu má mít soapová zpráva a kam se má webové službě poslat, aby ji rozpoznala.

Obrázek 4.1. Vztah tří základních technologií (SOAP, WSDL a UDDI) webových služeb

SOAP

SOAP je protokol pro posílání zpráv XML a je základem webových služeb. Ostatní standardy jako WSDL a UDDI vznikly až později po uvedení SOAPu a jen dále rozšiřují jeho možnosti a snadnost použití. SOAP umožňuje zaslání XML zprávy mezi dvěma aplikacemi a pracuje tedy na principu peer-to-peer. Zpráva je jednosměrný přenos informace od odesílatele k příjemci, ale díky kombinování několika zpráv můžeme pomocí SOAPu snadno implementovat běžné komunikační scénáře.

Nejčastěji se SOAP používá jako náhrada vzdáleného volání procedur (RPC), tedy v modelu požadavek/odpověď. Jedna aplikace pošle v XML zprávě požadavek druhé aplikaci, tak požadavek obslouží a výsledek zašle jako druhou zprávu zpět původnímu iniciátorovi komunikace. V tomto případě bývá webová služba vyvolána webovým serverem, který čeká na požadavky klientů a v okamžiku, kdy přes HTTP přijde soapová zpráva, spustí webovou službu a předá jí požadavek. Výsledek služby je pak předán zpět klientovi jako odpověď.

První verze (1.0) protokolu SOAP vznikla na konci roku 1999 jako výsledek společné práce firem DevelopMentor, Microsoft a UserLand, které chtěly vytvořit protokol pro vzdálené volání procedur (RPC) založený na XML [3]. Protokol navazoval na o rok mladší, jednodušší a méně flexibilní protokol XML-RPC. V průběhu roku 2000 se k podpoře přihlásila i firma IBM a nová verze SOAPu 1.1 byla zaslána W3C konsorciu [4]. Verze SOAPu 1.1 je dnes nejpoužívanější a v diplomové práci se budeme zabývat právě jí. Na půdě W3C konsorcia nyní probíhá práce na uvolnění prvního skutečného standardu SOAP 1.2 v rámci pracovní skupiny pro XML protokol. Pracovní verze specifikace je dostupná v [17].

Struktura zprávy

Zpráva v SOAPu je jednoduchý XML dokument, který má kořenový element Envelope. V této obálce jsou pak uzavřeny dva elementy Header (hlavička) a Body (tělo). Hlavička je přitom nepovinná a používá se pro přenos pomocných informací pro zpracování zprávy – například identifikaci uživatele, autentizační informace (jméno, heslo) apod.

O to nejdůležitější se stará tělo zprávy, v němž se přenášejí informace identifikující volanou službu a předávané parametry, resp. návratové hodnoty služby. SOAP používá jmenné prostory pro identifikování jednotlivých částí XML zprávy. Obálka, hlavičky a tělo zprávy patří do jmenného prostoru http://schemas.xmlsoap.org/soap/envelope/.

Příklad 4.1. Ukázka jednoduché zprávy SOAP

<SOAP-ENV:Envelope
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
 SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 
   <SOAP-ENV:Body>
    <m:GetLastTradePrice xmlns:m="urn:x-example:services:StockQuote">
      <symbol>MOT</symbol>
    </m:GetLastTradePrice>     
   </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Příklad 4.1 ukazuje velmi jednoduchý SOAP požadavek na zjištění posledního známého kurzu akcie s kódem MOT. Ukázková zpráva pro jednoduchost neobsahuje hlavičku, ale pouze tělo. V něm je požadavek na vyvolání vzdálené funkce GetLastTradePrice s parametrem pojmenovaným symbol s hodnotou MOT (kód akcií firmy Motorola).

Jak by mohla vypadat XML zpráva s výsledkem přibližuje příklad 4.2. Oba dva příklady jsou drobně modifikované ukázky přímo z [4].

Příklad 4.2. Ukázka zprávy s odpovědí

<SOAP-ENV:Envelope
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>   
 <SOAP-ENV:Body>
  <m:GetLastTradePriceResponse 
   xmlns:m="urn:x-example:services:StockQuote">
   <Price>14.5</Price>
  </m:GetLastTradePriceResponse>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Kódování dat

V ukázkách SOAP zpráv je použit ještě jeden jmenný prostor – http://schemas.xmlsoap.org/soap/encoding/. Ten identifikuje způsob kódování přenášených dat do XML. Se SOAPem můžeme použít libovolný způsob serializace, standard SOAPu jeden rovnou definuje. Standardní serializace je schopná do XML převést graf obsahující otypované objekty. V praxi se nejčastěji používají běžné skalární datové typy (jako čísla, řetězce apod.), které definují XML schémata. Navíc soapové kódování definuje způsob serializace složených datových typů – seznamů skalárních hodnot (polí) a struktur. Lze serializovat i reference na objekty.

Obecně platí, že se hodnoty ukládají vždy jako obsah elementů, jedna hodnota do jednoho elementu. Datové typy mohou být definovány buď v externím XML schématu nebo přímo v XML zprávě. Druhý způsob je jednodušší a tedy i používanější. Např. mé osobní údaje by mohly být zakódovány do XML pro potřeby SOAPu následujícím způsobem:

<jméno xsi:type="xsd:string">Jirka Kosek</jméno>
<email xsi:type="xsd:string">jirka@kosek.cz</email>
<věk xsi:type="xsd:int">26</věk>

Předpokládáme přitom, že prefixy xsi a xsd jsou svázány se jmenným prostorem http://www.w3.org/2001/XMLSchema-instance, resp. http://www.w3.org/2001/XMLSchema. Odpovídající samostatné XML schéma by pak vypadalo následovně:

<xsd:element name="jméno" type="xsd:string"/>
<xsl:element name="email" type="xsd:string"/>
<xsl:element name="věk" type="xsd:int"/>

Transportní mechanismy

Jelikož se dnes SOAP typicky používá pro RPC volání, je celkem přirozené, že se pro přenos požadavku/odpovědi nejčastěji používá protokol HTTP (HyperText Transfer Protocol) [16]. Důvodem je zejména široká podpora HTTP v různých aplikacích. Navíc webovou službu lze nahrát přímo na běžný webový server, jenž slouží jako „dispečer“, který jednotlivé požadavky předává odpovídající webové službě ke zpracování. Výhoda použití HTTP také spočívá v tom, že stávající síťová infrastruktura, zvláště ve firemní sféře, dovoluje v podstatě neomezenou komunikaci na portu vyhrazeném pro HTTP (TCP port 80). Webové služby je možné používat bez nutnosti zásahu do konfigurace aktivních síťových prvků jako jsou firewally. Při použití technologií DCOM nebo CORBA je potřeba povolit komunikaci na portech, které používají příslušné přenosové protokoly (např. IIOP pro CORBA).

SOAP požadavek se zasílá v těle HTTP požadavku. Používá se přitom metoda POST, která dovoluje posílat data v těle HTTP požadavku. Požadavek musí obsahovat HTTP hlavičku SOAPAction, která identifikuje SOAP požadavek. Tuto hlavičku mohou používat jednak firewally k filtrování požadavků a jednak může obsahovat URI s identifikací služby, která se má vyvolat. Pokud je obsahem hlavičky prázdný řetězec, služba ke spuštění je identifikována přímo adresou, na kterou směřuje požadavek.

Příklad 4.3. SOAP požadavek zaslaný přes HTTP

POST /StockQuote HTTP/1.1
Content-Type: text/xml; charset=utf-8
Content-Length: nnn
SOAPAction: ""

<SOAP-ENV:Envelope
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
 SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 
 <SOAP-ENV:Body>
  <m:GetLastTradePrice xmlns:m="urn:x-example:services:StockQuote">
   <symbol>MOT</symbol>
  </m:GetLastTradePrice>     
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Odpověď na požadavek nemá při přenosu pomocí HTTP žádné přídavné informace. Obsah odpovědi musí být identifikován jako XML dokument pomocí příslušného MIME typu text/xml v hlavičce Content-Type.

Příklad 4.4. SOAP odpověď přenášená pomocí HTTP

HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: nnn

<SOAP-ENV:Envelope
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>   
 <SOAP-ENV:Body>
  <m:GetLastTradePriceResponse 
   xmlns:m="urn:x-example:services:StockQuote">
   <Price>14.5</Price>
  </m:GetLastTradePriceResponse>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Další možností, jak posílat SOAP zprávy pomocí HTTP, je využití rozšiřujícího systému pro HTTP popsaného v [32]. Požadavek a odpověď se pak drobně liší v hlavičkách, jak ukazují příklady 4.5 a 4.6.

Příklad 4.5. SOAP požadavek zaslaný přes rozšíření HTTP

M-POST /StockQuote HTTP/1.1
Man: "http://schemas.xmlsoap.org/soap/envelope"; ns=42
Content-Type: text/xml; charset=utf-8
Content-Length: nnn
42-SOAPAction: ""

<SOAP-ENV:Envelope
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" 
 SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> 
  <SOAP-ENV:Body>
   <m:GetLastTradePrice xmlns:m="urn:x-example:services:StockQuote">
    <symbol>MOT</symbol>
   </m:GetLastTradePrice>     
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Příklad 4.6. SOAP odpověď přenášená pomocí rozšíření HTTP

HTTP/1.1 200 OK
Ext:
Content-Type: text/xml; charset=utf-8
Content-Length: nnn

<SOAP-ENV:Envelope
 xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
 SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>   
 <SOAP-ENV:Body>
  <m:GetLastTradePriceResponse 
   xmlns:m="urn:x-example:services:StockQuote">
   <Price>14.5</Price>
  </m:GetLastTradePriceResponse>
 </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

Jednotlivé implementace webových služeb podporují i další přenosové mechanismy. Patří mezi ně například přenos pomocí e-mailových zpráv pomocí protokolu SMTP (Simple Mail Transfer Protocol) nebo pomocí javové messagingové služby JMS.

WSDL

Jazyk WSDL [22] slouží k popisu síťových služeb jako množiny koncových bodů zpracovávajících zprávy. Operace a zprávy jsou popisovány na abstraktní úrovni a teprve poté jsou svázány s konkrétním síťovým protokolem a datovým formátem. To umožňuje snadné vytvoření popisu rozhraní, které nabízí jednu službu několika způsoby. V praxi WSDL popisy nejčastěji popisují služby, které si posílají zprávy pomocí formátu SOAP a protokolu HTTP.

WSDL vzniklo jako společná iniciativa firem Microsoft a IBM, které si uvědomily potřebu sjednocení jazyka používaného pro popis rozhraní webových služeb. Navazuje tak na předchozí aktivity, zejména na jazyky NASSL (Network Accessable Service Specification Language), SCL (SOAP Contract Language) a SDL (Service Description Language). WSDL [22] je v současné době vydán jako informativní poznámka W3C a v rámci pracovní skupiny pro popis webových služeb se pracuje na vytvoření skutečného standardu.

WSDL soubor s definicí rozhraní služby je XML dokument. Skládá se zejména z následujících elementů, které tvoří základní části každého WSDL popisu.

types

Obsahuje definici datových struktur používaných ve zprávách. K definici lze použít teoreticky libovolný typový systém, ale nejčastěji se používají XML schémata. Nástroje pro webové služby se starají o mapování datových typů podle XML schémat na nativní datové typy použitého jazyka.

message

Definuje formát předávaných zpráv pomocí dříve definovaných datových typů. Zprávy fungují jako vstupní anebo výstupní struktury pro operace. Každá zpráva se může skládat z několika logických částí s vlastním datovým typem. Při použití SOAPu pro RPC odpovídá jedna část zprávy jednomu parametru vzdálené metody.

operation

Abstraktní definice operací, které jsou službou podporovány. U operace se definuje jaké má vstupy a výstupy. Vstup a výstup je popsán již existující zprávou (message). V SOAP RPC modelu odpovídá operace metodě.

portType

Sdružuje dohromady několik operací.

binding

Slouží pro navázání určitého typu portu (portType) na konkrétní protokol a formát přenosu zpráv.

port

Jeden koncový bod služby definovaný jako kombinace síťové adresy a dříve definované vazby (binding).

service

Sdružuje několik koncových bodů (portů) do jedné služby.

Naším cílem není popsat zde detailně všechny možnosti WSDL, pro ilustraci uvádím jen ukázku WSDL souboru, který definuje rozhraní výše popsané služby pro zjišťování aktuálního kurzu zadané akcie.

Příklad 4.7. Ukázka WSDL souboru

<?xml version="1.0" encoding="utf-8"?>
<definitions name="StockQuote"
             targetNamespace="urn:x-example:services:StockQuote"
             xmlns:tns="urn:x-example:services:StockQuote"
             xmlns:xsd1="http://example.com/stockquote.xsd"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
             xmlns="http://schemas.xmlsoap.org/wsdl/">

  <types>
   <schema targetNamespace="http://example.com/stockquote.xsd"
           xmlns="http://www.w3.org/2000/10/XMLSchema">
     <element name="GetLastTradePrice">
       <complexType>
         <all>
           <element name="symbol" type="string"/>
         </all>
       </complexType>
     </element>
     <element name="GetLastTradePriceResponse">
       <complexType>
         <all>
           <element name="Price" type="float"/>
         </all>
       </complexType>
     </element>
   </schema>
  </types>

  <message name="GetLastTradePriceInput">
    <part name="body" element="xsd1:GetLastTradePrice"/>
  </message>

  <message name="GetLastTradePriceOutput">
    <part name="body" element="xsd1:GetLastTradePriceResponse"/>
  </message>

  <portType name="StockQuotePortType">
    <operation name="GetLastTradePrice">
      <input message="tns:GetLastTradePriceInput"/>
      <output message="tns:GetLastTradePriceOutput"/>
    </operation>
  </portType>

  <binding name="StockQuoteSoapBinding" 
           type="tns:StockQuotePortType">
    <soap:binding style="document" 
                  transport="http://schemas.xmlsoap.org/soap/http"/>
    <operation name="GetLastTradePrice">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
      </input>
      <output>
        <soap:body use="literal"/>
      </output>
    </operation>
  </binding>

  <service name="StockQuoteService">
    <documentation>Moje první služba</documentation>
    <port name="StockQuotePort" binding="tns:StockQuoteBinding">
      <soap:address location="http://example.com/StockQuote"/>
    </port>
  </service>

</definitions>

UDDI

UDDI nabízí mechanismy pro registrování, kategorizování a vyhledávání webových služeb. UDDI funguje jako velký adresář, který obsahuje informace o subjektech (firmách) a jimi poskytovaných službách. Samotný registr pracuje rovněž jako webová služba a komunikace s ní tedy opět probíhá pomocí SOAPu.

UDDI registr obsahuje následující čtyři druhy entit:

podnikatelské entity (firmy) – business entity

U každé firmy v registru jsou zaznamenány základní údaje jako název, stručný popis a kontaktní údaje. Každé firmě mohou být přiřazeny klasifikační identifikátory, které určují oblasti jejího podnikání a geografickou polohu.

služby – business service

Ke každé firmě jsou v registru uloženy seznamy služeb, které firma poskytuje. Každá služba je opět popsána a obsahuje seznam šablon vazeb, které ukazují na technické údaje nutné pro využití služby.

šablony vazeb – binding template

Šablony popisují, jak a kde je možné se službou komunikovat. Typicky je tato informace popsána odkazem na WSDL soubor s definicí rozhraní služby. Každá šablona kromě toho odkazuje na typ služby, který implementuje.

typy služeb – service typ

Typ služby definuje abstraktní službu. Funguje tedy jako obdoba rozhraní, jak je známe např. z Javy. Několik firem může nabízet stejný druh služby se stejným rozhraním a tedy i typem služby. Typ služby je popsán tzv. technickým modelem (tModel).

Typická práce s UDDI probíhá tak, že vývojář prohledá registr a najde si služby, které potřebuje. Získá pro ně popis WSDL a může je začít rovnou používat. Dodejme ještě, že UDDI nemusí obsahovat jen popisy webových služeb ve WSDL, lze do něj ukládat popisy služeb v libovolném formátu. Z důvodu interoperability se však společně s UDDI používá právě SOAP a WSDL.

Vzhledem k tomu, že náš projekt není tak rozsáhlý a zatím neobsahuje nijak velké množství služeb, nebudeme zatím UDDI registr potřebovat. Nebudu se jím proto ani podrobněji dále zabývat.