Les types de données SOAP et les types de données 1000

De Wiki1000
(Différences entre les versions)
 
(3 révisions intermédiaires par un utilisateur sont masquées)
Ligne 1 : Ligne 1 :
 
{{#customtitle:Les types de données SOAP et les types de données 1000}}
 
{{#customtitle:Les types de données SOAP et les types de données 1000}}
  
==Les types de données SOAP et Ligne 1000==
+
===Les types de données SOAP et Ligne 1000===
  
 
L’exemple précédent utilisait un service très simple échangeant une chaine de caractère, les types utilisables dans les WS peuvent être plus compliqués et s’appuient sur les types définis par les Schémas XML
 
L’exemple précédent utilisait un service très simple échangeant une chaine de caractère, les types utilisables dans les WS peuvent être plus compliqués et s’appuient sur les types définis par les Schémas XML
  
==Les principaux types simples ==
+
===Les principaux types simples ===
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
|SOAP
+
!SOAP
|Ligne 1000
+
!Ligne 1000
|Commentaire
+
!Commentaire
 
|-
 
|-
 
|string
 
|string
Ligne 48 : Ligne 48 :
 
|Une chaine encodée contenant les données binaires
 
|Une chaine encodée contenant les données binaires
 
|}
 
|}
 
 
  
 
Les types SOAP sont reconnus comme des types de données natifs par  1000
 
Les types SOAP sont reconnus comme des types de données natifs par  1000
  
==Les types binaires==
+
===Les types binaires===
 
+
 
SOAP permet d’échanger des éléments binaires encodé soit en base 64 (base64Binary) soit en hexadécimal (hexBinary).  
 
SOAP permet d’échanger des éléments binaires encodé soit en base 64 (base64Binary) soit en hexadécimal (hexBinary).  
  
 
Pour permettre de manipuler ces données binaires des propriétés base64Binary et hexBinary ont été ajouté au type de données binaires du Framework (TfwPicture, TfwBinary, TfwMemo), et de nouveaux objets techniques ont été introduis :  
 
Pour permettre de manipuler ces données binaires des propriétés base64Binary et hexBinary ont été ajouté au type de données binaires du Framework (TfwPicture, TfwBinary, TfwMemo), et de nouveaux objets techniques ont été introduis :  
  
TBinaryContent
+
*[[Contenus binaires (tech)|TBinaryContent]]
  
 
C’est un type générique permettant de contenir des données binaires.
 
C’est un type générique permettant de contenir des données binaires.
Ligne 65 : Ligne 62 :
 
Exemple d’utilisation :
 
Exemple d’utilisation :
  
<pre>
+
<source lang='delphi'>
 
// Procedure SendClaim;
 
// Procedure SendClaim;
 
//  
 
//  
Ligne 87 : Ligne 84 :
 
   inst.sendClaim(body,content.base64Binary);
 
   inst.sendClaim(body,content.base64Binary);
 
end;
 
end;
</pre>
+
</source>
 
+
  
 
Exemple :
 
Exemple :
Ligne 96 : Ligne 92 :
 
Le service :
 
Le service :
  
<pre>
+
<source lang='delphi'>
 
Type
 
Type
 
   InteropService = Class(TServiceLocal)
 
   InteropService = Class(TServiceLocal)
Ligne 106 : Ligne 102 :
 
   output := input;
 
   output := input;
 
end;
 
end;
</pre>
+
</source>
  
 
Le proxy local du service :  
 
Le proxy local du service :  
  
<pre>
+
<source lang='delphi'>
 
Type
 
Type
 
   ICinteropservice = Class(TServiceDistant)
 
   ICinteropservice = Class(TServiceDistant)
Ligne 121 : Ligne 117 :
 
  //Remote procedure, do not code
 
  //Remote procedure, do not code
 
end;
 
end;
</pre>
+
</source>
  
 
L’appel du service en utilisant des chaînes de caractères :  
 
L’appel du service en utilisant des chaînes de caractères :  
  
<pre>
+
<source lang='delphi'>
 
//Procedure echoBase64;
 
//Procedure echoBase64;
 
var inst:ICinteropService;
 
var inst:ICinteropService;
Ligne 157 : Ligne 153 :
 
     else showMessage('echoBase64 OK');
 
     else showMessage('echoBase64 OK');
 
end;
 
end;
</pre>
+
</source>
  
 
L’appel du service en utilisant des TStringList
 
L’appel du service en utilisant des TStringList
  
<pre>
+
<source lang='delphi'>
 
//Procedure echoBase64_2;
 
//Procedure echoBase64_2;
 
var inst:ICinteropService;
 
var inst:ICinteropService;
Ligne 177 : Ligne 173 :
 
   lsout.SaveToFile('c:\myText-2.txt');
 
   lsout.SaveToFile('c:\myText-2.txt');
 
end;
 
end;
</pre>
+
</source>
  
 
Même exemple en utilisant une compression :  
 
Même exemple en utilisant une compression :  
  
<pre>
+
<source lang='delphi'>
 
//Procedure echoBase64_3;
 
//Procedure echoBase64_3;
 
var inst:ICinteropService;
 
var inst:ICinteropService;
Ligne 197 : Ligne 193 :
 
   lsout.SaveToFile('c:\myText-3.txt');
 
   lsout.SaveToFile('c:\myText-3.txt');
 
end;
 
end;
</pre>
+
</source>
 
+
==Les énumérés==
+
  
 +
===Les énumérés===
 
Le protocole SOAP permet de définir des énumérations de valeurs pour préciser les valeurs possibles d’un  paramètre de message.  
 
Le protocole SOAP permet de définir des énumérations de valeurs pour préciser les valeurs possibles d’un  paramètre de message.  
  
Ligne 207 : Ligne 202 :
 
Par exemple pour définir un service effectuant l’écho d’un énuméré :  
 
Par exemple pour définir un service effectuant l’écho d’un énuméré :  
  
<pre>
+
<source lang='delphi'>
 
//Défini un énuméré.
 
//Défini un énuméré.
 
EchoNum = (cstEcho1, cstEcho2) ;
 
EchoNum = (cstEcho1, cstEcho2) ;
Ligne 215 : Ligne 210 :
 
   output := input;
 
   output := input;
 
end;
 
end;
</pre>
+
</source>
  
 
Pour appeler ce service, (le service a été importé en utilisant un préfixe de paquet IC) :  
 
Pour appeler ce service, (le service a été importé en utilisant un préfixe de paquet IC) :  
  
<pre>
+
<source lang='delphi'>
 
ICEchoNum = (cstEcho1,cstEcho2) ;
 
ICEchoNum = (cstEcho1,cstEcho2) ;
  
Ligne 233 : Ligne 228 :
 
     else showMessage('echoEnum OK');
 
     else showMessage('echoEnum OK');
 
end;
 
end;
</pre>
+
</source>
  
 
Les valeurs énumérées sont transmises par leur constantes et non par leur index, l’appel précédent génère le message suivant :  
 
Les valeurs énumérées sont transmises par leur constantes et non par leur index, l’appel précédent génère le message suivant :  
Ligne 248 : Ligne 243 :
 
</pre>
 
</pre>
  
==Les types complexes (structures)==
+
===Les types complexes (structures)===
 
+
 
Le protocole SOAP permet d’échanger des types complexes sous forme de structure.  
 
Le protocole SOAP permet d’échanger des types complexes sous forme de structure.  
  
Ligne 256 : Ligne 250 :
 
Appel d’un service effectuant l’écho d’une structure :
 
Appel d’un service effectuant l’écho d’une structure :
  
<pre>
+
<source lang='delphi'>
 
//Procedure echoStruct;
 
//Procedure echoStruct;
 
//
 
//
Ligne 275 : Ligne 269 :
 
   showMessage('Result:'+structout.varString);
 
   showMessage('Result:'+structout.varString);
 
end;
 
end;
</pre>
+
</source>
 
+
==Les extensions de type complexe.==
+
  
 +
===Les extensions de type complexe.===
 
Une extension de type complexe permet d’enrichir un type complexe préalablement défini, la correspondance en Ligne 1000 est une classe héritant de la classe enrichie.
 
Une extension de type complexe permet d’enrichir un type complexe préalablement défini, la correspondance en Ligne 1000 est une classe héritant de la classe enrichie.
  
 +
{{info|Lors de la publication d’un service toutes les classes dérivées d’une classe publiée sont publiées.}}
  
{| class="wikitable"
+
===Les tableaux et références.===
|-
+
|{{#images:image1.png|Web_Services_1000}}
+
|Lors de la publication d’un service toutes les classes dérivées d’une classe publiée sont publiées
+
|}
+
 
+
==Les tableaux et références.==
+
 
+
 
Le protocole SOAP permet d’échanger des ensembles de données sous forme de tableaux. L’implémentation de  1000 distingue les tableaux de type simple des tableaux de structure.  
 
Le protocole SOAP permet d’échanger des ensembles de données sous forme de tableaux. L’implémentation de  1000 distingue les tableaux de type simple des tableaux de structure.  
  
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
|Scénarii
+
!Scénarii
|Correspondance ligne 1000
+
!Correspondance ligne 1000
 
|-
 
|-
|1. Tableau de type simple (t1) passé en paramètre
+
|Tableau de type simple (t1) passé en paramètre
 
|Tableau ouvert du type simple (t1) dans les paramètres de l’opération
 
|Tableau ouvert du type simple (t1) dans les paramètres de l’opération
  
 
const p : Array of t1 ;
 
const p : Array of t1 ;
 
|-
 
|-
|2. Tableau de structure (s1) en paramètre
+
|Tableau de structure (s1) en paramètre
 
|Liste d’objet de la classe représentant la structure (s1) dans les paramètres de l’opération
 
|Liste d’objet de la classe représentant la structure (s1) dans les paramètres de l’opération
  
 
const p : s1List ;  
 
const p : s1List ;  
 
|-
 
|-
|3. Tableau de structure (s1) dans une structure (s2)
+
|Tableau de structure (s1) dans une structure (s2)
 
|Rôle liste vers la structure (s1) du tableau dans la classe de la structure (s2)  
 
|Rôle liste vers la structure (s1) du tableau dans la classe de la structure (s2)  
 
|-
 
|-
|4. Type complexe (s1) référençant un type complexe (s2)
+
|Type complexe (s1) référençant un type complexe (s2)
 
|Rôle référence vers la structure (s1) dans la classe de la structure (s2)
 
|Rôle référence vers la structure (s1) dans la classe de la structure (s2)
 
|-
 
|-
|5. Tableau de type simple (t1) dans une structure (s2).
+
|Tableau de type simple (t1) dans une structure (s2).
 
|Rôle liste vers une classe wrapper du type simple (t1) dans la classe de la structure (s2)
 
|Rôle liste vers une classe wrapper du type simple (t1) dans la classe de la structure (s2)
 
|}
 
|}
  
===1. Tableau de type simple passé en paramètre.===
+
====Tableau de type simple passé en paramètre.====
 
+
 
Exemple:
 
Exemple:
  
<pre>
+
<source lang='delphi'>
 
Procedure echoArrayOfString(const input:Array of string; out output:Array of string);
 
Procedure echoArrayOfString(const input:Array of string; out output:Array of string);
 
var idx:Integer;
 
var idx:Integer;
Ligne 331 : Ligne 317 :
 
   output[idx] := input[idx];
 
   output[idx] := input[idx];
 
End ;
 
End ;
</pre>
+
</source>
  
 
Pour appeler ce service :
 
Pour appeler ce service :
  
<pre>
+
<source lang='delphi'>
 
Procedure echoArrayOfString ;
 
Procedure echoArrayOfString ;
 
var inst:ICinteropService; sin,sout:Array of string;
 
var inst:ICinteropService; sin,sout:Array of string;
Ligne 365 : Ligne 351 :
 
     else showMessage('echoArrayString OK');
 
     else showMessage('echoArrayString OK');
 
end;
 
end;
</pre>
+
</source>
  
===2. Tableau de type complexe passé en paramètre.===
+
====Tableau de type complexe passé en paramètre.====
  
 
Un type complexe étant une classe un tableau de type complexe est une liste d’objet de cette classe
 
Un type complexe étant une classe un tableau de type complexe est une liste d’objet de cette classe
Ligne 373 : Ligne 359 :
 
Par exemple pour échanger une liste de SOAPStruct
 
Par exemple pour échanger une liste de SOAPStruct
  
<pre>
+
<source lang='delphi'>
 
Type
 
Type
 
   InteropStruct1 = Class(TitObject)
 
   InteropStruct1 = Class(TitObject)
Ligne 401 : Ligne 387 :
 
     Procedure echoStruct1Array(const input:InteropStruct1List; out output:InteropStruct1List);
 
     Procedure echoStruct1Array(const input:InteropStruct1List; out output:InteropStruct1List);
 
   end;
 
   end;
</pre>
+
</source>
  
 
Pour appeler ce service :  
 
Pour appeler ce service :  
  
<pre>
+
<source lang='delphi'>
 
Procedure echoStructArray;
 
Procedure echoStructArray;
 
var inst:ICinteropService;
 
var inst:ICinteropService;
Ligne 474 : Ligne 460 :
 
   showMessage('echoStruct1 OK');
 
   showMessage('echoStruct1 OK');
 
end;
 
end;
</pre>
+
</source>
  
===3. Tableau de structure dans une structure.===
+
====Tableau de structure dans une structure.====
  
 
Un type complexe SOAP peut contenir des tableaux,  1000 modélise un tableau contenu dans un type complexe par un rôle liste composition.
 
Un type complexe SOAP peut contenir des tableaux,  1000 modélise un tableau contenu dans un type complexe par un rôle liste composition.
Ligne 482 : Ligne 468 :
 
Voir l’exemple précédent.
 
Voir l’exemple précédent.
  
===4. Type complexe référençant un élément de type complexe.===
+
====Type complexe référençant un élément de type complexe.====
  
 
Un type complexe SOAP peut référencer un élément de type complexe,  1000 modélise l’élément comme une référence composition référençant le type complexe.
 
Un type complexe SOAP peut référencer un élément de type complexe,  1000 modélise l’élément comme une référence composition référençant le type complexe.
  
===5. Tableau de type simple dans une structure.===
+
====Tableau de type simple dans une structure.====
  
 
La ligne 1000 ne permet pas de manipuler nativement des tableaux de type simple comme attribut de classes. Pour permettre l’échange de ces tableaux elle définit des classes Wrapper de types simples puis utilise des tableaux sur ces classes.  
 
La ligne 1000 ne permet pas de manipuler nativement des tableaux de type simple comme attribut de classes. Pour permettre l’échange de ces tableaux elle définit des classes Wrapper de types simples puis utilise des tableaux sur ces classes.  
Ligne 496 : Ligne 482 :
 
{{#images:image20.png|Web_Services_1000}}
 
{{#images:image20.png|Web_Services_1000}}
  
<pre>
+
<source lang='delphi'>
 
unit InterpServicePackage
 
unit InterpServicePackage
 
interface
 
interface
Ligne 527 : Ligne 513 :
  
 
end.
 
end.
</pre>
+
</source>
  
 
Lorsque ce service est publié en WSDL, la classe wrapper n’apparait pas et un élément de type tableau est publié :  
 
Lorsque ce service est publié en WSDL, la classe wrapper n’apparait pas et un élément de type tableau est publié :  
Ligne 579 : Ligne 565 :
 
L’appel de la fonction echStruct5 avec le passage des éléments du tableau :  
 
L’appel de la fonction echStruct5 avec le passage des éléments du tableau :  
  
<pre>
+
<source lang='delphi'>
 
Procedure TestInteropService.echoStruct5;
 
Procedure TestInteropService.echoStruct5;
 
var inst:ICinteropService;
 
var inst:ICinteropService;
Ligne 606 : Ligne 592 :
 
   showMessage('echoStruct5 :'+ss);
 
   showMessage('echoStruct5 :'+ss);
 
end;
 
end;
</pre>
+
</source>
  
 
Ce qui génère le message suivant :  
 
Ce qui génère le message suivant :  
Ligne 625 : Ligne 611 :
 
</pre>
 
</pre>
  
==Publication des rôles des classes utilisées comme type complexe soap.==
+
===Publication des rôles des classes utilisées comme type complexe soap.===
 
+
 
Lorsqu’ une classe, utilisée dans un service, est publiée dans un descriptif de service (WSDL) elle y inclut tous les rôles référençant une classe du paquet de service. Un rôle référençant une classe à l’extérieur du paquet de service ne sera pas publié.  
 
Lorsqu’ une classe, utilisée dans un service, est publiée dans un descriptif de service (WSDL) elle y inclut tous les rôles référençant une classe du paquet de service. Un rôle référençant une classe à l’extérieur du paquet de service ne sera pas publié.  
  
==Les types de données SOAP et Ligne 1000==
+
{{Footer|Web Services (ws)}}
 
+
[[Category:Web Services]]
L’exemple précédent utilisait un service très simple échangeant une chaine de caractère, les types utilisables dans les WS peuvent être plus compliqués et s’appuient sur les types définis par les Schémas XML
+
 
+
==Les principaux types simples ==
+
{| class="wikitable"
+
|-
+
|SOAP
+
|Ligne 1000
+
|Commentaire
+
|-
+
|string
+
|String
+
|
+
|-
+
|int
+
|Integer
+
|
+
|-
+
|decimal
+
|Currency
+
|Le type Decimal peut comporter jusqu’à 128 décimales, la ligne 1000 ne permet que 4 décimales
+
|-
+
|float, double
+
|Double
+
|
+
|-
+
|dateTime
+
|TDateTime
+
|
+
|-
+
|date
+
|Date
+
|
+
|-
+
|time
+
|Time
+
|
+
|-
+
|boolean
+
|Boolean
+
|
+
|-
+
|base64Binary
+
|String
+
|Une chaine encodée contenant les données binaires
+
|}
+
 
+
 
+
 
+
Les types SOAP sont reconnus comme des types de données natifs par  1000
+
 
+
==Les types binaires==
+
 
+
SOAP permet d’échanger des éléments binaires encodé soit en base 64 (base64Binary) soit en hexadécimal (hexBinary).
+
 
+
Pour permettre de manipuler ces données binaires des propriétés base64Binary et hexBinary ont été ajouté au type de données binaires du Framework (TfwPicture, TfwBinary, TfwMemo), et de nouveaux objets techniques ont été introduis :
+
 
+
TBinaryContent
+
 
+
C’est un type générique permettant de contenir des données binaires.
+
 
+
Exemple d’utilisation :
+
 
+
<pre>
+
// Procedure SendClaim;
+
//
+
var inst:TACwsiattachement;
+
    body:TACClaimDetailType;
+
    content: TBinaryContent;
+
begin
+
  // Objet gestionnaire de binaire
+
  content := TBinaryContent.Create;
+
 
+
  // Chargement de l’objet avec une image
+
content.LoadFromFile('d:\Mes documents\Mes images\white house.jpg');
+
 
+
  // Descriptif de l’image attendu par le service
+
 
+
  body := ClassManager.CreateInstance('TACClaimDetailType');
+
  body.Name := 'White house';
+
 
+
  //
+
  inst := ClassManager.CreateInstance('TACwsiattachement');
+
  inst.sendClaim(body,content.base64Binary);
+
end;
+
</pre>
+
 
+
 
+
Exemple :
+
 
+
Cet exemple montre comment appelé un service exécutant l’écho d’un paramètre binaire :
+
 
+
Le service :
+
 
+
<pre>
+
Type
+
  InteropService = Class(TServiceLocal)
+
  Procedure echoBase64(const input:base64Binary; out output:base64Binary);
+
end;
+
 
+
Procedure InteropService.echoBase64(const input:base64Binary; out output:base64Binary);
+
begin
+
  output := input;
+
end;
+
</pre>
+
 
+
Le proxy local du service :
+
 
+
<pre>
+
Type
+
  ICinteropservice = Class(TServiceDistant)
+
  public
+
    Procedure echoBase64(const input:base64Binary; out output:base64Binary);
+
  end;
+
 
+
Procedure ICinteropservice.echoBase64(const input:base64Binary; out output:base64Binary);
+
begin
+
//Remote procedure, do not code
+
end;
+
</pre>
+
 
+
L’appel du service en utilisant des chaînes de caractères :
+
 
+
<pre>
+
//Procedure echoBase64;
+
var inst:ICinteropService;
+
    sin:string;
+
    sout:base64binary;
+
    contin,contout:TBinaryContent;
+
begin
+
  inst := ClassManager.CreateInstance('ICinteropService');
+
 
+
  // Une chaine a transmettre
+
  sin := 'coucou';
+
 
+
  // Converti la chaine en utilisant un BinaryContent
+
  //
+
  contin := TBinaryContent.Create;
+
  contin.AsString := sin;
+
 
+
  // appel du service
+
  // sout contient la réponse encodée
+
  inst.echoBase64(contin.base64Binary,sout);
+
 
+
  // converti la réponse
+
  //
+
  contout := TBinaryContent.Create;
+
  contout.base64Binary := sout;
+
 
+
  // compare le résultat
+
  //
+
  if sin<>contout.AsString
+
    then showMessage('echoBase64 failed')
+
    else showMessage('echoBase64 OK');
+
end;
+
</pre>
+
 
+
L’appel du service en utilisant des TStringList
+
 
+
<pre>
+
//Procedure echoBase64_2;
+
var inst:ICinteropService;
+
    lsin,lsout:TStringList;
+
    sout: base64binary;
+
begin
+
  inst := ClassManager.CreateInstance('ICinteropService');
+
  lsin := TStringList.Create;
+
 
+
  lsin.LoadFromFile('c:\myText-1.txt');
+
 
+
  inst.echoBase64(lsin.base64binary,sout);
+
  lsout := TStringlist.Create;
+
  lsout.base64Binary := sout;
+
  lsout.SaveToFile('c:\myText-2.txt');
+
end;
+
</pre>
+
 
+
Même exemple en utilisant une compression :
+
 
+
<pre>
+
//Procedure echoBase64_3;
+
var inst:ICinteropService;
+
    lsin,lsout:TStringList;
+
    sout: base64Binary;
+
begin
+
  inst := ClassManager.CreateInstance('ICinteropService');
+
  lsin := TStringList.Create;
+
  lsin.LoadFromFile('c:\myText-1.txt');
+
 
+
  inst.echoBase64(lsin.getAsBase64Binary(b64ZlibNoSig),sout);
+
 
+
  lsout := TStringlist.Create;
+
  lsout.setAsBase64Binary(sout,b64ZLibNoSig);
+
  lsout.SaveToFile('c:\myText-3.txt');
+
end;
+
</pre>
+
 
+
==Les énumérés==
+
 
+
Le protocole SOAP permet de définir des énumérations de valeurs pour préciser les valeurs possibles d’un  paramètre de message.
+
 
+
Un énuméré SOAP correspond à un énuméré Ligne 1000.
+
 
+
Par exemple pour définir un service effectuant l’écho d’un énuméré :
+
 
+
<pre>
+
//Défini un énuméré.
+
EchoNum = (cstEcho1, cstEcho2) ;
+
 
+
//Procedure echoEnum(input:EchoEnum; out output:EchoEnum);
+
begin
+
  output := input;
+
end;
+
</pre>
+
 
+
Pour appeler ce service, (le service a été importé en utilisant un préfixe de paquet IC) :
+
 
+
<pre>
+
ICEchoNum = (cstEcho1,cstEcho2) ;
+
 
+
// Procedure echoEnum;
+
//
+
var inst:ICinteropService; sin,sout:ICEchoEnum;
+
begin
+
  sin := cstEcho1;
+
  inst := ClassManager.CreateInstance('ICinteropService');
+
  inst.echoEnum(cstEcho1,sout);
+
  if sin<>sout
+
    then showMessage('echoEnum failed')
+
    else showMessage('echoEnum OK');
+
end;
+
</pre>
+
 
+
Les valeurs énumérées sont transmises par leur constantes et non par leur index, l’appel précédent génère le message suivant :
+
 
+
<pre>
+
<?xml version="1.0" encoding="utf-8"?>
+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
+
<soap:Body>
+
<echoEnum xmlns="http://www.sage.com/fr/line1000/InterpServicePackage">
+
<input>cstEcho1</input>
+
</echoEnum>
+
</soap:Body>
+
</soap:Envelope>
+
</pre>
+
 
+
==Les types complexes (structures)==
+
 
+
Le protocole SOAP permet d’échanger des types complexes sous forme de structure.
+
 
+
Une structure SOAP correspond à une classe Ligne 1000.
+
 
+
Appel d’un service effectuant l’écho d’une structure :
+
 
+
<pre>
+
//Procedure echoStruct;
+
//
+
var inst:DSService; structin,structout:DSSOAPStruct;
+
begin
+
  // La structure est une classe 1000
+
  structin := ClassManager.CreateInstance('DSSOAPStruct');
+
  structin.varString := 'coucou';
+
  structin.varInt := 1;
+
  structin.varFloat := 1.0;
+
 
+
  // appel du service
+
  inst := ClassManager.CreateInstance('DSService');
+
 
+
  // l’instance en retour est créée par le framework
+
  inst.echoStruct(structin,structout);
+
 
+
  showMessage('Result:'+structout.varString);
+
end;
+
</pre>
+
 
+
==Les extensions de type complexe.==
+
 
+
Une extension de type complexe permet d’enrichir un type complexe préalablement défini, la correspondance en Ligne 1000 est une classe héritant de la classe enrichie.
+
 
+
 
+
{| class="wikitable"
+
|-
+
|{{#images:image1.png|Web_Services_1000}}
+
|Lors de la publication d’un service toutes les classes dérivées d’une classe publiée sont publiées
+
|}
+
 
+
==Les tableaux et références.==
+
 
+
Le protocole SOAP permet d’échanger des ensembles de données sous forme de tableaux. L’implémentation de  1000 distingue les tableaux de type simple des tableaux de structure.
+
 
+
{| class="wikitable"
+
|-
+
|Scénarii
+
|Correspondance ligne 1000
+
|-
+
|1. Tableau de type simple (t1) passé en paramètre
+
|Tableau ouvert du type simple (t1) dans les paramètres de l’opération
+
 
+
const p : Array of t1 ;
+
|-
+
|2. Tableau de structure (s1) en paramètre
+
|Liste d’objet de la classe représentant la structure (s1) dans les paramètres de l’opération
+
 
+
const p : s1List ;
+
|-
+
|3. Tableau de structure (s1) dans une structure (s2)
+
|Rôle liste vers la structure (s1) du tableau dans la classe de la structure (s2)
+
|-
+
|4. Type complexe (s1) référençant un type complexe (s2)
+
|Rôle référence vers la structure (s1) dans la classe de la structure (s2)
+
|-
+
|5. Tableau de type simple (t1) dans une structure (s2).
+
|Rôle liste vers une classe wrapper du type simple (t1) dans la classe de la structure (s2)
+
|}
+
 
+
===1. Tableau de type simple passé en paramètre.===
+
 
+
Exemple:
+
 
+
<pre>
+
Procedure echoArrayOfString(const input:Array of string; out output:Array of string);
+
var idx:Integer;
+
begin
+
  // Implémentation du service
+
  // Copie le tableau élément par élément.
+
  //
+
  for idx:=0 to length(input)-1 do
+
  output[idx] := input[idx];
+
End ;
+
</pre>
+
 
+
Pour appeler ce service :
+
 
+
<pre>
+
Procedure echoArrayOfString ;
+
var inst:ICinteropService; sin,sout:Array of string;
+
    idx:Integer; s1,s2:string;
+
begin
+
  inst := ICinteropService.Create;
+
 
+
  // Initialise le tableau par une constante
+
  sin := ['Ah','que','coucou'];
+
 
+
  // Appel du service, sout sera initialisée
+
  // par la couche soap
+
  inst.echoArrayOfString(sin,sout);
+
+
 
+
  // Verification
+
  //
+
  s1 := '';
+
 
+
  for idx:=0 to length(sin)-1 do
+
  s1 := s1+sin[idx];
+
 
+
  s2 := '';
+
  for idx:=0 to length(sout)-1 do
+
  s2 := s2+sout[idx];
+
 
+
  if s1<>s2
+
    then showMessage('echoArrayString failed :'+s1+':'+s2)
+
    else showMessage('echoArrayString OK');
+
end;
+
</pre>
+
 
+
===2. Tableau de type complexe passé en paramètre.===
+
 
+
Un type complexe étant une classe un tableau de type complexe est une liste d’objet de cette classe
+
 
+
Par exemple pour échanger une liste de SOAPStruct
+
 
+
<pre>
+
Type
+
  InteropStruct1 = Class(TitObject)
+
  public
+
    InteropStruct2List: CompositionList of InteropStruct2;
+
    InteropStruct2Ref: InteropStruct2;
+
    InteropStruct3Ref: InteropStruct3;
+
    oidInteropStruct2Ref: string;
+
    oidInteropStruct3Ref: string;
+
    unCode1: string;
+
  end;
+
 
+
  InteropStruct2 = Class(TitObject)
+
  public
+
    InteropStruct1Ref: InteropStruct1;
+
    oidInteropStruct1Ref: string;
+
    unCode2: string;
+
  end;
+
 
+
  InteropStruct3 = Class(TitObject)
+
  public
+
    unCode3: string;
+
  end;
+
 
+
  InteropService = Class(Service)
+
  public
+
    Procedure echoStruct1Array(const input:InteropStruct1List; out output:InteropStruct1List);
+
  end;
+
</pre>
+
 
+
Pour appeler ce service :
+
 
+
<pre>
+
Procedure echoStructArray;
+
var inst:ICinteropService;
+
    sin,sout:ICInteropStruct1List;
+
    s1i,s1o:ICInteropStruct1;
+
    idx:Integer; s2:ICInteropStruct2;
+
begin
+
  inst := ICinteropService.Create;
+
 
+
  // Force l’appel distant
+
  inst.LoopMode := mlmNone;
+
 
+
  // Création de la liste d’appel.
+
  //
+
  sin := ClassManager.CreateObjectList('ICInteropStruct1');
+
  //
+
  s1i := ICInteropStruct1.Create;
+
  s1i.unCode1 := 'code1';
+
 
+
  for idx:=0 to 1 do
+
  begin
+
    s2 := ICInteropStruct2.Create;
+
    s2.unCode2 := 'code1-'+inttostr(idx);
+
    s1i.InteropStruct2List.AddRef(s2);
+
  end;
+
  sin.AddRef(s1i);
+
 
+
  // Appel du service
+
  // la liste sout sera initialisée
+
  // par la couche soap
+
 
+
  inst.echoStruct1Array(sin,sout);
+
 
+
 
+
  // Vérification
+
  //
+
  if sin.Count<>sout.Count then
+
  begin
+
    showMessage('echoStruct1Array failed, struct count');
+
    Exit;
+
  end;
+
 
+
  // Test du premier élément
+
  s1i := sin.Refs[0];
+
  s1o := sout.Refs[0];
+
  if s1i.unCode1<>s1o.unCode1 then
+
  begin
+
    showMessage('echoStruct1Array failed, struc1.unCode1');
+
    Exit;
+
  end;
+
  //
+
  //
+
  if s1i.InteropStruct2List.Count<>s1o.InteropStruct2List.Count then
+
  begin
+
    showMessage('echoStruct1Array failed, struc1.struct2.count');
+
    Exit;
+
  end;
+
 
+
  // Test de la liste imbriquée
+
  //
+
  for idx:=0 to s1i.InteropStruct2List.Count-1 do
+
  if (s1i.InteropStruct2List.Refs[idx].unCode2<>s1o.InteropStruct2List.Refs[idx].unCode2) then
+
    begin
+
    showMessage('echoStruct1Array failed, struc1.struct2[].unCode2');
+
    Exit;
+
    end;
+
 
+
  showMessage('echoStruct1 OK');
+
end;
+
</pre>
+
 
+
===3. Tableau de structure dans une structure.===
+
 
+
Un type complexe SOAP peut contenir des tableaux,  1000 modélise un tableau contenu dans un type complexe par un rôle liste composition.
+
 
+
Voir l’exemple précédent.
+
 
+
===4. Type complexe référençant un élément de type complexe.===
+
 
+
Un type complexe SOAP peut référencer un élément de type complexe,  1000 modélise l’élément comme une référence composition référençant le type complexe.
+
 
+
===5. Tableau de type simple dans une structure.===
+
 
+
La ligne 1000 ne permet pas de manipuler nativement des tableaux de type simple comme attribut de classes. Pour permettre l’échange de ces tableaux elle définit des classes Wrapper de types simples puis utilise des tableaux sur ces classes.
+
 
+
Exemple :
+
 
+
Déclaration du service :
+
 
+
{{#images:image20.png|Web_Services_1000}}
+
 
+
<pre>
+
unit InterpServicePackage
+
interface
+
Type
+
  InteropService = Class(TitObject)
+
  public
+
    Procedure echoStruct5(const input:InteropStruct5; out output:InteropStruct5);
+
  end;
+
 
+
  InteropStringWrapper = Class(TitObject)
+
  // cette classe a l’option Wrapper de type simple coché dans ses propriétés soap
+
  public
+
    data : string; // les classes wrapper doivent avoir un attribut data
+
  end;
+
 
+
  Interopstruct5 = Class(TitObject)
+
  public
+
    unArrayOfString: List of InteropStringWrapper;
+
    unCode: string;
+
  end;
+
 
+
Implementation
+
 
+
{InteropService}
+
 
+
Procedure InteropService.echoStruct5(const input:InteropStruct5; out output:InteropStruct5);
+
begin
+
  output := input;
+
end;
+
 
+
end.
+
</pre>
+
 
+
Lorsque ce service est publié en WSDL, la classe wrapper n’apparait pas et un élément de type tableau est publié :
+
 
+
<pre>
+
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://www.sage.com/fr/line1000/InterpServicePackage" xmlns:tns="http://www.sage.com/fr/line1000/InterpServicePackage">
+
<wsdl:types>
+
  <xsd:schema elementFormDefault="qualified" targetNamespace="http://www.sage.com/fr/line1000/InterpServicePackage" xmlns="http://www.w3.org/2001/XMLSchema">
+
  <element name="echoStruct5">
+
    <complexType>
+
    <sequence>
+
      <element name="input" type="tns:Interopstruct5" minOccurs="0" maxOccurs="1"/>
+
    </sequence>
+
    </complexType>
+
  </element>
+
  <complexType name="Interopstruct5">
+
    <sequence>
+
    <element name="unArrayOfString" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
+
    <element name="unCode" type="xsd:string"/>
+
    </sequence>
+
  </complexType>
+
  <element name="echoStruct5Response">
+
    <complexType>
+
    <sequence>
+
      <element name="output" type="tns:Interopstruct5" minOccurs="0" maxOccurs="1"/>
+
    </sequence>
+
    </complexType>
+
  </element>
+
  </xsd:schema>
+
</wsdl:types>
+
<wsdl:message name="echoStruct5">
+
  <wsdl:part name="parameters" element="tns:echoStruct5"/>
+
</wsdl:message>
+
<wsdl:message name="echoStruct5Response">
+
  <wsdl:part name="parameters" element="tns:echoStruct5Response"/>
+
</wsdl:message>
+
<wsdl:portType name="interopservicePortType">
+
  <wsdl:operation name="echoStruct5">
+
  <wsdl:input message="tns:echoStruct5" name="echoStruct5"/>
+
  <wsdl:output message="tns:echoStruct5Response" name="echoStruct5Respond"/>
+
  </wsdl:operation>
+
</wsdl:portType>
+
</pre>
+
 
+
L’import du wsdl de ce service génère le modèle suivant :
+
 
+
{{#images:image21.png|Web_Services_1000}}
+
 
+
L’élément unArrayOfString, tableau de type simple, génère une classe wrapper et une référence liste sur cette classe.
+
 
+
L’appel de la fonction echStruct5 avec le passage des éléments du tableau :
+
 
+
<pre>
+
Procedure TestInteropService.echoStruct5;
+
var inst:ICinteropService;
+
    sin,sout:ICInteropStruct5;
+
    wrp:ICWrapperOfString;
+
    idx:Integer;
+
    ss,stag: string;
+
begin
+
  inst := ICinteropService.Create;
+
  sin := ICInteropStruct5.Create;
+
  sin.unCode := 'code5';
+
  for idx:=0 to 1 do
+
  begin
+
    wrp := ICWrapperOfString.Create;
+
    wrp.data := 'data-'+inttostr(idx);
+
    sin.unArrayOfString.AddRef(wrp);
+
  end;
+
+
  inst.echoStruct5(sin,sout);
+
 
+
  ss := ''; stag := #13;
+
  for idx:=0 to sout.unArrayOfString.Count-1 do
+
  begin
+
    ss := ss+stag+sout.unArrayOfString.refs[idx].data;
+
  end;
+
  showMessage('echoStruct5 :'+ss);
+
end;
+
</pre>
+
 
+
Ce qui génère le message suivant :
+
 
+
<pre>
+
<?xml version="1.0" encoding="UTF-8"?>
+
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
<soap:Body>
+
<echoStruct5 xmlns="http://www.sage.com/fr/line1000/InterpServicePackage">
+
<input>
+
<unArrayOfString>data-0</unArrayOfString>
+
<unArrayOfString>data-1</unArrayOfString>
+
<unCode>code5</unCode>
+
</input>
+
</echoStruct5>
+
</soap:Body>
+
</soap:Envelope>
+
</pre>
+
 
+
==Publication des rôles des classes utilisées comme type complexe soap.==
+
 
+
Lorsqu’ une classe, utilisée dans un service, est publiée dans un descriptif de service (WSDL) elle y inclut tous les rôles référençant une classe du paquet de service. Un rôle référençant une classe à l’extérieur du paquet de service ne sera pas publié.
+
 
+
{{PrecedentSuivant|WebService2|WebService3}}
+
 
+
[[Category:WebServices|3]]
+

Version actuelle en date du 22 août 2009 à 09:40

Sommaire

Les types de données SOAP et Ligne 1000

L’exemple précédent utilisait un service très simple échangeant une chaine de caractère, les types utilisables dans les WS peuvent être plus compliqués et s’appuient sur les types définis par les Schémas XML

Les principaux types simples

SOAP Ligne 1000 Commentaire
string String
int Integer
decimal Currency Le type Decimal peut comporter jusqu’à 128 décimales, la ligne 1000 ne permet que 4 décimales
float, double Double
dateTime TDateTime
date Date
time Time
boolean Boolean
base64Binary String Une chaine encodée contenant les données binaires

Les types SOAP sont reconnus comme des types de données natifs par 1000

Les types binaires

SOAP permet d’échanger des éléments binaires encodé soit en base 64 (base64Binary) soit en hexadécimal (hexBinary).

Pour permettre de manipuler ces données binaires des propriétés base64Binary et hexBinary ont été ajouté au type de données binaires du Framework (TfwPicture, TfwBinary, TfwMemo), et de nouveaux objets techniques ont été introduis :

C’est un type générique permettant de contenir des données binaires.

Exemple d’utilisation :

// Procedure SendClaim;
// 
var inst:TACwsiattachement;
    body:TACClaimDetailType;
    content: TBinaryContent;
begin
  // Objet gestionnaire de binaire
  content := TBinaryContent.Create;
 
  // Chargement de l’objet avec une image
 content.LoadFromFile('d:\Mes documents\Mes images\white house.jpg');
 
  // Descriptif de l’image attendu par le service
 
  body := ClassManager.CreateInstance('TACClaimDetailType');
  body.Name := 'White house';
 
  //
  inst := ClassManager.CreateInstance('TACwsiattachement');
  inst.sendClaim(body,content.base64Binary);
end;

Exemple :

Cet exemple montre comment appelé un service exécutant l’écho d’un paramètre binaire :

Le service :

Type
  InteropService = Class(TServiceLocal)
  Procedure echoBase64(const input:base64Binary; out output:base64Binary); 
 end;
 
Procedure InteropService.echoBase64(const input:base64Binary; out output:base64Binary);
begin
  output := input;
end;

Le proxy local du service :

Type
  ICinteropservice = Class(TServiceDistant)
  public
    Procedure echoBase64(const input:base64Binary; out output:base64Binary);
  end;
 
Procedure ICinteropservice.echoBase64(const input:base64Binary; out output:base64Binary);
begin
 //Remote procedure, do not code
end;

L’appel du service en utilisant des chaînes de caractères :

//Procedure echoBase64;
var inst:ICinteropService;
    sin:string;
    sout:base64binary;
    contin,contout:TBinaryContent;
begin
  inst := ClassManager.CreateInstance('ICinteropService');
 
  // Une chaine a transmettre
  sin := 'coucou';
 
  // Converti la chaine en utilisant un BinaryContent
  // 
  contin := TBinaryContent.Create;
  contin.AsString := sin;
 
  // appel du service
  // sout contient la réponse encodée
  inst.echoBase64(contin.base64Binary,sout);
 
  // converti la réponse 
  //
  contout := TBinaryContent.Create;
  contout.base64Binary := sout;
 
  // compare le résultat
  //
  if sin<>contout.AsString
     then showMessage('echoBase64 failed')
     else showMessage('echoBase64 OK');
end;

L’appel du service en utilisant des TStringList

//Procedure echoBase64_2;
var inst:ICinteropService;
    lsin,lsout:TStringList;
    sout: base64binary;
begin
  inst := ClassManager.CreateInstance('ICinteropService');
  lsin := TStringList.Create;
 
  lsin.LoadFromFile('c:\myText-1.txt');
 
  inst.echoBase64(lsin.base64binary,sout);
  lsout := TStringlist.Create;
  lsout.base64Binary := sout;
  lsout.SaveToFile('c:\myText-2.txt');
end;

Même exemple en utilisant une compression :

//Procedure echoBase64_3;
var inst:ICinteropService;
    lsin,lsout:TStringList;
    sout: base64Binary;
begin
  inst := ClassManager.CreateInstance('ICinteropService');
  lsin := TStringList.Create;
  lsin.LoadFromFile('c:\myText-1.txt');
 
  inst.echoBase64(lsin.getAsBase64Binary(b64ZlibNoSig),sout);
 
  lsout := TStringlist.Create;
  lsout.setAsBase64Binary(sout,b64ZLibNoSig);
  lsout.SaveToFile('c:\myText-3.txt');
end;

Les énumérés

Le protocole SOAP permet de définir des énumérations de valeurs pour préciser les valeurs possibles d’un paramètre de message.

Un énuméré SOAP correspond à un énuméré Ligne 1000.

Par exemple pour définir un service effectuant l’écho d’un énuméré :

//Défini un énuméré.
EchoNum = (cstEcho1, cstEcho2) ;
 
//Procedure echoEnum(input:EchoEnum; out output:EchoEnum);
begin
  output := input;
end;

Pour appeler ce service, (le service a été importé en utilisant un préfixe de paquet IC) :

ICEchoNum = (cstEcho1,cstEcho2) ;
 
// Procedure echoEnum;
//
var inst:ICinteropService; sin,sout:ICEchoEnum;
begin
  sin := cstEcho1;
  inst := ClassManager.CreateInstance('ICinteropService');
  inst.echoEnum(cstEcho1,sout);
  if sin<>sout
     then showMessage('echoEnum failed')
     else showMessage('echoEnum OK');
end;

Les valeurs énumérées sont transmises par leur constantes et non par leur index, l’appel précédent génère le message suivant :

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<soap:Body>
<echoEnum xmlns="http://www.sage.com/fr/line1000/InterpServicePackage">
<input>cstEcho1</input>
</echoEnum>
</soap:Body>
</soap:Envelope>

Les types complexes (structures)

Le protocole SOAP permet d’échanger des types complexes sous forme de structure.

Une structure SOAP correspond à une classe Ligne 1000.

Appel d’un service effectuant l’écho d’une structure :

//Procedure echoStruct;
//
var inst:DSService; structin,structout:DSSOAPStruct;
begin
  // La structure est une classe 1000
  structin := ClassManager.CreateInstance('DSSOAPStruct');
  structin.varString := 'coucou';
  structin.varInt := 1;
  structin.varFloat := 1.0;
 
  // appel du service
  inst := ClassManager.CreateInstance('DSService');
 
  // l’instance en retour est créée par le framework
  inst.echoStruct(structin,structout);
 
  showMessage('Result:'+structout.varString);
end;

Les extensions de type complexe.

Une extension de type complexe permet d’enrichir un type complexe préalablement défini, la correspondance en Ligne 1000 est une classe héritant de la classe enrichie.

Info-20px.png Note : Lors de la publication d’un service toutes les classes dérivées d’une classe publiée sont publiées.

Les tableaux et références.

Le protocole SOAP permet d’échanger des ensembles de données sous forme de tableaux. L’implémentation de 1000 distingue les tableaux de type simple des tableaux de structure.

Scénarii Correspondance ligne 1000
Tableau de type simple (t1) passé en paramètre Tableau ouvert du type simple (t1) dans les paramètres de l’opération

const p : Array of t1 ;

Tableau de structure (s1) en paramètre Liste d’objet de la classe représentant la structure (s1) dans les paramètres de l’opération

const p : s1List ;

Tableau de structure (s1) dans une structure (s2) Rôle liste vers la structure (s1) du tableau dans la classe de la structure (s2)
Type complexe (s1) référençant un type complexe (s2) Rôle référence vers la structure (s1) dans la classe de la structure (s2)
Tableau de type simple (t1) dans une structure (s2). Rôle liste vers une classe wrapper du type simple (t1) dans la classe de la structure (s2)

Tableau de type simple passé en paramètre.

Exemple:

Procedure echoArrayOfString(const input:Array of string; out output:Array of string);
var idx:Integer;
begin
  // Implémentation du service
  // Copie le tableau élément par élément.
  //
  for idx:=0 to length(input)-1 do
   output[idx] := input[idx];
End ;

Pour appeler ce service :

Procedure echoArrayOfString ;
var inst:ICinteropService; sin,sout:Array of string;
    idx:Integer; s1,s2:string;
begin
  inst := ICinteropService.Create;
 
  // Initialise le tableau par une constante
  sin := ['Ah','que','coucou'];
 
  // Appel du service, sout sera initialisée 
  // par la couche soap
  inst.echoArrayOfString(sin,sout);
 
 
  // Verification
  // 
  s1 := '';
 
  for idx:=0 to length(sin)-1 do
   s1 := s1+sin[idx];
 
  s2 := '';
  for idx:=0 to length(sout)-1 do
   s2 := s2+sout[idx];
 
  if s1<>s2
     then showMessage('echoArrayString failed :'+s1+':'+s2)
     else showMessage('echoArrayString OK');
end;

Tableau de type complexe passé en paramètre.

Un type complexe étant une classe un tableau de type complexe est une liste d’objet de cette classe

Par exemple pour échanger une liste de SOAPStruct

Type
  InteropStruct1 = Class(TitObject)
  public
    InteropStruct2List: CompositionList of InteropStruct2;
    InteropStruct2Ref: InteropStruct2;
    InteropStruct3Ref: InteropStruct3;
    oidInteropStruct2Ref: string;
    oidInteropStruct3Ref: string;
    unCode1: string;
  end;
 
  InteropStruct2 = Class(TitObject)
  public
    InteropStruct1Ref: InteropStruct1;
    oidInteropStruct1Ref: string;
    unCode2: string;
  end;
 
  InteropStruct3 = Class(TitObject)
  public
    unCode3: string;
  end;
 
  InteropService = Class(Service)
  public
    Procedure echoStruct1Array(const input:InteropStruct1List; out output:InteropStruct1List);
  end;

Pour appeler ce service :

Procedure echoStructArray;
var inst:ICinteropService;
    sin,sout:ICInteropStruct1List;
    s1i,s1o:ICInteropStruct1;
    idx:Integer; s2:ICInteropStruct2;
begin
  inst := ICinteropService.Create;
 
  // Force l’appel distant
  inst.LoopMode := mlmNone;
 
  // Création de la liste d’appel.
  //
  sin := ClassManager.CreateObjectList('ICInteropStruct1');
  //
  s1i := ICInteropStruct1.Create;
  s1i.unCode1 := 'code1';
 
  for idx:=0 to 1 do
   begin
     s2 := ICInteropStruct2.Create;
     s2.unCode2 := 'code1-'+inttostr(idx);
     s1i.InteropStruct2List.AddRef(s2);
   end;
  sin.AddRef(s1i);
 
  // Appel du service
  // la liste sout sera initialisée 
  // par la couche soap
 
  inst.echoStruct1Array(sin,sout);
 
 
  // Vérification
  //
  if sin.Count<>sout.Count then
   begin
     showMessage('echoStruct1Array failed, struct count');
     Exit;
   end;
 
  // Test du premier élément
  s1i := sin.Refs[0];
  s1o := sout.Refs[0];
  if s1i.unCode1<>s1o.unCode1 then
   begin
     showMessage('echoStruct1Array failed, struc1.unCode1');
     Exit;
   end;
  //
  //
  if s1i.InteropStruct2List.Count<>s1o.InteropStruct2List.Count then
   begin
     showMessage('echoStruct1Array failed, struc1.struct2.count');
     Exit;
   end;
 
  // Test de la liste imbriquée
  //
  for idx:=0 to s1i.InteropStruct2List.Count-1 do
   if (s1i.InteropStruct2List.Refs[idx].unCode2<>s1o.InteropStruct2List.Refs[idx].unCode2) then
    begin
     showMessage('echoStruct1Array failed, struc1.struct2[].unCode2');
     Exit;
    end;
 
  showMessage('echoStruct1 OK');
end;

Tableau de structure dans une structure.

Un type complexe SOAP peut contenir des tableaux, 1000 modélise un tableau contenu dans un type complexe par un rôle liste composition.

Voir l’exemple précédent.

Type complexe référençant un élément de type complexe.

Un type complexe SOAP peut référencer un élément de type complexe, 1000 modélise l’élément comme une référence composition référençant le type complexe.

Tableau de type simple dans une structure.

La ligne 1000 ne permet pas de manipuler nativement des tableaux de type simple comme attribut de classes. Pour permettre l’échange de ces tableaux elle définit des classes Wrapper de types simples puis utilise des tableaux sur ces classes.

Exemple :

Déclaration du service :

image20.png

unit InterpServicePackage
interface
Type
  InteropService = Class(TitObject)
  public
    Procedure echoStruct5(const input:InteropStruct5; out output:InteropStruct5);
  end;
 
  InteropStringWrapper = Class(TitObject)
  // cette classe a l’option Wrapper de type simple coché dans ses propriétés soap
  public
    data : string; // les classes wrapper doivent avoir un attribut data
  end;
 
  Interopstruct5 = Class(TitObject)
  public
    unArrayOfString: List of InteropStringWrapper;
    unCode: string;
  end;
 
Implementation
 
{InteropService}
 
Procedure InteropService.echoStruct5(const input:InteropStruct5; out output:InteropStruct5);
begin
  output := input;
end;
 
end.

Lorsque ce service est publié en WSDL, la classe wrapper n’apparait pas et un élément de type tableau est publié :

<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" xmlns="http://schemas.xmlsoap.org/wsdl/" targetNamespace="http://www.sage.com/fr/line1000/InterpServicePackage" xmlns:tns="http://www.sage.com/fr/line1000/InterpServicePackage">
 <wsdl:types>
  <xsd:schema elementFormDefault="qualified" targetNamespace="http://www.sage.com/fr/line1000/InterpServicePackage" xmlns="http://www.w3.org/2001/XMLSchema">
   <element name="echoStruct5">
    <complexType>
     <sequence>
      <element name="input" type="tns:Interopstruct5" minOccurs="0" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
   <complexType name="Interopstruct5">
    <sequence>
     <element name="unArrayOfString" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
     <element name="unCode" type="xsd:string"/>
    </sequence>
   </complexType>
   <element name="echoStruct5Response">
    <complexType>
     <sequence>
      <element name="output" type="tns:Interopstruct5" minOccurs="0" maxOccurs="1"/>
     </sequence>
    </complexType>
   </element>
  </xsd:schema>
 </wsdl:types>
 <wsdl:message name="echoStruct5">
  <wsdl:part name="parameters" element="tns:echoStruct5"/>
 </wsdl:message>
 <wsdl:message name="echoStruct5Response">
  <wsdl:part name="parameters" element="tns:echoStruct5Response"/>
 </wsdl:message>
 <wsdl:portType name="interopservicePortType">
  <wsdl:operation name="echoStruct5">
   <wsdl:input message="tns:echoStruct5" name="echoStruct5"/>
   <wsdl:output message="tns:echoStruct5Response" name="echoStruct5Respond"/>
  </wsdl:operation>
 </wsdl:portType>

L’import du wsdl de ce service génère le modèle suivant :

image21.png

L’élément unArrayOfString, tableau de type simple, génère une classe wrapper et une référence liste sur cette classe.

L’appel de la fonction echStruct5 avec le passage des éléments du tableau :

Procedure TestInteropService.echoStruct5;
var inst:ICinteropService;
    sin,sout:ICInteropStruct5;
    wrp:ICWrapperOfString;
    idx:Integer;
    ss,stag: string;
begin
  inst := ICinteropService.Create;
  sin := ICInteropStruct5.Create;
  sin.unCode := 'code5';
  for idx:=0 to 1 do
   begin
     wrp := ICWrapperOfString.Create;
     wrp.data := 'data-'+inttostr(idx);
     sin.unArrayOfString.AddRef(wrp);
   end;
 
  inst.echoStruct5(sin,sout);
 
  ss := ''; stag := #13;
  for idx:=0 to sout.unArrayOfString.Count-1 do
   begin
     ss := ss+stag+sout.unArrayOfString.refs[idx].data;
   end;
  showMessage('echoStruct5 :'+ss);
end;

Ce qui génère le message suivant :

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soap:Body>
<echoStruct5 xmlns="http://www.sage.com/fr/line1000/InterpServicePackage">
<input>
<unArrayOfString>data-0</unArrayOfString>
<unArrayOfString>data-1</unArrayOfString>
<unCode>code5</unCode>
</input>
</echoStruct5>
</soap:Body>
</soap:Envelope>

Publication des rôles des classes utilisées comme type complexe soap.

Lorsqu’ une classe, utilisée dans un service, est publiée dans un descriptif de service (WSDL) elle y inclut tous les rôles référençant une classe du paquet de service. Un rôle référençant une classe à l’extérieur du paquet de service ne sera pas publié.

Web Services (ws)Développement DSM





Whos here now:   Members 0   Guests 0   Bots & Crawlers 1
 
Outils personnels