Pause-Café Volubis

pause-café

rendez-vous technique
Pause-Café est une réunion technique
destinée aux informaticiens sur plateforme IBM i.
Elle a lieu 3 à 4 fois par an : en Bretagne et sur internet.

Pause-café #41

Octobre 2006


V5R40, suite


Nouveautés RPG


|
 parmis les nouveautés bien agréables de la V5R40, il y a l'intégration
  d'ordres SQL en format libre, dans le RPG en format libre

 Avant :   /free       ...       exsr calnbv;       ...   /end-free
 C     calnbv        begsr  C/EXEC SQL  C+     SELECT cast(COUNT(*) as dec(3 , 0)) INTO :NBV FROM VINS  C+      WHERE PR_CODE = :PR_CODE  C/END-EXEC
 Maintenant :   /free    exec sql      SELECT cast(COUNT(*) as dec(3 , 0)) INTO :NBV FROM VINS      WHERE PR_CODE = :PR_CODE ; 

|

Ce qui va être traduit par le pré-compilateur, par :
   //****xec sql    //****SELECT cast(COUNT(*) as dec(3 , 0)) INTO :NBV FROM VINS    //**** WHERE PR_CODE = :PR_CODE ;   /END-FREE  C                   EVAL      SQL_00005    = PR_CODE  C                   Z-ADD     -4            SQLER6  C                   CALL      SQLROUTE  C                   PARM                    SQLCA  C                   PARM                    SQL_00000  C     SQL_00003     IFEQ      '1'  C                   EVAL      NBV = SQL_00006  C                   END   /FREE
 Il n'y a toujours q'une seule instruction SQL par ordre exec sql .

 SEU vérifie la syntaxe du RPG4 en format libre (avec ou sans SQL)

|

 Autre nouveautés
  EVAL-CORR, qui copie d'une structure à l'autre (DS, format, ...)    toutes les zones (compatibles) ayant le même nom .
  Exemple, soit :
     Dds1              ds                  qualified      D Z1                             3P 0      D Z2                             7      D Z3                              n      D Z4                            10  et
     Dds2              ds                   qualified      D Z1                             3P 0      D Z2                             7      D Z3                              n      D Z5                            10


