Services WEB



XML vs JSON


Les règles du jeu XML


Elles sont extrêmement simples. Les informations doivent être :

  un schéma est lui même un fichier XML qui en décrit un autre.

commençons par une partie d'entête :

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
<xsd:annotation>
<xsd:documentation xlm:lang="fr">
XML Schema pour la liste des cours AF400.
</xsd:documentation>
</xsd:annotation>

puis la partie descriptive en elle même:

<xsd:element name="AF400" type="AF400Type"/> 

<xsd:complexType name="AF400Type">
<xsd:sequence>
<xsd:element name="COURS" type="CoursType" minOccurs="1"/>
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="CoursType"> 
<xsd:sequence>
<xsd:element name="TEXTE" type="xsd:string"/>
<xsd:element name="TYPE" type="xsd:string"/>
<xsd:element name="SRCFIL" type="xsd:string"/>
<xsd:element name="SRCLIB" type="xsd:string"/>
<xsd:element name="SRCMBR" type="xsd:string"/>
<xsd:element name="CHEMIN" type="xsd:string"/>
<xsd:element name="SUJET" type="xsd:string"/>
<xsd:element name="MOT-DIRECTEUR type="MotType"/>
<xsd:element name="DATE" type="xsd:string"/>
</xsd:sequence>
< /xsd:complexType>
<xsd:complexType name="MotType"> 
<xsd:sequence>
<xsd:element name="MOTCLE1 type="xsd:string" minOccurs="1"/>
<xsd:element name="MOTCLE2 type="xsd:string"/>
<xsd:element name="MOTCLE3 type="xsd:string"/>
<xsd:element name="MOTCLE4 type="xsd:string"/>
<xsd:element name="MOTCLE5 type="xsd:string"/>
</xsd:sequence>
< /xsd:complexType>

On peut définir un élément (xsd:element) ou un attribut (xsd:attribut), chacun pouvant faire référence à un type  
(voyez ici la liste des types admis dans un schéma XML)  comme xsd:nonNegativeNumber
ou bien faire référence à un type définit dans le scéma.


Les types définis peuvent être :


Lorsqu'un document XML possède une DTD ou un Schéma associé et la/le respecte, on dit qu'il est valide.

Lorsqu'il respecte seulement les règles de la grammaire XML (balises fermées, correctement imbriquées) on dit qu'il est bien formé.



Aujourd'hui JSON est de plus en plus utilisé.

JSON (JavaScript Object Notation) est un format de données textuelles dérivé de la notation des objets du langage JavaScript (Wikipedia)

 

ce qui s'écrit comme cela en XML   s'écrit comme cela en JSON
<producteurs>
  <producteur>
    <numero>45</numero>
   <commune>Reims</commune>
    <appellation>13</appellation>
  </producteur>
</producteurs>
->

{
   "producteurs":  {
       "producteur": {
            "numero":45,
            "commune":"Reims",
            "appellation":13  
       }
    }
}


D'ailleurs vous trouverez ici deux fonctions bien pratiques XML2JSON et JSON2XML écrites en Java.

Un élément peut contenir un objet, une valeur ou un tableau de valeurs, marqué alors par [ et ]

<PO>
<id>103</id>
<orderDate>2014-06-20</orderDate>
<customer>
<cid>888</cid>
</customer>
<items>
<item>
<partNum>872-AA</partNum>
<shipDate>2014-06-21</shipDate>
<productName>Lawnmower</productName>
<USPrice>749.99</USPrice>
<quantity>1</quantity>
</item>
<item>
<partNum>837-CM</partNum>
<productName>Digital Camera</productName>
<USPrice>199.99</USPrice>
<quantity>2</quantity>
<comment>2014-06-22</comment>
</item>
</items>
</PO>

devient (remarquez le tableau de "item")

{
"PO":{
"id": 103,
"orderDate": "2014-06-20",
"customer": {"@cid": 888},
"items": {
"item": [ { "partNum": "872-AA", "productName": "Lawnmower", "quantity": 1, "USPrice": 749.99, "shipDate": "2014-06-21" }, { "partNum": "837-CM", "productName": "Digital Camera", "quantity": 2, "USPrice": 199.99, "comment": "2014-06-22" } ]
}
}
}

 


Présentation de l'architecture
web-services

(ou services web)


   

