
Soit une liste des cours AF400 , en HTML :
<h3>Liste des cours AF400 (© Volubis)</h3> |
ce qui s'affiche :

(voir le fichier complet, le source du pgm ayant réalisé cela)
Voici la manière dont RDP, montre ce fichier :

Pour les règles du jeu XML, voir ce cours
L'état de l'art est aujourd'hui de travailler dans une architecture dite 3 tiers, c'est à dire en découplant le serveur de traitement (les programmes souvent placés avec le serveur WEB) des données (pouvant être situées sur un serveur éloigné).
Cette technique est implémentée avec les serveurs
d'application ou serveurs de servlet.
Websphere Application Server(WAS) ou TOMCAT par
exemple, mais aussi ".NET" de Microsoft.
Il s'agit d'écrire des programmes JAVA (ou C#)
s'exécutant sur le serveur et non sur le poste client , le
serveur d'application assurant le lien entre le serveur WEB et la JVM
(machine virtuelle java).Ces programmes java pouvant être des
classes autonomes (servlet) générant du HTML :

ou contenus dans des pages JSP : pages HTML faisant
références à des objets externes [des beans].
Les pages JSP permettant d'intégrer du HTML (conçu par
un graphiste) et du code JAVA (écrit par un développeur)
dans un même fichier.
Aujourd'hui, pour une application WEB, l'architecture logique doit
être :
| Les web services sont des briques logicielles "en ligne" et permettent de créer des applications distribuées et accessibles depuis n'importe quel navigateur xml. Ces briques sont référencés dans l'annuaire UDDI, décrite selon la norme WSDL (dérivée de XML) et opérent avec d'autres briques selon le protocole SOAP. |

Un web-service : c'est un logiciel qui interagis avec d'autres au moyen de protocoles universels (http, xml...)
Exemple d'implémentation de services RESTful : projet XMLSERVICE ScriptAlias /cgi-bin/ /QSYS.LIB/QXMLSERV.LIB/ <Directory /QSYS.LIB/QXMLSERV.LIB/> AllowOverride None order allow,deny allow from all SetHandler cgi-script Options +ExecCGI </Directory> L'API s'utilise de la manière suivante
Les mot-clés transmis peuvent être <cmd>...commande 5250...</cmd> <cmd>...commande PASE...</cmd> <pgm name='PGM' lib='BIB' func='Fonction'> <sql>
Lancement d'une commande PASE Lancement d'un ordre SQL Les nouvelles fonctions HTTPOSTCLOB , HTTPPOSTCLOBVerbose permetterons de les utiliser en SQL |
<?xml version="1.0"?> |
<?xml version="1.0" encoding="UTF-8"?> |
<?xml version="1.0"?> |
| <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 */ } el se { 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 |



2/ et des outils pour tester

Voyez les cours sur les nouveautés WDSC V6 ou WDSC V7 pour plus de précisions.
Enfin, l'intégration de
code-opération pour manipuler le XML et l'arrivée
d'outils pour travailler sur les sockets (outils IBM ou projets
indépendants comme iSockets ou HTTPApi
de Scott Klement ) permettent aujourd'hui de consommer des services WEB
depuis un RPG.
Il s'agit du nouveau serveur d'application intégré à l'OS pour distribuer les applications Java., remplaçant Tomcat, qui n'est plus fourni avec la V6 et en V5R40, via PTF
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 OSGI . (vous trouverez plus d'infos à http://www-03.ibm.com/systems/i/software/iws/ et un comparatif entre WAS Express et ce dernier, ici )
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/


en même temps que la création du serveur d'application, vous allez déployer votre premier service web

Ici un programme W_RECAP de BDVIN0, attendant une zone PR_CODE, et retournant
une DS nommée INFOCENTRE,
ce pgm a été compilé avec PGMINFO(*MODULE)
, en V5R40 il faut SI27065 pour
activer cette option.

Indiqué le nom publique du service et un texte explicatif

et précisez le sens d'utilisation des paramètres (automatiquement découverts par l'assistant grave à PGMINFO)
pour infos, voici un extrait du programme en ce qui concerne les paramètres :
DPR_code S 6 0
DINFOCENTRE E DS qualified
C *entry plist
C parm pr_code
C parm infocentre

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

