Ukázka vytvoření a použití jednoduché webové služby

Na začátku kapitoly jsem došel k závěru, že použití webových služeb bude pro náš projekt asi nejlepší, mimo jiné z důvodu snadného použití. Většině čtenářů však asi soapové zprávy ani WSDL popisy nebudou připadat zrovna průhledné a jednoduché. Nezbývá s nimi než souhlasit. Pravdou však je, že od technických detailů je vývojář většinou zcela odstíněn díky podpoře webových služeb ve vývojových nástrojích. Abych demonstroval snadnost použití webových služeb, rozhodl jsem se do práce zařadit popis vytvoření a použití jednoduché webové služby. Služba nesouvisí nijak přímo s cílem projektu. Vzhledem k tomu, že by tato kapitola diplomové práce měla sloužit i jako návod pro tvůrce ostatních modulů systému RAINBOW, uvádím zde tento jednoduchý příklad. Vytvoření dalších modulů a jejich úspěšné zapojení do komunikační infrastruktury je klíčovým předpokladem úspěšnosti celého projektu.

V Javě vytvoříme jednoduchou webovou službu, která bude schopná sečíst dvě čísla. Pak ukáži, jak můžeme jednoduše napsat klienty využívající tuto službu v Javě, Perlu a C# v prostředí .NET.

Vytvoření služby

Pro vytvoření a provozování služby použijeme balík WASP (Web Applications and Services Platform) od firmy Systinet. Existuje mnoho dalších implementací webových služeb, jejich přehled lze nalézt např. na adrese http://www.soapware.org/directory/4/implementations.

Nejprve si vytvoříme jednoduchou třídu, která bude obsahovat metodu umožňující sečtení dvou čísel (viz příklad 4.8). Všimněte si, že se jedná o zcela běžnou třídu, neobsahuje nic specifického, co by indikovalo, že se má v budoucnu jednat o webovou službu.

Příklad 4.8. Javová třída s metodou pro součet čísel

public class Soucet
{
  public int Secti(int a, int b)
  {
    return a + b;
  }
}

Nyní chceme z této třídy udělat webovou službu. WASP pro tyto účely nabízí jednak sadu nástrojů ovladatelných z příkazové řádky, jednak mnohem pohodlnější nástroje (WASP Developer), které se integrují přímo do javového vývojového prostředí jako je JBuilder nebo Forte.

Obrázek 4.2. Vytvoření webové služby z javové třídy

Přímo ve vývojovém prostředí proto řekneme, že chceme z třídy udělat webovou službu. Průvodce převodem se nás zeptá, které metody mají být dostupné v rámci webové služby (obrázek 4.3).

Obrázek 4.3. Výběr metod převáděných na webovou službu

V dalším kroku si vybere jmenný prostor pro službu, její název a další parametry nezbytné pro správné vygenerování WSDL popisu (obrázek 4.4).

Obrázek 4.4. Nastavení názvu webové služby

WASP Developer nám nyní vygeneroval kostru webové služby a základ WSDL souboru. Z ní vygenerujeme kostru instalačního balíčku (obrázky 4.5 a 4.6).

Obrázek 4.5. Vygenerování kostry instalačního balíčku pro webovou službu

Obrázek 4.6. Zadání názvu instalačního balíčku

Nyní můžeme přikročit k vytvoření plně funkční webové služby. Možností je mnoho, jednou z nich je vytvoření javového archivu, který obsahuje vše podstatné provoz služby – její kód, WSDL popis a další konfigurační soubory, které vyžaduje WASP Server. Vytvoření archivu je zase jen otázkou kliknutí (obrázek 4.7).

Obrázek 4.7. Vytvoření instalačního archivu

Tento javový archiv pak můžeme použít k instalaci webové služby na server. WASP Server obsahuje administrační konzoli s webovým rozhraním. S její pomocí můžeme konfigurovat existující služby a nové přidávat (nahráním instalačního archivu – viz obrázek 4.8).

Obrázek 4.8. Instalace webové služby na server

