Les règles du jeu XML
Elles sont extrêmement simples. Les informations doivent être :
- soit encadrées par des balises ouvrantes(ex. <LIVRE>) et fermantes (ex. </LIVRE>) (contrairement à HTML où ses ces dernières n'étaient pas toujours obligatoires). On parle alors d'éléments. Les éléments doivent s'imbriquer proprement les uns dans les autres : aucun chevauchement n'est autorisé. Les éléments vides sont permis, selon le format <ELEMENTVIDE/>.
- soit incluses à l'intérieur même des balises : on parle alors d'attributs. Exemple : <LIVRE SUJET="XML">. Ici l'attribut SUJET de l'élément LIVRE a la valeur "XML" . En XML, contrairement à HTML, les valeurs des entités doivent toujours être encadrées par des guillemets (simples ou doubles).
- Soit encore définies sous forme d'entités. Les entités sont des abréviations. Par ex; si "Extensible Markup Language" est déclaré comme une entité associée à la notation "xml"; cette chaîne de caractères pourra être abrégée en "&xml;" dans tout le fichier XML. Une entité peut aussi représenter un fichier XML externe tout entier. (inclusion de fichier XML)
Les caractères < , > , & et " doivent être remplacés par les entités < , > , & et "e;dans les valeurs de type texte.
- le document peut enfin contenir :
- des commentaires sous la forme <!-- le commentaire -->
- des processing instructions (PI) c'est à dire des instructions destinées à une application particulière sous la forme <?nom-application instructions-spécifiques?>
par exemple, une "processing instruction" destinées à XML lui même commence souvent les documents XML.
- <?xml version="1.0" encoding="ISO-8859-1" ?> (version de XML et jeu de caractères des données, ici "latin-1", c.a.d le nôtre)
- La structure arborescente du document XML (intitulé des balises, imbrications des balises, caractère obligatoire ou facultatif des balises et de leur ordre de succession) peut être déclarée formellement dans le corps du document XML ou dans un fichier séparé.
Cette déclaration s'appelle une Définition de Type de Document (DTD) ou un schéma XML (XSD)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 :
- xsd:complexType (structure)
- xsd:simpleType (donnée élémentaire, mais subissant, par exemple, des contrôles particuliers)
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" } ]
}
}
}
Un web-service : c'est un logiciel qui interagis avec d'autres au moyen de protocoles universels (http, xml...)
<?xml version="1.0"?> |
<?xml version="1.0" encoding="UTF-8"?> |
<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
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)
Et indiquez /iASP/QSYS.LIB/mabib.LIB/monpgm.PGM ou monsrvpgm.SRVPGM
ou /iASP est le point de montage de votre ASP indépendant
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 apparaitre 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 :
Dans un ASP indépendant
avec une structure :
|
voici les types reconnus par PCML :
Pour infos, voici un extrait du programme déployé ici, en ce qui concerne les paramètres
:
vous pouvez retourner une structure
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.
<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
Les scripts suivants (dans /Qibm/ProdData/os/webservices/V1/server/bin) permettent d'automatiser les déploiements
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.shcreateWebServicesServer.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
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
- nouveaux scripts saveWebservicesServeur.sh et restoreWebservicesServeur.sh
puis
saveWebservicesServer.sh
-server Demo -savefile /qsys.lib/libsavf.lib/wsdemo.file
restorewebservicesserver.sh
-fromserverdirectory /www/Demo
-savefile /qsys.lib/libsavf.lib/wsdemo.file
- nouveaux scripts saveWebservices.sh et restoreWebservices.sh
- ce dernier peut être utilisé pour migrer un web service du serveur LWI (1.5) à celui basé sur liberty profile (2.6)
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...
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
IWS00102I - Command completed successfully. |
|
getWebServiceProperties.sh -server WFORMATION -service GETVINJ |
|
stopWebservicesServer.sh -server WFORMATION |
|
saveWebServices.sh -server WFORMATION -saveFile /QSYS.LIB/LIBSAVF.LIB/WFORMATION.FILE |
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 :
QtmhGetEnv
+ char(?) variable pour recevoir le paramètre à lire
+ int(10) lg de la variable (ce que je transmet)
+ int(10) lg de la valeur retour (ce qu'il fallait)
+ Char(?) nom de la variable d'environnement
+ int(10) lg du nom
+ char(?) structure std de gestion des erreurs
- /chemin/{variable} dans le cas d'une transmission de paramètre dans le PATH (PATH_PARAM)
(vous pouvez alors précisez ":" et une expression régulière devant être vraie, ici que des chiffres)
- /chemin, dans tous les autres cas
ici l'URL sera /web/services/W_RECAP/recap/prod/1 pour le producteur 1
Les paramètres sont reconnus grâce à PCML, indiquez le sens d'utilisation
Ensuite précisez
- la méthode (GET | POST | PUT |DELETE)
- la manière de renseigner les paramètres en entrée
![]()
- *QUERY_PARAM
les paramètres sont transmis dans l'URL sous la forme ?param1=valeur1¶m2=valeur2
- *PATH_PARAM
les paramètres sont transmis dans l'URL sous la forme /chemin/valeur, l'URL vue plus haut -> /chemin/{param1} définit le nom du paramètre
- *FORM_PARAM
les paramètres sont transmis dans un formulaire contenant une zone de formulaire nommé param1 <input name="param1" type="text">
- *COOKIE_PARAM
les paramètres sont transmis sous forme de cookies (param1=valeur1)
- *HEADER_PARAM
les paramètres sont transmis dans l'entête HTTP sous la forme param1=valeur1
- *MATRIX_PARAM
les paramètres sont transmis dans l'URL sous la forme ;param1=valeur1;param2=valeur2
- *NONE
les paramètres sont transmis en tant que structure (XML ou JSON) dans le corps (Body)
<param1>
<zone1>valeur</zone1>
<zone2>valeur</zone2>
</param1>
un seul paramètre peut être transmis via cette méthode
- dans tous les cas, Indiquez à quel paramètre RPG correspond param1 (ici noprod)
- Notez que :
- L'un des paramètres du pgm peut servir à retourner le statut HTTP (404 ou 500, par exemple) dans HTTP response code...
- L'un des paramètres du pgm peut servir à retourner l'entête HTTP (LOCATION: url-de-redirection, par ex.) dans HTTP header ...
Avec SI56883, le type est libre (text/html, par ex.) et vous pouvez préciser plusieurs types de média en retour.
![]()
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 RESTici la création d'un client par POST
Un seul paramètre peut être indiqué Input Source *NONE
Le pgm attend une zone de niveau 01 ClientRecu, composée des champs indiqués en haut (id, reference,...)
- Depuis Octobre 2016, une documentation complète est disponible : http://www-03.ibm.com/systems/resources/systems_i_software_iws_pdf_WebServicesServer_new.pdf
- Depuis Décembre 2016, un fichier swagger est généré pour chaque web service REST (l'équivalent de WSDL pour SOAP)
- Il faut aller chercher swaggerUI ici : http://swagger.io/swagger-ui/
- puis l'installer sur un serveur Apache (ce sont de simples pages web avec du JavaScript)
- Si vous l'installez sur IBMi , ajoutez cette option dans index.html
- Malheureusement à ce jour le fichier swagger reste dans HTTPAdmin et n'est donc pas accessible sans authentification, exportez le quelque part !
Copyright © 2019 VOLUBIS