Indiquez le profil utilisateur qui lancera le programme

indiquez aussi, la liste des bibliothèques à utiliser

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

liste des services (le votre, plus un exemple nommé ConvertTemp)

Les opérations admises 
soit les informations que l'on peut demander :
w_recap, les paramètres retour transmis dans l'enveloppe SOAP
w-recap_XML, les données transmises dans un flux XML
Le serveur se créé 
Puis, vous basculez automatiquement sur la gestion du serveur d'application de type web services V1.3, cette fois.

Remarquez l'ajout automatique du service exemple convertTemp
Vous pouvez, ici, revenir gérer les services déployés, ou bien, en déployer de nouveaux.

(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

Mais surtout, vous pourrez tester votre service web, par le bouton "Test Service"

Choisissez l'opération (w_recap ou w_recap_XML), ici w_recap

Ajoutez un paramètre en entrée, PR _CODE est automatiquement proposé et vous ne pourrez l'ajouter qu'une seule fois

puis ajoutez une valeur (là aussi, une seule occurrence, dans ce cas) et cliquez sur GO

la réponse vous est affichée dans la fenêtre Status
Ci dessous, le résultat de w_recap_XML

Vous pouvez tester aussi avec des produits standard comme soapUI
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
Octobre 2008, une PTF PTF SI32432 apporte les scripts suivants qui à ce jour ne sont donc pas documentés, dans /Qibm/ProdData/os/webservices/V1/server/bin
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
pour vous familiariser avec les scripts, passez la commande QSH (qui un émulateur
de shell UNix sur AS/400) sur une ligne de commande OS/400
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...
listWebServices.sh -server WSERVICE, vous affiche les services disponibles d'un serveur donné.
si vous tapez le nom d'un script -help , il vous affiche une aide "limitée" (ainsi que si des paramètres sont manquants) , par exemple :
installWebservice.sh
Command usage:
installWebService.sh
-server 'server-name' -programObject 'program-object'
[-service 'service-name'] [-pcml 'pcml-file'] [-userid 'userid']
[-libraryList 'library-list'] [ -printErrorDetails ] [ -help ]
Where:
-server is the name of the Web services server in which the service
will be installed.
-programObject is the integrated file system path to the ILE program or
service program. For example, '/QSYS.LIB/MYLIB.LIB/MYPGM.[SRVPGM or PGM]'
-service is the name of Web service to be installed. This parameter is
optional. If not specified, the program object name will be used.
-pcml is a path to the PCML file. This parameter is optional. If not
specified, the program object must contain the PCML data.
-userid is the user profile that the Web service will run under. This
parameter is optional. If not specified, the Web service will run under
the Web services server user profile.
-libraryList is a list of libraries, that will be added to the library
list prior to invoking the Web service. Each library in the list must
be delimited by a colon. This parameter is optional.
-printErrorDetails will show additional error information, such as stack
traces and error codes, if the command fails. This parameter is optional.
-help displays the command syntax. This parameter is optional.
pour passer la commande directement depuis un CL
QSH CMD('/qibm/proddata/os/webservices/V1/server/bin/<votrescript.sh> paramètre1 paramètre2 ...')
2010, le dernier groupe PTF permet de déléguer des droits via l'administration graphique.
Sans cette délégation, il faut être *ALLOBJ et *IOSYSC FG 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)

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ées ces correctifs vous verrez apparaître une option de migration 
Vous aurez aussi d'autres options :