Pomocí administračního rozhraní (obrázek 4.9) lze jednotlivé služby zastavovat a spouštět, odinstalovat, případně si zapnout trasování odesílaných a přijímaných SOAP zpráv. Je zde k dispozici i URL adresa, kde je dostupný popis služby ve WSDL. S jeho znalostí mohou naši webovou službu využívat i další aplikace.

Obrázek 4.9. Administrační rozhraní WASP Serveru

Příklad 4.9. WSDL popis ukázkové webové služby

<?xml version='1.0'?>
<wsdl:definitions name='Soucet' 
  targetNamespace='urn:x-kosek:services:Soucet'
  xmlns:wsdl='http://schemas.xmlsoap.org/wsdl/'
  xmlns:xsd='http://www.w3.org/2001/XMLSchema'
  xmlns:tns='urn:x-kosek:services:Soucet'
  xmlns:http='http://schemas.xmlsoap.org/wsdl/http/'
  xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
  xmlns:mime='http://schemas.xmlsoap.org/wsdl/mime/'
  xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/'
  xmlns:SOAP-ENC='http://schemas.xmlsoap.org/soap/encoding/'>
  <wsdl:message name='Soucet_Secti_Response'>
    <wsdl:part name='response' type='xsd:int'/>
  </wsdl:message>
  <wsdl:message name='Soucet_Secti_Request'>
    <wsdl:part name='p0' type='xsd:int'/>
    <wsdl:part name='p1' type='xsd:int'/>
  </wsdl:message>
  <wsdl:portType name='Soucet'>
    <wsdl:operation name='Secti' parameterOrder='p0 p1'>
      <wsdl:input name='Secti' 
                  message='tns:Soucet_Secti_Request'/>
      <wsdl:output name='Secti' 
                   message='tns:Soucet_Secti_Response'/>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name='SoucetSOAPBinding0' type='tns:Soucet'>
    <soap:binding 
     transport='http://schemas.xmlsoap.org/soap/http' style='rpc'/>
    <wsdl:operation name='Secti'>
      <soap:operation soapAction='' style='rpc'/>
      <wsdl:input name='Secti'>
        <soap:body use='encoded' 
          encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' 
          namespace='urn:x-kosek:services:Soucet'/>
      </wsdl:input>
      <wsdl:output name='Secti'>
        <soap:body use='encoded' 
          encodingStyle='http://schemas.xmlsoap.org/soap/encoding/' 
          namespace='urn:x-kosek:services:Soucet'/>
      </wsdl:output>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name='Soucet'>
    <wsdl:port name='Soucet' binding='tns:SoucetSOAPBinding0'>
      <soap:address location='http://localhost:6060/Soucet/'/>
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Javový klient

WASP není určen jen pro tvorbu webových služeb, ale i pro tvorbu konzumentů webových služeb. Konzument (klient) potřebuje pro připojení k webové službě znát její WSDL. WASP Developer nabízí průvodce, který je schopný z WSDL popisu vygenerovat všechen potřebný kód, existují samozřejmě i nástroje spustitelné z příkazové řádky.

Průvodce si od nás nejprve vyžádá URL adresu, na které lze získat WSDL (obrázek 4.10). Analýzou WSDL jsou zjištěny všechny dostupné služby (4.11) a můžeme potvrdit vytvoření kódu pro jejich přístup.

Obrázek 4.10. Generování klienta z WSDL popisu I

Obrázek 4.11. Generování klienta z WSDL popisu II

V našem jednoduchém případě průvodce automaticky vygeneruje dva javové soubory. První obsahuje definici rozhraní, které mapuje WSDL rozhraní na odpovídající javové rozhraní:

package client.iface;

public interface Soucet 
{
    int Secti(int p0, int p1);
}

Druhý soubor obsahuje kód, který vytvoří proxy objekt umožňující volání metod webové služby. Tento kód můžeme použít ve vlastním programu nebo jej použít pro otestování služby. Pro názornost si ukážeme, jak sečíst čísla 2 a 3 pomocí webové služby.

