Järgevalt väljatoodud koodi ja konfiguratsiooninäited on pärit lähtekoodis näitest Examples\Calculus .

Klientrakenduse ehitamine

Generaatori kasutamine

Selleks et päringuid xtee teenuste poole teha, tuleb kõigepealt valmis genereerida wsdl-ist struktuurid.
Avades Xtee Generaatori, tuleb sisestada dto-de ja serialiseerijate väljundite ning wsdli asukohad. Wsdli asukoht võib olla nii veebiaadress kui ka asukoht failisüsteemis, mõlemaga saab generaator hakkama. Samuti ei pea olema erinev dto-de ja serialiseerijate genereerimise asukoht, see võib olla ühesugune.
Kui genereerimine on õnnestunud, siis tuleb väljundist luua klass teegi projekt ja ära kompileerida (kui dtod ja serialiseerijad olid erinevatesse kataloogidesse paigutatud siis 2 projekti).
Vahemärkuseks, et generaatoril on konfiguratsiooni fail (Seadistus.xml), kuhu saab kirjeldada geneerimiseks argumendid ning mida saab valida vahendil olevast rippmenüüst. Näiteks nii:

<keha xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <item xsi:type="tns:XteeGenConfiguraton" xmlns:tns="http://XteeGen/XteeGenConfiguraton.xsd">
    <Name xsi:type="xsd:string">Wsdl1</Name>
    <WsdlPath xsi:type="xsd:string">http://local/app.wsdl</WsdlPath>
    <ModelOutputFolder xsi:type="xsd:string">C:\app1</ModelOutputFolder>
    <ImplOutputFolder xsi:type="xsd:string">C:\app1</ImplOutputFolder>
    <GenerateOperationsNamely xsi:type="xsd:boolean">true</GenerateOperationsNamely>
  </item>
 <item xsi:type="tns:XteeGenConfiguraton" xmlns:tns="http://XteeGen/XteeGenConfiguraton.xsd">
    <Name xsi:type="xsd:string">Wsdl2</Name>
    <WsdlPath xsi:type="xsd:string">c:\\app2.wsdl</WsdlPath>
    <ModelOutputFolder xsi:type="xsd:string">C:\app2</ModelOutputFolder>
    <ImplOutputFolder xsi:type="xsd:string">C:\app2</ImplOutputFolder>
    <GenerateOperationsNamely xsi:type="xsd:boolean">true</GenerateOperationsNamely>
  </item>
</keha>
GenerateOperationsNamely element konfiguratsioonis on igand vanemast versioonist kus
meetodite signatuurid genereeriti kõik ühe nimega (Execute) mis aga tekitas probleeme sellega
et operatsioonide hulgas võib olla mitu sama sisendi/väljundiga operatsioone ja geneeruv kood seega ei komileeru. Soovitaks alati selle elemendi väärtuse tõesena hoida, siis klientrakendusele genereeruva teenuse kliendi meetodid nimetatakse wsdlis olevate operatsioonide nime järgi ja nii ei tohiks konflikte tekkida.

Klientrakenduse ülesseadmine

Xtee päringu väljakutsumiseks on vaja lisada rakendusse genereeritud dll-id ja Xtee.Core.dll (Lisaks log4net.dll).
Seejärel saab juba kirjutada päringu, mis võib välja näha näiteks selline:

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            //CalcAdapter on pärit genereeritud struktuuride teegist
            var client = new CalcAdapter();
            decimal result = client.Add(new Variables(3, 4)).Value;
            result = client.Multiply(new Variables(3, 4)).Value;
            result = client.Subtract(new Variables(3, 4)).Value; 
            Console.WriteLine(result); 
        }
    }
 
}

Selleks et päringud reaalselt ka tööle hakkaksid, on vaja rakendus konfigureerida.
Konfiguratsiooni failis tuleb registreerida xtee sektsioon selliselt:

  <configSections>
    <section name="xtee.configuration" type="Xtee.Core.Client.Config.ClientConfigurationSection, Xtee.Core"/>
  </configSections>

ning kliendi konfiguratsioon minimaalses mahus selliselt:

<xtee.configuration proxyURL="http://localhost/adapter.asmx">
    <xteeTypeAssemblies>
      <clear/>
      <add assemblyName="GenereeritudDtoDllNimi"/>
      <add assemblyName="GenereeritudSerialiseerijadDllNimi"/>
    </xteeTypeAssemblies> 
  </xtee.configuration>

Kindlasti tuleb registreerida genereeritud dll-id, nagu näites, muidu päringud tööle ei hakka.
Xtee kliendi konfiguratsiooni (xtee.configuration) võimalikud atribuudid on:

