• Nieuwe artikelen

  • Nieuw in Delphi 6: Webservices

    Marcel van Beuzekom


    Eén van de nieuwe technieken die we tegenkomen in Delphi 6
    is 'Web Services'. Dit artikel legt je uit wat Web Services zijn, hoe je een
    server kunt maken en wat een client moet doen om met zo'n Web Service te
    communiceren.


    Wat zijn Web Services?


    Web Services zijn objecten die gebruikt kunnen worden via een netwerk,
    bijvoorbeeld internet. Web Services zijn platform onafhankelijk en
    programmeeromgeving onafhankelijk. Een object geschreven in de ene taal kan dus
    worden gebruikt in de andere taal. Het platform waar de server en client op
    draaien is niet van belang.


    Het kan zijn dat deze beschrijving je erg bekend voorkomt, het zou namelijk
    ook een beschrijving van COM/DCOM kunnen zijn. Wat is er dan nieuw? Eigenlijk
    niets! DCOM is alleen nooit helemaal geworden wat het zou moeten zijn, namelijk
    een platform onafhankelijk systeem. Een ander nadeel van DCOM is dat het een
    protocol is naast de standaard protocollen zoals http, pop news enzovoort.
    Verder vereist DCOM nogal wat administratie en registratie in het netwerk, op
    zich niet vreemd omdat bij DCOM de beveiliging door het besturingssysteem
    gebeurd. Kortom, DCOM is zeer goed in wat het moet doen, maar multi platform is
    het nooit geworden. Web Services belooft dat wel te bereiken.


    Waarom zou Web Services nou wel het succes kunnen worden waar dat bij DCOM
    niet helemaal lukte? De technieken die Web Services gebruiken zijn:  SOAP,
    HTTP, GET/POST, MIME en XML. Kortom, het is een verzameling van bestaande
    technieken in plaats van een compleet nieuwe techniek. Er hoeft dus weinig te
    worden geconfigureerd op de server (publiceren is voldoende) en op de client.
    Ook firewalls hoeven niet speciaal te worden aangepast omdat Web Services over
    standaard HTTP draaien.


    Een andere mogelijke succesfactor is het feit dat het World Wide Web
    Consortium heeft vastgelegd waaraan een webservice moet voldoen. Het verleden
    heeft bewezen dat dat nog geen garantie is dat iedereen zich aan die standaard
    houdt, denk maar aan de HTML uitbreidingen die zowel Microsoft als Netscape
    verzonnen zonder dit in een standaard vast te leggen. Maar de standaard is er en
    die is door een onafhankelijke partij vastgelegd.


    Overigens worden SOAP en
    Web Services vaak door elkaar gebruikt, dat is niet helemaal terecht. SOAP is
    één van de protocollen die gebruikt kan worden voor Web Services, maar dat zou
    net zo makkelijk een ander protocol kunnen zijn. Borland houdt het voorlopig bij
    SOAP, wij sluiten ons daar maar bij aan.


    WSDL


    De standaard van W3C beschrijft onder andere dat er een Web Services
    Description Language
    (WSDL) moet zijn. Een WSDL is een XML-document waarin
    wordt beschreven wat de mogelijkheden van een Web Service zijn, het 'contract' naar
    de buitenwereld. Ook hier zie je weer een overeenkomst met COM: de WSDL van een
    Web Service is vergelijkbaar met de interface van een COM object.


    Zonder op alle details in te gaan: er zijn dus een aantal afspraken waaraan we ons moeten houden voordat we
    een Web Service kunnen gaan bouwen. Maar gelukkig zijn wij Delphi programmeurs
    en, verwend als we zijn, gaan we er vanuit dat Borland dat allemaal voor ons
    heeft geregeld. En uiteraard: ook nu klopt dat weer. We gaan ons dus niet te
    veel meer bezighouden met de techniek, laten we maar gewoon eens een Web Service
    gaan bouwen, samen met een client die daar gebruik van maakt.


    De webserver


     De Web Service die we gaan bouwen zal worden gepubliceerd als een CGI
    applicatie. Je zult dus een webserver nodig hebben en die zul je zo moeten configureren
    dat er CGI applicaties gedraaid kunnen worden. Een korte inleiding hierover vind
    je in het artikel WebDelphi: introductie


    De EuroConverter


    Waarschijnlijk één van de meest gebouwde routines van de afgelopen jaren:
    euroconversie routines. Zou het niet handig zijn als die berekening gewoon op
    één plaats stond zodat we die vanuit onze programma's gewoon konden aanroepen?
    Problemen zoals: "Mag ik in één keer van NLG naar BEF omrekenen?", "Hoe
    moet ik afronden?" zouden dan niet meer bestaan, die routine zou dat
    allemaal zelf verzorgen. Uiteraard willen we zo'n routine vanuit alle platformen
    en programmeertalen aan kunnen roepen... een webservice dus!


    De Web Service


    Om een nieuwe Web Service te maken kies je voor File / New / Other / Web
    Services / Soap Server application. Vervolgens zie je een dialoog die je kent
    van het maken van web applicaties:  



    We hadden al besloten dat de Web Service in een CGI applicatie zou komen, het
    wordt dus de tweede keuze. Vervolgens wordt er een web applicatie gemaakt, maar
    op de datamodule staan alvast een aantal componenten:



    • HTTPSoapDispatcher1

      • Dit component regelt het inkomende verkeer dat als requests binnenkomt
        en naar interface calls moet worden omgezet. Het component registreert
        zich als 'auto dispatching' object bij de webmodule zodat alle calls van
        de webmodule meteen naar de SoapDispatcher worden doorgestuurd.



    • HTTPSoapPascalInvoker1

      • De SoapPascalInvoker krijgt de requests van de SoapDispatcher en
        stuurt ze uiteindelijk door naar de betreffende interfaces.



    • WSDLHTMLPublish1

      • Dit is het component dat de WSDL aanmaakt voor de interfaces die we
        hebben geregistreerd binnen de server




    De datamodule die is aangemaakt is helemaal klaar voor gebruik, die sla je
    dus op als MainModuleU en daar doe je verder niets aan. Het project sla je op
    als EuroConvertServer.


    Om de eigenlijke Web Service te maken moeten er twee dingen gebeuren: er moet
    een interface worden gemaakt en een object die deze interface ondersteund.
    Vervolgens moeten interface en object worden geregistreerd door middel van InvRegistry
    (Invocation Registry). Dit is de plaats waar de componenten die we op de
    datamodule al zagen staan gaan zoeken naar interfaces en objects.


    De interface


    Om een interface te kunnen registreren bij InvRegistry moet deze 'erven' van
    IInvokable.
    IInvokable heeft geen implementatie en erft direct van IInterface, maar IInvokable
    zorgt er wel voor dat de extra benodigde RTTI (runtime type information) wordt meegelinkt in de applicatie. 



    In het geval van onze EuroConverter willen we de betreffende landen en
    munsoorten opvragen en uiteindelijk de conversie uitvoeren. De interface ziet er
    dus als volgt uit:


    IEuroConverter = interface(IInvokable)
    ['{A83BAEB4-3F5B-4341-8027-6A874EC0D6A5}']
    function Convert(Amount: Real;
    FromCurrency, ToCurrency: string): Real; stdcall;
    function GetCountryCount: integer; stdcall;
    function GetCurrency(Index: integer): string; stdcall;
    function GetCountry(Index: integer): string; stdcall;
    end;

    Het object


    Vervolgens moet er een object
    aangemaakt worden die deze interface ondersteund. Ook voor dit object is een
    speciale ancestor nodig, namelijk TInvokableClass. De interface van het object
    ziet er als volgt uit:


    TEuroConverter = class(TInvokableClass, IEuroConverter)
    public
    function Convert(Amount: Real;
    FromCurrency, ToCurrency: string): Real; stdcall;
    function GetCountryCount: integer; stdcall;
    function GetCountry(Index: integer): string; stdcall;
    function GetCurrency(Index: integer): string; stdcall;
    end;
    De verdere implementatie vind je in het EuroConverterU.pas.

    De registratie


    Tenslotte moeten interface en object nog worden geregistreerd, dat doe je als
    volgt:


    initialization
    InvRegistry.RegisterInterface(TypeInfo(IEuroConver ter));
    InvRegistry.RegisterInvokableClass(TEuroConverter) ;

    Nu is het nog een kwestie van de unit opslaan (EuroConvertU.pas), compileren,
    zorgen dat je executable in de juiste CGI directory komt en je bent klaar. Je
    hebt zojuist je eerste Web Service gemaakt!

    Zolang je nog geen client hebt kun je er weinig mee, maar je kunt al wel de
    WSDL bekijken. Als je executable in je cgi-bin directory staat doe je dat door
    het volgende adres te openen in je browser


    http://localhost/cgi-bin/euroconvertserver.exe/wsdl/IEuroConverter


    Je kunt ook de WSDL
    op NLDelphi
    bekijken.


    Je ziet: als je deze executable nu op een webserver zou publiceren zou
    iedereen de WSDL op kunnen vragen en een programma kunnen maken dat jouw
    berekeningen gebruikt.


    De Client


    Het maken van een server was al simpel, de client is zo mogelijk nog
    simpeler. Ook hier heeft Borland de benodigde technische zaken voor ons opgelost
    en kunnen we op een gewone Delphi manier onze Web Service gebruiken.


    Maak een nieuwe applicatie en plaats daar een HTTPRIO component op van het
    WebService tabblad. Dit component zorgt ervoor dat een WSDL document in het
    geheugen wordt omgezet in een interface. Vul bij de property WSDLLocation de URL
    van de WSDL in en selecteer vervolgens de Service en de Port. Het component kan
    nu een verbinding maken met onze Web Service.


    Interface genereren


    Omdat we zojuist zelf de server hebben gemaakt zouden we onze eigen interface
    kunnen gebruiken. Maar we gaan er even vanuit dat we geen kennis hebben van de
    server (behalve zijn locatie) en laten Delphi een nieuwe interface maken. 


    Om de interface te genereren kies je voor File / New / Other / Web Services /
    Web Services Importer. Bij de URL vul je het adres in dat je net hebt gebruikt
    om de WSDL te bekijken in je browser. Klik op Generate en je ziet dat er een
    interface wordt aangemaakt voor onze EuroConverter. Deze interface wordt dus
    niet aangemaakt op basis van onze eerdere interface of ons object, maar op basis
    van de WSDL. Het maakt dus niet uit in welke taal de Web Service is geschreven
    of op welk platform deze draait, we kunnen van elke WSDL een interface aanmaken!


    Berekenen


    Zorg dat je formulier de unit met de interface used die je zojuist hebt
    aangemaakt, plaats een button en in het OnClick event zet je de volgende code:


    ShowMessage(FloatToStr((
    HTTPRio1 as IEuroConverter).Convert(100, 'EUR', 'NLG')));

    Als alles goed is gegaan zie je dat de berekening wordt uitgevoerd door je
    Web Service. Ook een client applicatie die gebruik maakt van een Web Service
    hebben we dus kunnen maken zonder ons uitgebreid te verdiepen in de
    achterliggende techniek.


    Conclusie


    In dit artikel heb je gezien wat een Web Service is en hoe je die met behulp
    van Delphi kunt maken en aanspreken. In volgende artikelen zal ik verder ingaan
    op de mogelijkheden van Web Services en zullen we ook Web Services van anderen,
    gebouwd in andere omgevingen, gaan gebruiken.


    De source van de server en een wat uitgebreider voorbeeld van de client vind
    je in EuroConverter.zip.


    Links


    Web
    Services Description Language (W3C)

    Gepubliceerde Web Services