package client;

import client.iface.*;
import org.idoox.wasp.Context;
import org.idoox.wasp.MessageAttachment;
import org.idoox.webservice.client.WebService;
import org.idoox.webservice.client.WebServiceLookup;

public class SoucetClient{
  public static void main(String args[]) throws Exception {
    String host = "http://localhost:6060/Soucet/";

    //init the lookup
    WebServiceLookup lookup = (WebServiceLookup)Context.getInstance
        ("org.idoox.webservice.client.WebServiceLookup");

    //get the instance of the Web Service interface from the lookup
    //change the interface class to your Web Service's interface
    Soucet service = (Soucet)lookup.lookup
        ("http://localhost:6060/Soucet/", Soucet.class,host);

    //now call the methods on your Web  Service's interface
    System.out.println(service.Secti(2,3));
  }
}

Nejzajímavější je poslední řádka programu, kde voláme metodu Secti() jakoby byla dostupná lokálně. Objekt service je přitom proxy objekt, který volání metody předá webové službě – postará se tedy o vytvoření SOAP zprávy, její doručení, příjem odpovědi, její dekódování a převod zpět do nativních datových typů Javy.

Administrační konzole WASP Serveru umožňuje zapnout sledování SOAP komunikace. Můžeme se pak podívat, jak přesně vypadají SOAP požadavky/odpovědi, které si klient vyměňuje se serverem. Na obrázku 4.12 je zachycen požadavek na sečtení čísel 2 a 3. Je z něj jasně vidět, že SOAP rozhodně není optimalizován na velikost přenášených dat. Požadavek i odpověď obsahuje velké množství servisních informací. Ty však zaručují snadné použití webových služeb na různých platformách.

Obrázek 4.12. Ukázka SOAP komunikace mezi webovou službou a jejím konzumentem

C# klient pro .NET

.NET je nová platforma Microsoftu založená na principu podobném Javě. Programy se nyní nepřekládají přímo do binárního kódu pro určitou hardwarovou platformu a operační systém, ale překládají se do mezikódu – CIL (Common Intermmediate Language). Pro spuštění programu pak musí být na počítači k dispozici CLR (Common Language Runtime), který se postará o překlad CIL do nativního binárního kódu a jeho spuštění [40].

.NET také obsahuje velké množství knihoven s výbornou podporou XML a webových služeb. .NET je ostatně kolem webových služeb postaven – Microsoft si uvědomuje potřebu distribuovaných aplikací a s webovými službami je jejich implementace snazší než s použitím DCOM.

Vývojové prostředí Visual Studio .NET obsahuje nástroje pro pohodlnou práci s webovými službami. Pomocí jednoduchého průvodce (4.13) nám Visual Studio .NET vygeneruje z WSDL popisu proxy objekt.

Obrázek 4.13. Generování konzumenta z WSDL ve Visual Studiu .NET

Automaticky se vytvoří třída Soucet, která patří do jmenného prostoru localhost (ten je určen z adresy serveru, kde je umístěna webová služba – v našem případě se jedná o lokální webový server). Zavolání webové služby je pak hračka:

// vytvoření instance proxy objektu
localhost.Soucet service = new localhost.Soucet();

// zavolání webové služby
int vysledek = service.Secti(2,3);

Klient v Perlu

Do třetice si ukážeme volání webové služby z Perlu. Použijeme přitom modul SOAP:Lite, který umožňuje využít webové služby přímo v Perlu. Knihovna opět z WSDL přímo za běhu programu vytvoří proxy objekt, ve kterém můžeme volat vzdálené metody webové služby.

use SOAP::Lite;

print "Program na sčítání přes webovou službu\n";
print "Zadej A: ";
$a = <STDIN>;
chop($a);
print "Zadej B: ";
$b = <STDIN>;
chop($b);

print "\nA + B = ";
print SOAP::Lite->service('http://localhost:6060/Soucet/')
	        ->Secti($a,$b);