En V6R1, et de manière intégrée au système d'exploitation, nous avons des mécanisme pour accéder à un service web depuis le langage RPG (entre autre).
on dit "consommer un service web"...
L'exemple fourni par IBM est basé sur le service ConvertTemp automatiquement créé lors de la création du serveur d'application
Allez sur la page 
Si vous le testez, vous voyez (remarquez le paramètre param0, qui est une structure composée d'une seule zone _TEMPIN) :

Utilisation en en PHP
|
<?php $client = new SoapClient("http://AS400S:10030/web/services/ConvertTemp?wsdl"); |
Résultat :

en .NET
Après avoir ajouté une référence web dont l'URL est "http://AS400S:10030/web/services/ConvertTemp?wsdl"
|
Dim wsTemp As New AS400_Temperature.ConvertTemp |
Par exemple sur l'événement "click" d'un bouton cmdOK (ici libellé Go)
Protected Sub cmdOK_Click(ByVal sender As Object, ByVal e As System.EventArgs)
Dim wsTemp As New AS400_Temperature.ConvertTemp
Dim input As New AS400_Temperature.CONVERTTEMPInput
If txtF.text <> "" Then
input._TEMPIN = txtF.text
lblC.Text = wsTemp.converttemp_XML(input)
End If
End Sub
Résultat

Enfin, en RPG :
1/ récupérez le fichier de définition (WSDL) en cliquant
sur View definition
(sinon, pour celui-ci uniquement , il est déja
présent dans /QIBM/ProdData/OS/WebServices/V1/client)
2 / il faut générer le "stub" soit le programme "proxy" faisant l'interface entre Axis et notre RPG.
pour cela nous utiliserons l'outil WSDL2WS.SH sous shell (STRQSH)
|
> /QIBM/ProdData/OS/WebServices/V1/Client/bin/wsdl2ws.sh |
Si vous passez la commande ls, vous devez voir :
|
$ |
L'utilisation de ces sources C en RPG était assez complexe.
En début 2011 les PTF suivantes SI42234 (V5R40) , SI42236 (V6R10) , SI42235 (v7) apportent un nouvel utilitaire wsdl2rpg
comme le précédent, il se trouve dans QIBM/ProdData/OS/WebServices/V1/Client/bin/
> /QIBM/ProdData/OS/WebServices/V1/Client/bin/wsdl2rpg.sh |
L'option -T demande la création d'un programme de service dans la bibliothèque MABIB.
Cette fois il génère aussi du RPG, soit 6 fichiers en plus, portant le nom du type de port (ConvertTempPortType dans nos exemples)
| ConvertTempPortType.CL | le CL de création du *SRVPGM |
| ConvertTempPortType.rpgleinc | fichier à inclure (dans votre programme) |
| ConvertTempPortType.rpgle | le code d'invoquation du web service (*SRVPGM) |
| ConvertTempPortType_util.rpgleinc | fichier à inclure (dans le source suivant) |
| ConvertTempPortType_util.rpgle | divers utilitaires |
| ConvertTempPortType__xsdtypes.rpgleinc | différents types de données standards |
le fichier de référence est le ConvertTempPortType.rpgleinc qui contient les définitions dont vous avez besoin, et qu'il faut inclure dans votre code :

Compilez ce source par CRTRPGMOD.
Malheureusement, pour des problèmes de code page, il faut probablement modifier légèrement le fichier à inclure
et remplacer les @ de fin par à, sur les trois fonctions vues plus haut ou bien recompiler le *SRVPGM.

Dernier point, vous devez linker tout ce petit monde, par :
![]()
Essayons le pgm :
.
Cette nouvelle version, permet un code RPG relativement simple et lisible.
Si vous préférez utiliser SQL, la PTF SF99701 level 23 propose une consommation de web services via des fonctions dans SYSTOOLS
httpGetBlobhttpGetClobhttpPutBlobhttpPutClobhttpPostBlobhttpPostClobhttpDeleteBlobhttpDeleteClobhttpBlobhttpClobhttpHead- UrlEncode
UrlDecode
base64Encode
base64Decode
le but de ces fonctions est de consommer des services web plutôt orientés REST
Regardons à travers des exemplesValues SYSTOOLS.HTTPGETCLOB('http://www.volubis.fr' ,'') ;
Récupère dans une variable le contenu de notre page d'accueil
![]()
Si le site retourne du XML, l'utilisation de la fonction XMLTABLE permettera de ne recevoir que les données utiles
Ici, le site www.redbooks.ibm.com propose des flux RSS donnant les publications récentes
![]()
le codeSELECT * FROM XMLTABLE('$result/rss/channel/item' PASSING XMLPARSE( DOCUMENT SYSTOOLS.HTTPGETBLOB('http://www.redbooks.ibm.com/rss/iseries.xml','') ) as "result" COLUMNS title VARCHAR(128) PATH 'title', description VARCHAR(1024) PATH 'description', link VARCHAR(255) PATH 'link', pubDate VARCHAR(20) PATH 'substring(pubDate, 1, 16)' ) AS RESULT;permet de lire les données de manière structurée :
![]()
Ce code permet de lire le fichier cours.xml , s'il est disponible via HTTP
SELECT cours, texte, motcle1, monthname(modif) concat '-' concat year(modif) FROM XMLTABLE('$result/AF400/COURS' PASSING XMLPARSE( DOCUMENT SYSTOOLS.HTTPGETBLOB('http://as400.volubis.intra/af4dir/courshtm/XML/cours.xml','') ) as "result" COLUMNS cours CHAR(10) PATH 'AF4MBR', texte CHAR(50) PATH 'AF4TXT', motcle1 VARCHAR(20) PATH 'MOTCL1', MODIF DATE PATH 'DATOUT' ) AS TABLEXML;
Ce code permet de le lire via HTTP, la page étant protégée par un mot de passe
-- LECTURE fichier XML via INTERNET avec authentification
SELECT cours, texte, motcle1, monthname(modif) concat '-' concat year(modif)
FROM XMLTABLE('$result/AF400/COURS'
PASSING XMLPARSE(
DOCUMENT
SYSTOOLS.HTTPGETBLOB('http://af400:motdepasse@as400.volubis.fr/af4dir/courshtm/XML/cours.xml','')
) as "result"
COLUMNS
cours CHAR(10) PATH 'AF4MBR',
texte CHAR(50) PATH 'AF4TXT',
motcle1 VARCHAR(20) PATH 'MOTCL1',
MODIF DATE PATH 'DATOUT'
) AS TABLEXML;
Appel d'un Web services, utilisation du deuxième paramètre permettant de fournir les entêtes http (ici, nous demandons la valeur de l'action IBM à aujourd'hui dans une enveloppe SOAP)
-- Appel d'un web service , récupération de l'enveloppe SOAP réponse dans une variable
VALUES SYSTOOLS.HTTPPOSTCLOB('http://www.webservicex.net//stockquote.asmx',
CAST ('<httpHeader>
<header name="Content-Type" value="text/xml;charset=utf-8"/>
<header name="SOAPAction" value=""http://www.webserviceX.NET/GetQuote""/>
</httpHeader>' AS CLOB(1K)),
CAST('<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<GetQuote xmlns="http://www.webserviceX.NET/">
<symbol>IBM</symbol>
</GetQuote>
</soap:Body>
</soap:Envelope>' AS CLOB(10K)) ) ;
-- Appel d'un web service , récupération de l'enveloppe SOAP, "parsée" -- il y a des espaces de nommage (xmlns) SOAP et d'autres propres au web service, d'où -> *:
-- les données extraites sont elles mêmes au format XML (on voit que l'action est à 210 $ 55 ) SELECT* FROM XMLTABLE('$result/*:Envelope/*:Body/*:GetQuoteResponse' PASSING XMLPARSE( DOCUMENT SYSTOOLS.HTTPPOSTCLOB('http://www.webservicex.net//stockquote.asmx', CAST ('<httpHeader> <header name="Content-Type" value="text/xml;charset=utf-8"/> <header name="SOAPAction" value=""http://www.webserviceX.NET/GetQuote""/> </httpHeader>' AS CLOB(1K)), CAST('<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <GetQuote xmlns="http://www.webserviceX.NET/"> <symbol>IBM</symbol> </GetQuote> </soap:Body> </soap:Envelope>' AS CLOB(10K)) ) ) as "result" COLUMNS resultat VARCHAR(2000) PATH '*:GetQuoteResult' ) AS TABLEXML;-- Appel d'un web service , récupération de l'enveloppe SOAP, "parsée" pour lire le montant de l'action -- puis découpage du XML extrait à nouveau par la fonction XMLTABLE WITH temp as (SELECT resultat FROM XMLTABLE('$result/*:Envelope/*:Body/*:GetQuoteResponse' PASSING XMLPARSE( DOCUMENT SYSTOOLS.HTTPPOSTCLOB('http://www.webservicex.net//stockquote.asmx', CAST ('<httpHeader> <header name="Content-Type" value="text/xml;charset=utf-8"/> <header name="SOAPAction" value=""http://www.webserviceX.NET/GetQuote""/> </httpHeader>' AS CLOB(1K)), CAST('<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> <soap:Body> <GetQuote xmlns="http://www.webserviceX.NET/"> <symbol>IBM</symbol> </GetQuote> </soap:Body> </soap:Envelope>' AS CLOB(10K)) ) ) as "result" COLUMNS resultat VARCHAR(2000) PATH '*:GetQuoteResult' ) AS TABLEXML )select * from temp, XMLTABLE ('$c/StockQuotes/Stock' passing XMLPARSE(DOCUMENT RESULTAT) as "c" COLUMNS symbol CHAR(30) PATH 'Symbol', prix dec(11, 2 ) PATH 'Last' ) AS X ;![]()
Ces fonctions peuvent être utilisées pour lire le résultat produit par XMLSERVICE (vu plus haut)
Rappel
Lancement d'une commande PASE
![]()
Résultat
-- Appel XMLSERVICE avec une commande PASE Values SYSTOOLS.HTTPPOSTCLOB('http://as400/cgi-xml/xmlcgi.pgm' , CAST ('<httpHeader> <header name="Content-Type" value="application/x-www-form-urlencoded"/> </httpHeader>' AS CLOB(1K)), CAST('db2=AS400&uid=NOBODY&pwd=nopwd&ipc=/tmp/htmlxml&ctl=*sbmjob
&xmlin=<?xml version=''1.0''?><script><sh rows=''on''>/QOpenSys/usr/bin/uname -a</sh></script>
&xmlout=500000' AS CLOB(10K)) )Affiche-- Appel XMLSERVICE avec une commande WRKACTJOB via PASE SELECT * FROM XMLTABLE('$result/script/sh/row' PASSING XMLPARSE(DOCUMENT SYSTOOLS.HTTPPOSTCLOB('http://as400/cgi-xml/xmlcgi.pgm' , CAST ('<httpHeader> <header name="Content-Type" value="application/x-www-form-urlencoded"/> </httpHeader>' AS CLOB(1K)), CAST('db2=AS400&uid=NOBODY&pwd=nopwd&ipc=/tmp/htmlxml&ctl=*sbmjob
&xmlin=<?xml version=''1.0''?><script><sh rows=''on''>/QOpenSys/usr/bin/system -i wrkactjob</sh></script>
&xmlout=500000' AS CLOB(10K)) ) ) AS "result" COLUMNS ligne VARCHAR(132) PATH '.' ) AS reponse; ;
Affiche![]()
httpGetBlobVerbosehttpGetClobVerbosehttpPutBlobVerbosehttpPutClobVerbosehttpPostBlobVerbosehttpPostClobVerbosehttpDeleteBlobVerbosehttpDeleteClobVerbosehttpBlobVerbosehttpClobVerbosehttpHeadVerbose![]()
Attention
Toutes ces fonctions sont livrées dans SYSTOOLS, donc "as is' et ne peuvent faire l'objet d'une demande de support
Copyright © 1995,2013 VOLUBIS