Un web-service : c'est un logiciel qui interagis avec d'autres au moyen de protocoles universels (http, xml...)


Il existe deux types de services WEB


Précisions sur SOAP


Précisions sur WSDL

Et sur nos systèmes IBM i?


IBM proposait déjà des mécanismes d'appel de programmes (RPG ou COBOL) depuis une application Java : PCML : langage de description du programme
<pcml version="1.0">
 <!-- Create a Data Structure -->
 <struct name ="custinfo" >
   < data name ="Number" type="char" length= " 7"
            usage="inputoutput" init="0014400"> </data>
   < data name ="Name"   type="char" length= " 40"
            usage="inputoutput" init=" "> </data>
 </struct>
 <!-- Program getcust -->
 <program name="getcust"
              path="/QSYS.lib/MABIB.lib/GETCUST.pgm" >
   < data name ="gotback" type=" struct"
            usage="inputoutput" struct="custinfo"> </data>
 </program >
</pcml>


public static void main(String[] argv)
{
       AS400 as400System = new AS400();
       ProgramCallDocument pcml = null;
       String msgId, msgText;
       Object value = null;
       try {
           System.out. println ("Creating ProgramCallDocument for GetCust pgm.");
           pcml = new ProgramCallDocument(as400System, "GETCUST");
           boolean ok = pcml.callProgram("getcust");
           System.out.println(" rc is---> " + rc);
           if (!ok)
               { /* Retrieve list of AS/400 messages & display them */ }
           else
               {
                  value = pcml.getValue("getcust.gotback.Name");
                  System.out.println("Customer name: " + value);
               }
       } catch (PcmlException exc) {
           System.out.println("*** Call to getcust failed. ***");
           Sy ste m. exit (0);
       }
       System.exit(0 );
} // end main method

WDS Client V7et RDI for SOA contiennent les mêmes fonctionnalités (mais avec un nouvel assistant pour RDI)

Cliquez sur parcourir pour modifier les caractéristiques du service

1/ le choix *SRVPGM ou *PGM

2/ par le bouton Modifier, la connexion :

Vous devrez indiquer aussi, le(les) type(s) de service(s) à générer

 

Une page de test est générée puis lancée


IBM i V7 : Serveur intégré Liberty

 

Il s'agit du nouveau serveur d'application intégré à l'OS pour distribuer les applications Java.

 

Ce serveur support JSF, JSP, servlets et services web, et implique peu de ressources et d'administration, c'est le même que celui utilisé par DB2 WebQUERY,

Il est basé sur une version de WAS nommée Liberty profile

 

Lancez le serveur d'administration HTTP, si ce n'est déjà fait par STRTCPSVR *HTTP HTTPSVR(*ADMIN)

Puis loggez vous sur http://<votreas400>:2001/HTTPAdmin/




et voilà, vérifiez les informations récapitulatives (regardez les ports IP attribués automatiquement)

liste des services (l'assistant créé un exemple nommé ConvertTemp)

 

Le serveur est créé avec un service : ConvertTemp, il faudra utiliser "Manage Deployed Services/ Deploy" pour en créer d'autres.


Depuis 2010, un groupe PTF permet de déléguer des droits via l'administration graphique.

Sans cette délégation, il faut être *ALLOBJ et *IOSYSCFG pour administrer les serveurs mais aussi déployer les web services.

Ajoutons un utilisateur à la liste des utilisateurs autorisés :

Il faut ensuite spécifier les droits (globalement par type de serveur ou serveur par serveur)


Déployons un programme RPG

Ici W_RECAP de BDVIN0, attendant une zone PR_CODE, et retournant une DS nommée INFOCENTRE,
    ce pgm RPG a été compilé avec PGMINFO(*PCML:*MODULE) , en COBOL ->PROCESS OPTIONS PGMINFO(PCML MODULE)

en V5R40 il faut SI27065 pour activer cette option.

SI55531 (7.2) et SI55340 (7.1) apportent l'option *DCLCASE permettant de demander le respect de la casse quant aux noms dans le PCML

Si vos programmes sont dans un ASP indépendant, Utilisez plutôt l'option Browse...

Et indiquez /iASP/QSYS.LIB/mabib.LIB/monpgm.PGM ou monsrvpgm.SRVPGM

ou /iASP est le point de montage de votre ASP indépendant

 

Depuis les correctifs d'Avril 2020, vous devrez saisir selon cette dénomination "IFS"


vous remarquerez l'accès à la nouvelle possibilité de web services en SQL

Indiquez ensuite, le nom public du service et un texte explicatif


puis, précisez le sens d'utilisation des paramètres (automatiquement découverts par l'assistant grâce à PGMINFO)