atribuut väärtus
proxyURL Teenuse url mille vastu päringud sooritatakse
storeMessages (true/false) Kas sõnumid salvestada või mitte (vaikimisi:false)
storagePath asukoht kuhu sõnumid salvestada, võib olla nii relatiivne kui absoluutne rakenduse suhtest
timeout saab täpsustada kaua oodatakse enne kui päring katkestatakse, ooteaeg on millisekundites (vaikimisi : 100000 (1 min 40 sek))
objectType sõnumi client elemendi attribuut, saab vaikimisi määrata väärtuse, mis päises kaasa antakse
xRoadInstance sõnumi client elemendi element, saab vaikimisi määrata väärtuse, mis päises kaasa antakse
memberClass sõnumi client elemendi element, saab vaikimisi määrata väärtuse, mis päises kaasa antakse
memberCode sõnumi client elemendi element, saab vaikimisi määrata väärtuse, mis päises kaasa antakse
subSystemCode sõnumi client elemendi element, saab vaikimisi määrata väärtuses, mis päises kaasa antakse
userId sõnumi element, saab vaikimisi määrata väärtuse, mis päises kaasa antakse
issue sõnumi element, saab vaikimisi määrata väärtuse, mis päises kaasa antakse
message-path-format Võimaldab kohandada salvestatavate sõnumite asukohta võtmesõnade abil.
Vaikeväärtus on: [service]\[year]\[month]\[day]\[personalcode]\[year]-[month]-[day]__[timeofday]__[ms].[type].txt mille puhul faili asukohaks määratakse näiteks : ...\colors.mix.v1\2013\10\23\38056489521\2013-10-23__21-04-22__012847@127.0.0.1.request.txt. Võimalikud võtmesõnad on [service],[year],[month],[day],[personalcode],[timeofday],[ms],[type]. Kohustuslikud pole [personalcode] ja [service]. Ülejäänud aga küll et tagada faili unikaalsus.
temporaryStoragePath Valikuline, kui ei ole määratud kasutatakse võtme storagePath väärtust. Hetkel kasutatakse manuste mahasalvestamise puhul. (commit:b918b8805c23)
kui väärtuseks on :inmemory: siis vastu võetud manuseid käsitletakse vaid mälus. (commit:c18fc1ae37b0 (1.0.6.4) )


Konfiguratsiooni saab hõlpsasti muuta ka koodi kaudu, tavaliselt võib olla näiteks isikukood muutuv vastaval kasutajale:
 static void Main(string[] args)
        {
            var client = new CalcAdapter();
            client.XteeCommand.Configuration.UserId= "12345678912"; 
        }

Päringu "Interceptorid"

Alates versioonist 1.0.5.1 on võimalik dekoreerida päringut nn. "interceptor"-itega millega
on võimalik rikastada funktsionaalselt päringu käivitamist. Selleks tuleb klient süsteemis implementeerida :
 public interface ICommandInterceptor
    {
        /// <summary>
        /// Called before request is sent out
        /// </summary> 
        void Begin(ISoapEnvelope requestEnvelope);

        /// <summary>
        /// Called after execution completes either with failure(exception not null) or successfully (exception null)
        /// </summary> 
        void End(ISoapEnvelope requestEnvelope, SoapEnvelope responseEnvelope, AboutCommand aboutCommand, Exception exception = null);
    }

Seejärel see registreerida järgevalt:
(näide PaintShop projektist mis logib päringu info konsooli)
  var adapter = new ColorsAdapter();
  //Examples\PaintShop\Client\CommandLoggingInterceptor.cs
  adapter.XteeCommand.Add(new CommandLoggingInterceptor()); 

Alates versioonist 2.0.1.3 on võimalik dekoreerida päringud ka teenusepakkuja poole peal.
Selleks tuleb teenusepakkuja projektis luua klass, mis implementeerib ICommandInterceptor ja
kirjeldada see configus elemendi adapter.configuration attribuudis commandInterceptor.

<adapter.configuration commandInterceptor="MyNamespace.MyCommandInterceptor,  MyAssembly">

Serverrakenduse ehitamine

Generaatori kasutamine

Esmalt on vaja genereerida struktuurid ja kompileerida teeki samamoodi nagu eespool kirjeldatud.

Serverrakenduse ülesseadmine

Klientide teenindamiseks tuleb koostada teenuse klass, panna pärinema soovitud teenuse interface-ist, mis on kättesaadav geneeritud teegist (geneeritakse wsdlist operatsioonidele vastavad interface-id) ja implementeerida ProcessRequest meetod:

namespace Server.Services
{ 
    public class ServiceMultiply : MultiplyServiceHandler
    {
        public MultiplyResponse ProcessRequest(MultiplyRequest input, MultiplyInputHeader header)
        {
            return new MultiplyResponse(input.Request, new Result(input.Request.VarX * input.Request.VarY));
        }
    }
}
Selleks et teenus ka tööle hakkaks, tuleb konfigureerida rakendus:
Registreerida sektsioon konfiguratsiooni failis:
<configSections>
    <section name="adapter.configuration" type="Xtee.Core.Adapter.Service.Config.AdapterServiceConfigurationSection, Xtee.Core"/>
  </configSections>