|

 avec EVAL-CORR DS2 = DS1;
      les zones Z1, Z2 et Z3 sont copiées, le compilateur le signale :
      Récapitulatif EVAL-CORR 1                    29 (N° d'instruction)           Z1                Affecté ; correspondance exacte           Z2                Affecté ; correspondance exacte           Z3                Affecté ; correspondance exacte  *RNF7341 Z5                Dans la cible uniquement.  *RNF7342 Z4                Dans la source uniquement.
 avec EVAL-CORR DS3 = DS1;
     Dds3              ds                   qualified      D Z1                             3S 0      D Z2                            12    varying      D Z3                              n      D Z5                            10
     les même zones sont copiées, elles sont compatibles :

|

           Z1                Affecté ; cible et source sont compatibles            Z2                Affecté ; cible et source sont compatibles            Z3                Affecté ; correspondance exacte   *RNF7341 Z5                Dans la cible uniquement.   *RNF7342 Z4                Dans la source uniquement.
 mais avec EVAL-CORR DS4 = DS1;
     Dds4              ds                   qualified      D Z1                             3  0      D Z2                              D      D Z3                             1  0      D Z5                            10
 seules la zone Z1 est copiée (il n'y a pas d'erreur à l'exécution)
          Z1                Affecté ; cible et source sont compatibles  *RNF7349 Z2                Le type de données est différent dans la source  *RNF7349 Z3                Le type de données est différent dans la source  *RNF7341 Z5                Dans la cible uniquement.  *RNF7342 Z4                Dans la source uniquement.

|

 Grosse nouveauté V5R4, très intéressante, le support (en lecture) de XML
 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, contrairemet à 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)

 La structure arborescente du document XML peut être déclarée formellement    dans le corps du document XML ou dans un fichier à part.
 Historiquement on utilisait des DTD, aujourd'hui on utilise plutôt   des shémas XML, qui sont des fichiers (XML) décrivant la structure XML
   ==> Liste des zones, type, obligatoire/facultative, etc...
 Lorsque qu'un document respecte cette description (DTD ou schéma) on dit   qu'il est valide, lorsqu'il respecte uniquement les règles XML on dit   qu'il est bien formé.

|
 Exemple :
<AF400 COPYRIGHT="VOLUBIS">
 <COURS NOM="£EAU" MODULE="INIT">
  <TEXTE>Espace adressable Unique</TEXTE>
  <MOT_DIRECTEUR>
    <MOTCLE1>EAU</MOTCLE1>
    <MOTCLE2>MEMOIRE</MOTCLE2>
    <MOTCLE3>VIRTUELLE</MOTCLE3>
  </MOT_DIRECTEUR>
  <DATREF>1999-08-10</DATREF>
 </COURS>
 <COURS NOM="£OBJET" MODULE="INIT">
  <TEXTE>Notion d'objet de l'OS/400</TEXTE>
  <MOT_DIRECTEUR>
    <MOTCLE1>OS/400</MOTCLE1>
    <MOTCLE2>OBJET</MOTCLE2>
    <MOTCLE3>ECAPSULATION</MOTCLE3>
  </MOT_DIRECTEUR>
  <DATREF>2002-05-11</DATREF>
 </COURS>
   ...
</AF400>

|

 Le nouveau Code Opération XML-INTO, permet de lire un flux XML.
 - A partir d'une variable ou d'un fichier IFS
 - dans une variable ou en indiquant une procédure à appeller
 XML-INTO récepteur %XML(origine : 'options')
 le récepteur peut-être une variable (simple ou DS à n dimensions)   ou bien une procédure désignée par la fonction %HANDLER() qui sera   invoquée x fois (cas ou le nombre d'éléments est inconnu à l'avance)
 la fontion %XML admet en argument  :
       un nom de variable à remplir (option 'doc=string')
       un nom de variable ou une chaîne représentant les coordonées         d'un fichier IFS à lire (option 'doc=file')
       ansi que des options d'utilisation du parser (routine de lecture XML)

|

 options valides (le défaut est souligné)
 +-------------+-----------------+-----------------------------------------+  ! doc         !  doc=string     ! string : la source est une variable     !  !             !  doc=file       !          contenant du XML               !  !             !                 ! file   : la source est un fichier IFS   !  +-------------+-----------------+-----------------------------------------+  ! case        !  case=lower     ! lower  : le flux XML est en minuscules  !  !             !  case=upper     ! upper  : le flux est en majuscules      !  !             !  case=any       ! any    : le flux XML doit être converti !  !             !                 !           avant d'être traité.          !  +-------------+-----------------+-----------------------------------------+  ! trim        !  trim=all       ! all    : les espaces d'extrémité des    !  !             !  trim=none      !          informations caractères sont   !  !             !                 !          enlevés                        !  !             !                 ! none   : ils sont conservés             !  +-------------+-----------------+-----------------------------------------+  ! allowmissing! allowmissing=no ! peut-il y avoir des sous zones de DS    !  !             ! allowmissing=yes!  en plus, c.a.d n'ayant pas d'équivalent!  !             !                 !  en tant qu'élément XML                 !  +-------------+-----------------+-----------------------------------------+

|
 +-------------+-----------------+-----------------------------------------+
 ! allowextra  ! allowextra=no   ! peut-il y avoir des éléments XML        !
 !             ! allowextra=yes  !  n'ayant pas d'équivalent dans la DS ?  !
 !             !                 !  (le complément de allowmissing)        !
 +-------------+-----------------+-----------------------------------------+
 ! path        ! path=noeud/elem ! chemin de l'élément à extraire          !
 !             !                 !                                         !
 !             !                 ! dans ce flux                            !
 !             !                 !                                         !
 !             !                 ! <cours>                                 !
 !             !                 !   <nom>EAU</nom>                        !
 !             !                 !   <module>INIT</module>                 !
 !             !                 ! </cours>                                !
 !             !                 !                                         !
 !             !                 ! si votre DS se nomme COURS et contient  !
 !             !                 !  2 zones NOM et MODULE, tout est        !
 !             !                 !  automatique, sinon mettez 'path=cours' !
 !             !                 !                                         !
 !             !                 ! pour lire directement le nom dans une   !
 !             !                 ! variable simple (pas une DS), indiquez  !
 !             !                 ! 'path = cours/nom'                      !
 +-------------+-----------------+-----------------------------------------+

|
quelques exemples de code :

      *       *  test avec le nom de DS = nom de l'élément       *  il faut que le nom de l'élément soit en minuscule       *  dans le XML, sauf à indiquer l'option case=upper ou case=any       *      Ddata             S           1024    inz('+      D                                      <?xml version="1.0" +      D                                            encoding="ISO-8859-1"?>   +      D                                      <cours nom="XML"  module="PGM"> +      D                                      </cours>                        +      D                                     ')      DCOURS            DS      D NOM                           10      D MODULE                        10

      /free        xml-into cours %xml(data) ; // ou bien %xml(data : 'doc=string')        *inlr = *on;       /end-free

|

      *       *  test avec le nom de DS <> de l'élément, il faut indiquer path=       *       *
     Ddata             S           1024    inz('+      D                                      <cours nom="XML"  module="PGM">   +      D                                      </cours>                          +      D                                     ')      DCOURSDS          DS      D NOM                           10      D MODULE                        10

      /free        xml-into coursds %xml(data : 'path=cours');        *inlr = *on;       /end-free



|
      *
      *  test avec des attributs et plusieurs éléments
      *
      *
     Ddata             S           1024    inz('+
     D                                      <cours nom="XML"  module="PGM">   +
     D                                        <sujet>RPG</sujet>              +
     D                                        <texte>manipuler du XML en RPG  +
     D                                        </texte>                        +
     D                                      </cours>                          +
     D                                     ')
     DCOURS            DS
     D NOM                           10
     D MODULE                        10
     D SUJET                         10
     D TEXTE                         50


      /free        xml-into cours   %xml(data);        *inlr = *on;       /end-free

|
      *
      *  test avec une structure imbriquée
      *
      *
     Ddata             S           1024    inz('+
     D                                      <cours nom="XML"  module="PGM">   +
     D                                        <sujet>RPG</sujet>              +
     D                                        <texte>manipuler du XML en RPG  +
     D                                        </texte>                        +
     D                                        <motcle>                        +
     D                                          <motcl1>RPG</motcl1>          +
     D                                          <motcl2>XML</motcl2>          +
     D                                          <motcl3>SAX</motcl3>          +
     D                                        </motcle>                        +
     D                                      </cours>                          +
     D                                     ')

     DmotclDS          DS      D MOTCL1                        10      D MOTCL2                        10      D MOTCL3                        10

|
     DCOURS            DS                  Qualified
     D NOM                           10
     D MODULE                        10
     D SUJET                         10
     D TEXTE                         50
     D MOTCLE                              likeds(motclDS)


      /free        xml-into cours   %xml(data);        *inlr = *on;
       //*** en debug ***        //   COURS.NOM = 'XML       '        //   COURS.MODULE = 'PGM       '        //   COURS.SUJET = 'RPG       '        //   COURS.TEXTE = 'manipuler du XML en RPG                           '        //   COURS.MOTCLE.MOTCL1 = 'RPG       '        //   COURS.MOTCLE.MOTCL2 = 'XML       '        //   COURS.MOTCLE.MOTCL3 = 'SAX       '
      /end-free

|

      *       *  test avec plusieurs occurences       *       *
     Ddata             S           2048    inz('+      D                                      <af400 copyright="Volubis">       +      D                                      <cours nom="XML"  module="PGM">   +      D                                        <sujet>RPG</sujet>              +      D                                        <texte>manipuler du XML en RPG  +      D                                        </texte>                        +      D                                        <motcle>                        +      D                                          <motcl1>RPG</motcl1>          +      D                                          <motcl2>XML</motcl2>          +      D                                          <motcl3>SAX</motcl3>          +      D                                        </motcle>                       +      D                                      </cours>                          +      D                                      <cours nom="SQL"  module="PGM">   +      D                                        <sujet>SQL</sujet>              +      D                                        <texte>nouveautés SQL en V5R40  +      D                                        </texte>                        +

|
     D                                        <motcle>                        +
     D                                          <motcl1>RECURSIF</motcl1>     +
     D                                          <motcl2>RANK</motcl2>         +
     D                                          <motcl3>OVER</motcl3>         +
     D                                        </motcle>                       +
     D                                      </cours>                          +
     D                                      <cours nom="I5OS"  module="SYS">  +
     D                                        <sujet>V5R4</sujet>             +
     D                                        <texte>nouveautés 5.40 de I5/SO +
     D                                        </texte>                        +
     D                                        <motcle>                        +
     D                                          <motcl1>OS</motcl1>           +
     D                                          <motcl2>I5</motcl2>           +
     D                                          <motcl3>OS4OO</motcl3>        +
     D                                        </motcle>                       +
     D                                      </cours>                          +
     D                                      </af400>                          +
     D                                     ')





|
     DmotclDS          DS
     D MOTCL1                        10
     D MOTCL2                        10
     D MOTCL3                        10

     DCOURS            DS                  Qualified  dim(50)      D NOM                           10      D MODULE                        10      D SUJET                         10      D TEXTE                         50      D MOTCLE                              likeds(motclDS)

      /free
       // la DS est déclarée DIM(50), et il n'y a que 3 éléments, cela ne        //  pose pas de problèmes, les 3 premières occurences sont remplies
       xml-into cours   %xml(data : 'path=af400/cours');        *inlr = *on;       /end-free

|

      *       *  test avec un fichier XML externe       *       *
     DmotclDS          DS      D MOTCLE1                       10      D MOTCLE2                       10      D MOTCLE3                       10      D MOTCLE4                       10      D MOTCLE5                       10
     DCOURS            DS                  Qualified  dim(50)      D NOM                           10      D MODULE                        10      D TEXTE                         50      D TYPE                          10      D SRCFIL                        10      D SRCLIB                        10      D SRCMBR                        10      D CHEMIN                        80

|
     D SUJET                         10
     D MOT_DIRECTEUR                       likeds(motclDS)
     D DATREF                          D


      /free
        // la DS est déclarée DIM(50), et il n'y a bien plus d'éléments dans         // le fichier IFS, cela ne pose pas de problèmes, seules les 50         //  premières occurences sont remplies
       xml-into cours   %xml('/af4dir/courshtm/xml/cours.xml'  :                         'doc=file case=upper path=AF400/COURS') ;        *inlr = *on;       /end-free







|
     H dftactgrp(*no) actgrp(*caller)
      *
      *  test avec un fichier XML externe et un %Handler
      *     (voir http://www.volubis.fr/af4dir/courshtm/xml/cours.xml )
      *
     DmotclDS          DS
     D MOTCLE1                       10
     D MOTCLE2                       10
     D MOTCLE3                       10
     D MOTCLE4                       10
     D MOTCLE5                       10

     DCOURS            DS                  Qualified      D NOM                           10      D MODULE                        10      D TEXTE                         50      D TYPE                          10      D SRCFIL                        10      D SRCLIB                        10      D SRCMBR                        10      D CHEMIN                        80      D SUJET                         10

|
     D MOT_DIRECTEUR                       LikeDS(motclDS)
     D DATREF                          D

     D flagERR         S               n
      * prototype de la procédure déclarée %handler()      Dtrt10cours       PR            10I 0      D flag                            n      D cours10                             likeds(cours)      D                                     dim(10)      D                                     CONST      D nbcours                       10I 0 value
      /free        xml-into       %HANDLER(trt10cours : flagERR)                       %XML('/af4dir/courshtm/xml/cours.xml'  :                         'doc=file case=upper path=AF400/COURS') ;        if flagERR ;          ////        endif;        *inlr = *on;       /end-free

|

     Ptrt10cours       B       * paramètres en entrée      D                 PI            10I 0      D flag                            n      D cours10                             likeds(cours)      D                                     dim(10)      D                                     CONST      D nbcours                       10I 0 value
      * variables locales      D i               S             10I 0      D plusgrandeDate  S               D   static
      /free         for i = 1 to nbcours;
         Monitor;            if cours10(i).datref > plusgrandedate;               plusgrandedate = cours10(i).datref;            endif;

|
         on-error *all;
           flag = *ON;
         endmon;
        endfor;

        if flag = *ON;           return -1;         else;           return 0;         endif;
      /end-free      Ptrt10cours       E
 La doc précise que la procédure doit avoir le prototype suivant :
   D handler         PR            10I 0    D commarea                        ?    D uneDS                               dim(??)    D                                     CONST    D nbelem                        10U 0 value     il y a un bug en début de version obligeant à saisir ce dernier 10I 0

|

 la zone commarea est une zone de communication entre votre programme et    le handler, ce doit etre un passage de paramètre par référence ("normal")
 le type peut-être n'importe quoi (un booléen, une chaîne, ...)

 le deuxième paramètre, doit être la DS de réception des données à N   dimensions.
 Le handler est appellé, autant de fois que nécessaire, en lui transmettant   N éléments, sauf la dernière fois ou cela risque d'être moins.

 Le troisième paramètre contient le nombre d'éléments transmis (obligatoire)   lors du dernier appel.

 Enfin, la procédure, doit retourner une valeur indiquant si tout c'est bien   passé. Si la valeur retournée n'est pas 0, le traitement s'arrete.


|

 Dernier point, vous avez un accès direct au parser (plus compliqué)   par le biais du code opération XML-SAX
 Par exemple, pour le flux XML suivant
 <cours nom="EAU">    <datref>1999-08-10</datref>  </cours>  votre Hanlder est appellé
 1/ en début de traitement  2/ pour le début d'élément <cours  3/ pour l'attribut nom=  4/ pour la valeur de l'attribut ("EAU")  5/ pour la fin de l'élément  6/ pour le début de l'élément <datref>  7/ pour la valeur de l'élément (1999-08-10)
  etc, etc...
 le handler doit recevoir alors 4 paramètres (et non 3)

|
  D handler         PR            10I 0
  D evenement                     10I 0 value
  D chaine                          *   value
  D chaine_lg                     20I 0 value
  D exception                     10I 0 value

   "evenement" pouvant prendre l'une des valeurs suivantes :      (les équivalents numériques sont entre parenthèses)
     *XML_ATTR_UCS2_REF (1)   *XML_ATTR_NAME (2)   *XML_ATTR_PREDEF_REF (3)      *XML_ATTR_CHARS (4)      *XML_CHARS (5)       *XML_COMMENT (6)      *XML_UCS2_REF (7)        *XML_PREDEF_REF (8)  *XML_DOCTYPE_DECL (9)      *XML_ENCODING_DECL (10)  *XML_END_CDATA (11)  *XML_END_DOCUMENT (12)      *XML_END_ELEMENT (13)    *XML_END_PREFIX_MAPPING (14)      *XML_EXCEPTION (15)      *XML_PI_TARGET (16)  *XML_PI_DATA (17)      *XML_STANDALONE_DECL(18) *XML_START_CDATA(19) *XML_START_DOCUMENT (20)      *XML_START_ELEMENT (21)  *XML_START_PREFIX_MAPPING (21)      *XML_UNKNOWN_ATTR_REF(23)*XML_UNKNOWN_REF(24) *XML_VERSION_INFO(25)      *XML_END_ATTR(26) ,  qui sont de nouveaux mots réservés du RPG
  pour plus de détails, voyez http://www.saxproject.org et particulièrement    http://www.saxproject.org/event.html sur la notion d'évenement.

|

 Le mot-clé DEBUG() prend de nouvelles valeurs
  avant la V5R40 seules les options *YES|*NO étaient possibles activant ou    non, le code opération DUMP.
 V5R40
   *XMLSAX , rend actif un tableau _QRNU_XMLSAX( ) contenant les événements              XML possibles sans le préfix "*XML_"              (si le programme est compilé avec DBGVIEW(*SOURCE) ou plus)
             par exemple _QRNU_XMLSAX(1) = 'ATTR_UCS2_REF       '
             le but est que vous puissiez demander les différents codes                possibles en tapant EVAL _QRNU_XMLSAX en debug.
   *INPUT  , les zones en entrées des fichiers en lecture, sont placées                en mémoire, même si elles ne sont pas manipulées par le pgm.
   *DUMP   , le code opération DUMP est actif.

|

 Enfin, dernière nouveauté RPG, le support des variables à valeur nulle,    possible sur les DS externes (E DS ou définies avec LIKERCD)
 Si le fichier qui sert de modèle contient des zones à valeur nulle possible   , les même zones ont aussi la même possibilité dans la DS.
 Cet attribut est transmis lors de la définition d'une DS par LIKEDS   (mais est perdu lors de la définition d'une zone simple par LIKE)
 Cet attribut est copié lors d'un EVAL-CORR.
 Vous pouvez voir la valeur nulle en DEBUG, en demandant
     EVAL _QRNU_NULL_NomdeDs.NomdeZone
  ou toutes les valeurs nulle par EVAL _QRNU_NULL_NomdeDs
 Si une telle DS (contenant des zones à valeur nulle) ou une variable   simple, à valeur nulle possible, est transmise en tant que paramètre,   OPTIONS(*NULLIND) sur le prototype permet de transmetre la valeur nulle   aussi bien que la valeur elle même, à la procédure appellée.

Le transporteur TNT, fourni une liste de ces "points relais" sous forme de réponse XML, simple, aujourd'hui à utiliser en RPG.

par exemple : la liste des communes dans le département 44 et celles de Carquefou ayant un point relais (affichez le source,s'il le faut, pour voir le XML)


Dans le même temps, Scott KLEMENT (rédacteur à systemI /news) propose un projet : HTTPAPI, contenant

  • des API d'utilisation du protocole HTTP
  • un parser XML (projet expat) pour les versions précédentes.
  • des API pour consommer un service WEB
  • ainsi que des exemples d'utilisation en RPG

Ces programmes peuvent être très utiles pour interroger le serveur TNT vu plus haut


Mais aussi pour consommer directement un service Web.

Le site suivant fournit des services WEB à utiliser librement www.webservicex.net entre autre un service de conversion d'une devise vers une autre
( USD vers EUR ou vers JPY par exemple)

Un des programmes RPG, utilise ce service de la manière suivante :

Ou nous apprenons que 450 euros font 571 US $ et 66987 Yens (en septembre 2006, lors de la préparation de ce support)

Pour infos, voici un extrait du code, utilisant une des fonctions proposées :

     http_url_post_xml( )
qui envoie une requête http, attend du XML en réponse et le traite.

 /free 
  SOAP = 
         '<?xml version="1.0" encoding="US-ASCII" standalone="no"?>'          
         +'<SOAP-ENV:Envelope' 
         +' xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"'          
         +' xmlns:tns="http://www.webserviceX.NET/">' 
         +'<SOAP-ENV:Body>' 
         +' <tns:ConversionRate>' 
         +' <tns:FromCurrency>'+ %trim(Country1) +'</tns:FromCurrency>'          
         +' <tns:ToCurrency>'+ %trim(Country2) + '</tns:ToCurrency>'          
         +' </tns:ConversionRate>' 
         +'</SOAP-ENV:Body>' 
         +'</SOAP-ENV:Envelope>'; 
   rc = http_url_post_xml( 
         'http://www.webservicex.net/CurrencyConvertor.asmx' 
          : %addr(SOAP) + 2 
          : %len(SOAP) 
          : *NULL 
          : %paddr(Incoming) 
          : %addr(rate) 
          : HTTP_TIMEOUT 
          : HTTP_USERAGENT 
          : 'text/xml' 
          : 'http://www.webserviceX.NET/ConversionRate');
     // ici on utilise rate pour calculer le montant, puis on envoie un message
/end-free * * cette procédure fonctionne sur la méthode du "callback" * elle est appellée pour chaque élément XML recu * "name" contient le nom de l'élément * "value" la valeur associée * P Incoming B
D Incoming PI
D rate 8F
D depth 10I 0 value
D name 1024A varying const
D path 24576A varying const
D value 32767A varying const
D attrs * dim(32767)
D const options(*varsize)
* fonction du C, convertissant une chaine en virgule flottante
D atof PR 8F extproc('atof')
D string * value options(*string)
/free if (name = 'ConversionRateResult');
rate = atof(value); endif; /end-free P Incoming E

Vous remarquerez qu'il est important de bien connaitre ILE




PHP sur I5/OS (V5R40 uniquement) : Zend core for I5/OS

Produit non facturable avec un support assuré par Zend (voyez l'annonce IBM )

Ce produit installe en fait un serveur Apache sous Pase qui tourne sur un autre port (8000, modifiable) , il faut alors utiliser une directive PROXY pour rerouter les requêtes vers cet autre serveur (depuis le serveur Apache "natif" de I5/OS).

L'interet du serveur Apache2 sous Pase (c'est véritablement celui d'UNIX) pour Zend, c'est de réutilsier les routines existantes, particulièrement celles permettant de lancer PHP en mode module, ce qui offre les meilleures performances et le debug avec ZendStudio.


1/ Téléchargez le fichier zippé sur le site de ZEND, dézippez et transférez (en binaire) via FTP le SAVF ZCOREPROD dans QGPL

2/ Passez ensuite la commande RSTLICPGM LICPGM(1ZCORE5) DEV(*SAVF) SAVF(QGPL/ZCOREPROD)

cela doit vous afficher l'écran de licence suivant :

La version définitve (GA) porte le N°  V1R4M1

Puis vous entrerez un mot de passe pour l'administrateur


Ensuite vient la phase de connexion au serveur Zend (pour les mises à jour), vous devez avoir créé un compte sur le site de Zend.


cela va ajouter un poste au scheduler I5/OS (WRKJOBSCDE)



L'installation a modifié QSYSWRK pour ajouter un poste de routage, et vous pouvez lancer le menu GO ZENDCORE/ZCMENU 

Cette installation contient une version d'Apache pour Unix tournant sur le port 8000(Zend indique que cela permet d'utiliser php en mode module, ce qui est plus rapide). cela a probablement permis aussi la réutilisation du debuger de ZendCore. Pour modifier cette instance, particulièrement le port 8000, voyez /usr/local/Zend/apache2/conf/httpd.conf

pour lancer ce serveur,  utilisez le menu (ZCMENU) ou bien (depuis QP2TERM) /usr/local/zend/apache2/bin/apachectl -k start | stop

ou bien, encore, placez dans un CL :
 

SBMJOB     CMD(CALL PGM(QP2SHELL)  PARM('/usr/local/Zend/apache2/bin/apachectl' '-k' 'start'))
                            JOB(APACHE2) JOBQ(QUSRNOMAX [par exemple)] )

      
  La version 1.4.1 propose de nouveaux services accessibles depuis le menu ZCAMENU
(option 5 du précédent)

 

Ces services sont lancés dans un sous système ZEND ,particulièrement un travail I5_COMD faisant tourner un programme
            EASYCOMD (hum, hum..Easycom propose aussi un produit.) correspondant au "I5 PHP API Toolkit" qui contient des API spécifiques à l'AS/400, comme :

  • Accès aux programmes I5/OS (avec passage et récupération de paramètres)
  • Accès aux commandes I5/OS (y compris commandes comme RTVJOBA avec récupération des valeurs retour)
  • Accès à la base de données en mode ligne à ligne (dit aussi accès "natif"),
    l'accès en mode SQL se faisant par le module ODBC ou DB2
  • Accès aux DTAARA
  • Gestion des erreurs et récupération des messages d'erreur.

Pour plus de détai, voyez  la documentation à :
                http://www.zend.com/content/download/1842/11547/file/Zend_Core_User_Guide_i5OS.pdf



Cette installation a aussi créé une instance APACHE NATIVE (nommée ZENDCORE et qui est lancée normalement dans QHTTPSVR)
            contenant les lignes suivantes , dont vous devez vous inspirer pour completer votre instance de production :

LoadModule proxy_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM        
LoadModule proxy_http_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM   
LoadModule proxy_connect_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM
LoadModule proxy_ftp_module /QSYS.LIB/QHTTPSVR.LIB/QZSRCORE.SRVPGM

puis
ProxyPass /exemplesphp http://localhost:8000/exemplesphp       
ProxyPassReverse /exemplesphp http://localhost:8000/exemplesphp    

Qui demande à ce que chaque requête dont l'URL commence par exemplesphp soit redirigée vers le port 8000, donc vers le serveur apache2 installé par Zend.

ainsi que
ProxyPass /core http://localhost:8000/      
          ProxyPassReverse /core http://localhost:8000/

permettant d'accèder à la racine du nouveau site
           

     et donc un accès au coeur du produit

           
            Indiquez ici, le mot de passe saisi lors de l'installation

et voilà !


Avec cette version, MYSQL, n'est pas activé par défaut, il faut modifier php.ini (dans /usr/local/Zend/core/etc) et enlever le caractère ; (qui comment une ligne) devant mysql.so et mysqli.so




Enfin vous pouvez utiliser Zend Studio for I5/OS (en attendant l'intégration de ce produit dans Eclipse, dixit IBM)

Contenant un éditeur PHP tout à fait sympathique


Mais surtout un outil de debug, en direct avec le serveur ZendCore

Pour cela
  1. Autorisez une adresse ou une plage d'adresses IP à faire du debug

    Lancer ZendCore, puis optez pour Configuration/Zend studio server


    Ici toutes les adresses IP 10.* sont autorisées ( zend_debugger.allow_hosts dans /usr/local/zend/Core/etc/php.ini)


  2. Sur le client choisissez Outils/Personnalisation puis l'onglet "débogage"

    et indiquez
  • Mode de débogage : serveur
  • URL du serveur : http://votre-as-400:8000/

Vous pourrez alors demander l'exécution d'une page sur le serveur et lancer le debug


ce qui vous affiche :
  1. le code dans la fenêtre éditeur
  2. les boutons habituels d'un débuger (avancer, pas à pas, etc...) dans la barre d'outils
  3. la page résultat dans la fenêtre de droite (en texte ou en html)
  4. la possibilité de voir le contenu des variables (fenêtre du bas ou en mettant la souris sur un nom de variable)

WDSc, nouveautés de la version 6

  • Cette version est basée sur Eclipse 3, ce qui change les éléments suivants
    • vous pouvez installer plus de PlugIn (phpeclipse, par exemple)
    • globalement le "look & feel" des fenêtres change.
    • le passage d'une perspective à l'autre, qui se fait maintenant en haut à droite

    • en même temps IBM rachetait la société Rational et donc le produit s'appelle maintenant "IBM Rational Web developer"

  • L'éditeur LPEX
    • Enfin une sauvegarde automatique de proposée


      ce qui vous affiche le message suivant en cas d'arrêt anormal du produit :



    • La vue structure est maintenant opérationnelle pour les sources SDD


    • il est possible d'ouvrir plusieurs fois (plusieurs vues) un même source


      ensuite, en cliquant droit sur cette nouvelle fenêtre, vous pourrez afficher horizontalement ou fermer cette vue.



    • La gestion des messages d'erreur suite à compilation est plus simple :

      • on peut filter le niveau de gravité (chaque niveau est représenté par une icone différente)


      • l'option "insérer uniquement les messages sélectionnés" permet de ne voir que le message d'erreur en cours dans le source, quand on double-clique sur ce dernier.



      • LPEX tenant compte des nouveautés syntaxique de la version 5.4, si vous convertissez un RPG-IV contenant du SQL, en format libre, les ordres SQL eux même (/EXEC SQL  /END-EXEC) passent en format libre (Exec SQL, terminé par ;)

      • Il existe désormais des modèles  pour COBOL (voyez préférences/systèmes distants/iSeries/modèles)

      • Dans la vue table, vous pouvez masquer la ligne de commande

      •  Le fait de pouvoir lancer un shell, se fait maintenant de manière identique pour un shell local (accès à une "boite DOS") ou pour un shell distant (sur iSeries, l'équivalent de QSHELL), avec l'option "Commandes Shell" dans l'arboresence de RSE). Remarquez le résultat de la commande "ls", les répertoires sont cliquables et cela passe la commande "cd")

    WDSc et services Web

    Une des nouveautés de cette version est la création directe de services WEB


    IBM proposait déja des méchanismes 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)
                   { /* gerer l'erreur et afficher qqchose */ }
               else
                   {
                      value = pcml.getValue("getcust.gotback.Name");
                      System.out.println("Customer name: " + value);
                   }
           } catch (PcmlException exc) {
               System.out.println("*** impossible de lancer le pgm. ***");
               Sy ste m. exit (0);
           }
           System.exit(0 );
    } // end main method



    WDS Client V6.01 propose maintenant des outils de gestion de services WEB.

    Cliquez droit à partir d'un source RPG4 (programme avec des paramètres, bien sûr)

     

    Cela va lancer un assistant

    cochez :

  • générer un proxy java
  • tester le service Web (cela lancera automatiquement un test)
  • Contrôler le service Web qui va générer un affichage du dialogue soap
  • cliquez sur suivant, vous arrivez sur la fenêtre de sélection d'objet

    Indiquez bien s'il s'agit d'un programme ou d'un programme de service ,puis sur modifier pour modifier les paramètres de connexion

    Indiquez :

    Profil et mot de passe


    liste de bibliothèques et/ou programme "d'ouverture de session"

Nous revenons à la fenêtre principale de l'assistant, pour préciser le sens d'utilisation des paramètres


cliquez sur suivant et indiquez les caractèristiques du projet WEB (au sens WDSc)



Cliquez sur Fin, c'est fini, la classe java est générée, le test est lancé



le bouton invoke, lance le test

En bas le dialogue soap est affiché

Si vous ouvrez une perspective WEB,
vous retrouverez tous vos éléments


L'option Classe de service permet d'accèder au source généré


L'option WSDL, vous affiche le diagramme ou le source wsdl correspondant.

 

WDSc lite

Dernier point, peut-être le plus important, pour de nombreux clients : WDSc lite, version allégée de WDSc, directement basée sur Eclipse (et non plus sur WSSD ou Rational Web Developer) et donc moins gourmande : uniquement de 256 Mo de mémoire principale.

Bizarrement, c'est une pré-version, et il faut d'abord installer la version complète, qui doit rester présente sur votre disque dur, pour pouvoir installer la version lite. 


Il faut utiliser le produit de mise à jour de WDSc

ce mettre à niveau sur les correctifs (cela peut représenter un beau volume à télécharger)


Cette étape commencant, par mettre à jour le produit de mise à jour lui même !

redémarrez

Ensuite les correctifs, vous faisant passer à la version 6.0.1.1 et les correctifs WDSc.

Acceptez les contrats de licence (et soyez patient ...)


Ensuite (enfin) vous pouvez sur le même produit, utiliser le deuxième onglet "Fonctions facultatives", où vous trouverez WDSc lite



Une fois cette "option" installée, vous aurez les deux versions sur votre poste




et vous constaterez le peu de perspectives disponibles par rapport à la version complète  

 


Top


Copyright © 1995,2006 VOLUBIS