Si vous avez oublié l'option PGMINFO ou si vous appelez un CL (CLLE et non CLP), il faudra faire référence à un fichier PCML, pour faire apparaître les paramètres

SI vous voulez lancer un COBOL (non ILE) ou un RPG 3, faite un CLLE qui appelle pour vous.

Un fichier PCML devant être structuré comme suit :

<pcml version="4.0"> 
  <program name="MONPGM" path="/QSYS.LIB/MABIB.LIB/MONPGM.PGM">
     <data name="P1" type="char" length="3" usage="inputoutput" />
     <data name="P2" type="packed" length="2" precision="0" usage="inputoutput" />
  </program>
</pcml>

Dans un ASP indépendant

<pcml version="4.0"> 
  <program name="MONPGM" path="/IASP/QSYS.LIB/MABIB.LIB/MONPGM.PGM">
     <data name="P1" type="char" length="3" usage="inputoutput" />
     <data name="P2" type="packed" length="2" precision="0" usage="inputoutput" />
  </program>
</pcml>

avec une structure :

<pcml version="4.0"> 
<!-- exemple avec une structure complexe -->
 <struct name="INFOCENTRE">
   <data name="PR_CODE" type="int" length="4" precision="31" usage="inherit" />
   <data name="PR_NOM" type="char" length="50" usage="inherit" />
   <data name="PR_TEL" type="char" length="20" usage="inherit" />
   <data name="APPEL00001" type="char" length="80" usage="inherit" />
   <data name="NBVIN" type="packed" length="3" precision="0" usage="inherit" />
   <data name="ENCAVE" type="char" length="3" usage="inherit" />
   <data name="CEPAGE" type="char" length="25" usage="inherit" />
   <data name="NBCEPAGE" type="packed" length="3" precision="0" usage="inherit" />
 </struct>
<!-- le pgm avec ses paramètres -->
 <program name="AVECDS" path="/QSYS.LIB/MABIB.LIB/AVECDS.PGM">
   <data name="PR_CODE" type="packed" length="9" precision="0" usage="inputoutput" />
  <data name="INFOCENTRE" type="struct" struct="INFOCENTRE" count="500" usage="inputoutput" />
 </program>
</pcml>

voici les types reconnus par PCML :  

 

un paramètre déclaré const sera utilisé en input, sinon inputoupout


Pour infos, voici un extrait du programme déployé ici, en ce qui concerne les paramètres :

 H PGMINFO(*PCML : *MODULE)
DPR_code S 6 0
DINFOCENTRE E DS qualified


C *entry plist
C parm pr_code
C parm infocentre

En free

Ctl-opt PGMINFO(*PCML : *MODULE);
Dcl-DS INFOCENTRE_T EXT EXTNAME('INFOCENTRE') Qualified Template;
DCL-PI *n;
pr_code packed(6:0);
infocentre likeds(infocentre_T);
End-PI;

 

Des PTF de 2009, apportent la possibilité de gérer en variable (integer uniquement) le nombre d'occurrences d'une structure

Enfin en Juin 2015, SI56823(7.2) propose de rechercher automatiquement le nombre d'occurrences dans une variable placée avant la DS et nommée comme la DS suivit de _LENGTH

si vous décochez l'option, vous retrouvez l'affichage du dessus permettant de saisir le nbr d'occurrences


Cela permet de gérer les DS imbriquées :

Indiquez ensuite le profil utilisateur qui lancera le programme

indiquez aussi, la liste des bibliothèques à utiliser



Si vous travaillez avec un ASP indépendant, vous saisirez /IASP/QSYS.LIB/AUTREBIB.LIB

Le service déployé, vous le retrouverez ici, vous pourrez en gérer certaines caractèristique par Properties