Ja konfiguratsioon ise:
<adapter.configuration storagePath="stored_messages" storeMessages="true">
    <services>
      <clear/>
      <!--Xtee operatsioonid seotakse konkreetse klassiga mis teenendab konkreetset xtee 
            operatsiooniga   -->
      <add objectType="SERVICE" xRoadInstance="EE" memberClass="GOV" memberCode="700030" subSystemCode="Calc" serviceCode="Add" version="v1" servicehandler="Server.Services.ServiceAdd,Server"/>
      <add objectType="SERVICE" xRoadInstance="EE" memberClass="GOV" memberCode="700030" subSystemCode="Calc" serviceCode="Multiply" version="v1" servicehandler="Server.Services.ServiceMultiply,Server"/>
      <add objectType="SERVICE" xRoadInstance="EE" memberClass="GOV" memberCode="700030" subSystemCode="Calc" serviceCode="Subtract" version="v1" servicehandler="Server.Services.ServiceSubtract,Server"/>
    </services>
    <xteeTypeAssemblies>
      <clear/>
        <add assemblyName="GenereeritudDtoDllNimi"/>
      <add assemblyName="GenereeritudSerialiseerijadDllNimi"/>
    </xteeTypeAssemblies>
  </adapter.configuration>

Xtee serveri konfiguratsiooni (adapter.configuration) võimalikud atribuudid on:

atribuut väärtus
commandInterceptor Täispikk klassi nimi, mis implenteerib ICommandInterceptor ja komaga eraldatud dll nimetus, milles vastav klass asub.
storeMessages (true/false) Kas sõnumid salvestada või mitte (vaikimisi:false)
storagePath asukoht kuhu sõnumid salvestada, võib olla nii relatiivne kui absoluutne rakenduse suhtest
message-path-format Võimaldab kohandada salvestatavate sõnumite asukohta võtmesõnade abil.
Vaikeväärtus on: [service]\[year]\[month]\[day]\[personalcode]\[year]-[month]-[day]__[timeofday]__[ms]@[client].[type].txt mille puhul faili asukohaks määratakse näiteks : ...colors.mix.v1\2013\10\23\38210272737\2013-10-23__21-04-22__012847@127.0.0.1.request.txt. Võimalikud võtmesõnad on [client] ,[service],[year],[month],[day],[personalcode],[timeofday],[ms],[type]. Kohustuslikud pole [personalcode] ja [service]. Ülejäänud aga küll et tagada faili unikaalsus. [client] markeerib päringu saaja ip-d, [personalcode] kliendi isikukoodi ,[type] - on tegemist päringuga või vastusega
temporaryStoragePath Valikuline, kui ei ole määratud kasutatakse võtme storagePath väärtust. Hetkel kasutatakse manuste mahasalvestamise puhul. (commit:b918b8805c23)
kui väärtuseks on :inmemory: siis vastu võetud manuseid käsitletakse vaid mälus. (commit:c18fc1ae37b0 (1.0.6.4))



Lisaks tuleb regisreerida teenuse httphandler:
 <system.web>
    <httpHandlers>
      <add verb="*" path="AdapterXtee.asmx" type="Xtee.Core.Adapter.XteeServiceHandlerFactory"/>
    </httpHandlers>
    .........
 </system.web>
Httphandleri-i registreerimine IIS7-es käib natukene teistmoodi, näites tooduna töötab IIS6-es ja ASP.NET development serveris .

Failide saatmisest .

Antud lahendus võimaldab saata ja vastuvõtta faile MIME formaadis. Lähtekoodis on ka näiterakendus failide saatmisest ja vastuvõtmisest: Examples\DocumentRepository.
Kui wsdlis on manused kirjeldatud vastavavalt xtee spetsifikatsioonile:


<complexType name="Document">
  <sequence>
    <element name="Name" type="string"></element>
    <element name="Sisu" nillable="true" type="base64Binary" xmime:expectedContentTypes="application/octetstream"/>
  </sequence>
</complexType> 

või


<complexType name="Document">
  <sequence>
    <element name="Name" type="string"></element>
    <element name="Sisu" nillable="true" type="ref:swaRef"/>
  </sequence>
</complexType> 


Sellisel juhul geneeritakse dto, mille küljest saab faili mugavalt kätte:

public interface IDocument {   
    string Name {
        get;
        set;
    }
    global::Xtee.Core.MultipartFile Sisu {
        get;
        set;
    }
}
mis võimaldab saata faile otse failisüsteemist (endist viisi) või siis otse mälust:
FileInfo fileInfo =new FileInfo(@"/somepicture.jpg");
//vanaviisi
doc.AddDocument(new Document("docA", fileInfo)); 
//uuemat moodi
doc.AddDocument(new Document("docA", MultipartFile.Create(fileInfo))); 
byte[] fileBytes = File.ReadAllBytes(@"/somepicture.jpg");
//baidid mälust
doc.AddDocument(new Document("docB", MultipartFile.Create(fileBytes))); 
//vastuvõtmisel kui ei ole konfis :inmemory: 
//siis toimib endiselt
var fail = document.Sisu.FullName;
// kui :inmemory: siis  'FullName' annab vea kuna fail istub mälus
//mõlemal juhul küll aga toimib
var bytes = document.Sisu.AllBytes()


Last edited Dec 20, 2016 at 12:00 PM by s0ps, version 43

Comments

No comments yet.