(properties, permet de changer le profil ou d'éditer le fichier WSDL)

le WSDL pouvant être produit dynamiquement ou de manière statique (nouveauté) et donc être édité par vos soins

passez la paramètre "Web service endpoint generation" à Static, appliquez, puis éditer le wsdl.



Important si vous masquez votre Serveur IBM i derrière un nom de domaine public.

Il faudra alors remplacer (par exemple)
   <soap:address location="http://as400.volubis.intra:10030/web/services/W_RECAP"/>

par

   <soap:address location="http://www.volubis.fr:10030/web/services/W_RECAP"/>


Il y avait une option de test, qui a disparue en 7.3. Pour tester utilisez des produits standard comme soapUI

Téléchargez, Installez et lancez le produit.

Créez un nouveau projet en indiquant les coordonnées pour acquérir le fichier WSDL sur le system i.

renseignez les valeurs envoyées en remplacant les ? par vos données (ici le producteur 45)

lancez (flèche verte en haut à gauche de la fenêtre Request1)


Si vous rencontrez des problèmes, voyez

* pour passer en pcml 7, installez SI66149 (7.2) ou SI66150 (7.3)

puis ajoutez une variable d'environnement niveau système
ADDENVVAR ENVVAR(QIBM_RPG_PCML_VERSION) VALUE(7.0) LEVEL(*SYS)

Les scripts suivants (dans /Qibm/ProdData/os/webservices/V1/server/bin) permettent d'automatiser les déploiements

createWebServicesServer.sh
deleteWebServicesServer.sh
getWebServiceProperties.sh
getWebServicesServerProperties.sh
installWebService.sh
listWebServices.sh
listWebServicesServers.sh
setWebServiceProperties.sh
setWebServicesServerProperties.sh
startWebService.sh
startWebServicesServer.sh
stopWebService.sh
stopWebServicesServer.sh
uninstallWebService.sh

 

pour le passage en production d'un service WEB, il faut passer en production l'objet *PGM (l'exécutable) et l'enregistrer ensuite par le script installWebService.sh

Des correctifs (2015) proposent un nouveau paramètre -parameterUsage

permettant d'indiquer le sens d'utilisation des paramètres i (input) , o (output) , io (input/output)


-parameterUsage GetClientDEp:i,o:UpdateClientCA:i,i,io

pour vous familiariser avec les scripts, passez la commande QSH (émulateur de shell Unix) sur une ligne de commande IBM i

puis CD /qibm/proddata/os/webservices/v1/server/bin


ls vous affiche le contenu du répertoire, pwd vous affiche le répertoire en cours, etc...


si vous tapez le nom d'un script -help , il vous affiche une aide "limitée" , par exemple :
installWebservice.sh -help 

Command usage:

installWebService.sh
-server 'server-name' -programObject 'program-object'
[-service 'service-name'] [-pcml 'pcml-file'] [-userid 'userid']
[-detectFieldLengths] [-serviceType '*SOAP11|*SOAP12|*REST']
[-targetNamespace 'target-namespace']
[-parameterUsage 'parameter-list'] [-propertiesFile 'property-file']
[-libraryList 'library-list'] [-libraryListPosition '*FIRST|*LAST']
[-disableNillableWSDLElements] [-disableOptionalWSDLElements]
[-addUnderscoreToWSDLElementNames] [-printErrorDetails] [-help]


Quelques Exemples :

installWebService.sh
-server 'WFORMATION'
-programObject '/QSYS.LIB/FORMATIONX.LIB/GETVINS.PGM'
-service 'GETVINJ' -userid 'CM' -detectFieldLengths
-serviceType '*REST' -propertiesFile '/home/CM/getvins.properties'
-libraryList 'FORMATIONX;BDVIN1' -libraryListPosition '*LAST'

fichier properties :
uri.path.template=/
GETVINS.uri.path.template=/getvinj/{uncode}
GETVINS.wrap.input.parameters=false
GETVINS.wrap.output.parameter=true
GETVINS.http.request.method=GET
GETVINS.consumes=*/*
GETVINS.produces=application/xml, application/json
GETVINS.response.code.parameter=
GETVINS.http.headers.parameter=
GETVINS.CODE.usage=input
GETVINS.CODE.pathparam=uncode
GETVINS.NOM.usage=output
GETVINS.DESVINS_LENGTH.usage=output
GETVINS.DESVINS.usage=output
 IWS00102I - Command completed successfully.
$
getWebServiceProperties.sh  -server WFORMATION -service GETVINJ

Name: GETVINJ
Description: GETVINJ
Startup type: Automatic
Type: REST
Status: Stopped
Runtime user ID: CM
Install path: /www/WFORMATION/webservices/services/GETVINJ
Program object path: /QSYS.LIB/FORMATIONX.LIB/GETVINS.PGM
PCML file path: /www/WFORMATION/webservices/services/GETVINJ/GETVINJ.pcml
Library list: FORMATIONX;BDVIN1;
Library list position: *LAST
Connection pool properties
Default CCSID: *USERID
Use maintenance threads: true
Cleanup interval (seconds): 300
Maximum number of connections: *NOMAX
Maximum inactivity time (seconds): 3600
Maximum life time (seconds): 86400
Maximum use count: *NOMAX
Maximum use time (seconds): *NOMAX
Transport metadata:
Transport headers:
stopWebservicesServer.sh -server WFORMATION 
IWS00102I - Command completed successfully.
$

startWebservicesServer.sh -server WFORMATION
IWS00102I - Command completed successfully.
$
saveWebServices.sh -server WFORMATION -saveFile /QSYS.LIB/LIBSAVF.LIB/WFORMATION.FILE
-serviceList *ALL
IWS00102I - Command completed successfully.
$

-> le fichier WFORMATION (SAVF) a bien été créé dans LIBSAVF

pour passer la commande directement depuis un CL

QSH CMD('/qibm/proddata/os/webservices/V1/server/bin/<votrescript.sh> paramètre1 paramètre2 ...')



Enfin, les Groupes PTF de 2012 (SF99115 level 23 et SF99368 level 11) améliorent le serveur de Web service pour le faire utiliser Axis 1.5 (à la place de 1.3)

(voyez ce Wiki pour accéder aux dernières nouveautés)

Une fois installés ces correctifs vous verrez apparaître une option de migration

Vous aurez aussi d'autres options :

la V7R2 amenant une nouvelle version de PCML (6) supportant les dates, les restrictions concernant les paramètres s'estompent


• Déclarons un programme ayant des dates en paramètre

le service est déployé , testons

les variables DATE doivent être saisie au format xs:date

sans paramétrage particulier, si vous recevez une erreur IWAB0383E

avec la propriété Java com.ibm.xml.xlxp.jaxb.opti.level=0, cela fonctionne (mais cela ralentit le serveur)

Serveur/properties/JVM options -> bouton EDIT



Résultat ->

le format pour les timestamp est xs:dateTime



EN Juin 2018, Les PTF SI67769/SI67772 (7.2) ou SI67770/SI67773 (7.3) améliore la gestion des champs date/heure.

 

ce programme

exposé en tant que web service retournant du XML affiche ceci :


EN JSON :


Les paramètres sont reconnus grâce à PCML, indiquez le sens d'utilisation


Ensuite précisez




Avec SI56883, vous pouvez préciser plusieurs types de média en retour et le type est libre (text/html, par ex.)


Il faut alors fixer la variable d'environnement CONTENT_TYPE pour préciser dynamiquement le type retourné à chaque appel.

Ensuite, Indiquez le profil utilisateur à utiliser

la liste de bibliothèques

les informations d'entête HTTP à transporter, puis vous arrivez sur l'écran final







Quelques tests

*PATH_PARAM (celui déployé ci-dessous)



*QUERY_PARAM

nouveau service

paramètre en entrée



Format de sortie JSON


Format de sortie HTML

Exemple

Avec les tables résultat de CALL CREATE_SQL_SAMPLE




Résultat


Pour retourner du binaire (ce qui n'est pas officiellement supporté) il faut convertir en base64


Ces nouveaux Web services peuvent être testés par les dernières versions de SoapUI


Indiquez l'URL


SoapUI va découvrir les paramètres (ici {prod}) , assignez des valeurs et exécutez :




ou par POSTMAN, plus simple pour tester les web services REST

ici la création d'un client par POST



Un seul paramètre peut être indiqué Input Source *NONE


Le pgm attend une DS ClientRecu composée des champs indiqués en haut (id, reference,...)

Il retourne plusieurs paramètres :

Les champs sont transmis en minuscules, car le programme utilise PGMINFO(*PCML:*MODULE : *DCLCASE)

Tout cela devrait continuer d'évoluer rapidement...

Copyright © 2017 VOLUBIS