, Démystification de la Modernisation IBMi

Cette semaine c’est un article un peu spéciale c’est notre ami Jérôme Clément qui nous livre ses réflexions éclairées sur la modernisation de vos applications #ibmi et ses enjeux , merci à lui pour ce partage .

Objectifs

Cet article a pour objectif de démystifier la modernisation IBMi et surtout de mettre en évidence toutes les actions de modernisation réalisables aisément qui faciliteront grandement les actions d’envergure qui seront à réaliser ensuite.

Le concept de Modernisation de l’IBMi est, certes, très vaste et peut paraitre très difficile à mettre en œuvre mais nous allons voir que cette modernisation repose aussi sur de nombreuses étapes qui peuvent, elles, être réalisées facilement et rapidement par les équipes internes à l’entreprise.

En plus d’être indispensables à la modernisation, ces étapes apporteront une meilleure maîtrise des applicatifs IBMi existants, ce sont des prérequis aux chantiers plus conséquents que sont, par exemple :

  • La mise en place de solutions DEVOPS
  • La conversion automatisée des bases DB2 en bases SQL
  • La transformation des programmes RPG en programmes FREEFORM

Voici quelles sont ces différentes étapes, que je détaillerai ensuite :

  • Adhésion à la démarche
  • Normalisation des développements
  • Définition des bonnes pratiques
  • Documentation et centralisation de la documentation
  • Etat des lieux des applicatifs
  • Modularisation et utilisation des programmes de service
  • Migration progressive d’une base de données DB2 vers une base de données SQL
  • Accès aux données avec SQL
  • Implication des équipes de développement

Adhésion à la démarche

Il est primordial que la démarche de modernisation soit partagée par tous. C’est-à-dire :

  • Par la direction de votre entreprise
  • Par la DSI
  • Par les équipes de développement

Pour être efficace, cette démarche doit être comprise de tous et avoir l’adhésion de chacun.

Cela car elle nécessite des moyens (essentiellement du temps), de la rigueur et l’implication de tous les acteurs.

Il est important que la direction de votre entreprise ait conscience que :

  • La modernisation est nécessaire au bon fonctionnement et aux évolutions futures des applications qui reposent sur l’IBMi.
  • L’IBMi est une machine moderne, en phase avec son époque, capable de s’interfacer avec tous les autres systèmes actuels. Robuste, rapide, économique l’IBMi porte actuellement le cœur de l’activité de votre entreprise, il est primordial de maintenir ce système à niveau.
    La dette technique accumulée au fil des années peut être « remboursée », et cela doit être fait pour pouvoir profiter encore longtemps des investissements déjà réalisés dans la mise en place des applications spécifiques à votre entreprise et spécifiques à votre activité.
  • Quitter l’IBMi pour un autre système peut être une solution. Mais c’est une opération longue, couteuse et risquée. C’est une solution sur laquelle de nombreuses entreprises se sont déjà « cassés les dents ».
  • Il est, selon moi, nettement plus judicieux et beaucoup plus économique de capitaliser sur vos acquis en modernisant vos applicatifs plutôt que de chercher à les remplacer à l’identique ou presque sur un autre support.
  • Moderniser les applicatifs IBMi est un investissement qui ne pourra être mener à bien que s’il est appuyé par la direction de l’entreprise et uniquement si celle-ci donne les moyens à ses équipes de se lancer pleinement dans cette démarche.

Il est important que la DSI ait conscience que :

  • La modernisation nécessite du temps et qu’il va donc falloir en accorder à ses équipes pour la mettre en œuvre.
    En effet, une équipe sous pression d’échéances de livraison de projets ne prendra pas le temps de faire « bien », elle se contentera de faire « vite ». Elle vivra la démarche de modernisation comme une contrainte lui demandant du temps dont elle ne dispose déjà pas. Elle ne percevra pas cette démarche comme un investissement, et cherchera à s’y soustraire à la moindre occasion plutôt que de la porter.
  • La modernisation réduira les coûts des développement futurs.
    La maitrise et la connaissance des applicatifs, la mise en place de services évitant la redondance de code, l’homogénéisation des méthodes de développements, la suppression des programmes obsolètes : toutes ces étapes, une fois réalisées, permettront de gagner du temps dans la réalisation de vos projets.
    Le temps nécessaire à la modernisation sera donc récupéré par la suite. 
  • Certains développeurs peuvent aussi se montrer réfractaires à l’idée de sortir de leur zone de confort en devant changer leurs habitudes de développement. C’est pourquoi la démarche de modernisation doit être portée par la DSI. Il va falloir contrôler que tous les développeurs y participent et la mettent en œuvre. En effet, il est contreproductif de résorber la dette technique d’un côté si c’est pour continuer à la générer d’un autre.

Il est important que les développeurs aient conscience que :

  • La modernisation est nécessaire et qu’elle pérennise la présence de l’IBMi au cœur de l’infrastructure technique de l’entreprise et par conséquent leur présence en tant que développeurs spécialisés sur ce système au sein de l’entreprise.
  • La modernisation est formatrice et donc très positive.

Cette démarche va probablement changer les habitudes des développeurs. Mais il est, me semble-t-il, particulièrement motivant d’avoir à appréhender de nouvelles façons de développer lorsque celles-ci sont plus efficaces et plus performantes. Les développeurs ont tout à gagner à se mettre au RPG FREEFORM, à utiliser au mieux SQL, à développer des programmes de services. C’est un plus pour l’entreprise mais également un plus personnel pour chaque d’entre eux.

Ce qui a pour conséquence une grande disparité dans la façon de nommer les objets comme dans la façon d’écrire les programmes.

Normalisation des développements


Avec les années, le turnover des développeurs internes et les interventions de prestataires externes, on constate bien souvent que chacun a laissé son empreinte, son style, sa façon de développer dans les applicatifs de l’entreprise.

C’est une lapalissade mais il faut normaliser tout ça.

Mettre en place des normes de développement a pour objectifs :

  • De rendre le code homogène afin qu’il soit facilement appréhendable par chaque membre vos équipes.
  • D’identifier facilement les différents objets qui composent vos applications.

Définissez, ensemble, avec tous les membres de vos équipes :

  • Les normes de nommage des objets.
  • Les normes de codification à utiliser dans les sources de vos programmes.

Rédiger un document récapitulatif clair, consultable par chaque membre de vos équipes. Ce document doit devenir une référence, il devra être mis à disposition de chaque nouvelle personne qui rejoindra vos équipes (en interne comme en prestation). Il contribuera à sa bonne intégration et facilitera le respect et la mise en œuvre de ces normes par les nouveaux arrivants.

Définition des Bonnes Pratiques

Là aussi c’est une lapalissade mais c’est très important.

Définissez ces bonnes pratiques, ensemble, en restant à l’écoute des uns et des autres mais en finalisant la réflexion en statuant ces règles dans un document de référence (comme pour les normes de développement).

Et surtout veillez à ce ces bonnes pratiques soient respectées, quitte à développer, si nécessaire, des process de contrôle qui bloqueraient chaque mise en production ne respectant pas les préconisations établies.

Voici quelques exemples de règles de bonnes pratiques classiques dans le cadre de la modernisation :

  • Respecter les normes de développement et les bonnes pratiques définies.
  • Ecrire les nouveaux programmes en RGP FREEFORM.
  • Proscrire les SELECT * dans le SQL EMBEDDED.
  • Gérer les accès à la base de données par SQL.
  • Ne pas créer de nouveaux fichiers physiques ou logiquesDB2, mais créer des tables, index et vues SQL.
  • Convertir chaque programme RPG modifié en programmes RPGLE.
  • Commenter les sources de façon claires et réfléchies en évitant les commentaires inutiles.
  • Utiliser des noms de variables parlant.
  • Ne jamais faire d’accès aux index dans les requêtes SQL, laisser SQL choisir ses modes d’accès aux données.

Documentation et Centralisation des documents

Là aussi, cela semble évident, mais nombre d’entreprise ne documentent pas leurs traitements et s’étonnent ensuite de ne pas maîtriser leurs propres applications.

On constate fréquemment que chaque développeur s’est construit sa propre petite documentation, détaillant telle ou telle chaine de traitement, mais que ces documents ne sont ni partagés, ni à jour.

Il faut donc impérativement :

  • Documenter vos applications.
    Cela peut se mettre en place progressivement, en profitant de chaque nouveau projet, de chaque nouveau développement pour mettre en place cette documentation.
  • Définir des modèles de document qui seront utilisables par tous.
    Cela facilitera la création des documentations suivantes.
  • Centraliser ces documents.
    Pour que chacun puisse y accéder, que chacun puisse y ajouter sa contribution mais surtout pour que toute personne sache où rechercher ces informations.
  • Faire vivre ces documents en les maintenant à jour.

Etat des lieux de vos applicatifs

Faire un état des lieux des applications qui tournent sur l’IBMi permet de quantifier la dette technique à résorber.

Les services SQL permettent en quelques requêtes d’obtenir de très nombreuses informations sur les objets de vos applications.

Elles permettent par exemple :

  • D’identifier les programmes qui n’ont pas été exécutés depuis des années.
    Ces programmes alourdissent vos développements alors qu’ils ne servent plus.
    En effet, chaque analyse d’impact, chaque modification de base de données les prennent en compte ce qui augmente inutilement la charge de travail.
    Identifier ces programmes permet de les sauvegarder leurs sources puis de les supprimer.
    C’est autant de programme qui ne seront plus à moderniser.
  • Contrôler l’unicité des sources des programmes, de façon à n’avoir qu’un seul référentiel de sources. Avoir différentes versions de sources d’un même programme dans différentes bibliothèques est très dangereux. Les développeurs ne doivent pas avoir à s’interroger pour savoir quel est le source à modifier pour ne pas risquer d’écraser les modifications précédemment livrées en production.
  • Vérifier la cohérence entre vos objets de production et votre référentiel de source.
    Il est impératif de pouvoir avoir une totale confiance en son référentiel de source.
    Avoir des objets de production qui ne correspondent pas aux sources du référentiel est très inquiétant. Il faut profiter de la modernisation pour vérifier et remettre la situation à plat.
  • Vérifier et optimiser les requêtes SQL, identifier les plus consommatrices, vérifier et éventuellement créer les index proposés.
  • Mettre en évidence les ratios suivants :
    • Nombre de fichiers DB2 / Nombre de tables SQL
    • Nombre de programme RPG / nombre de programmes RPGLE
  • Identifier le nombre de procédures de services mises en place.

Encapsuler ces requêtes dans des programmes de façon à pouvoir les relancer régulièrement et stocker les résultats obtenus est une idée intéressante.

Cela permettra de mettre en place des métriques pouvant être remontés à la direction pour montrer que le process de modernisation est en œuvre et progresse régulièrement.

Modularisation et utilisation des programmes de service

Convertir les programmes en RPG en RPGLE : c’est bien.

Mais appréhender et mettre en place le concept de programmes de service : c’est mieux.

L’idée qui se cache derrière ce concept est de développer de petits programmes de service, facilement maintenables puisque répondant chacun à une et une seule fonctionnalité bien spécifique. Ces services pourront être ensuite consommés, à chaque instant, par les différents traitements.

Cela permet :

  • D’éviter le code redondant. Puisque le code de la fonctionnalité n’est présent que dans le service et non plus dans chaque chaine de traitement qui utilise sa fonction.
  • De gagner énormément de temps en maintenance puisque seul le service est à modifier en cas d’évolution de la fonctionnalité concernée.
  • De gagner en performance grâce aux groupes d’activation.
    En effet les groupes d’activation permettent de garder en mémoire le service précédemment appelé au sein du même groupe d’activation. Contrairement à un appel de programme classique qui va être monté en mémoire puis déchargé à chaque appel.
  • D’exposer, si nécessaire, ces programmes de services très simplement grâce au serveur intégré à l’IBMi via IWS (websphère), les rendant ainsi également accessibles à des applicatifs hors IBMi.

Ces programmes de services, une fois développés, doivent pouvoir être réutilisés par tous et il ne faut pas qu’une même fonctionnalité face l’objet de plusieurs programmes de service, c’est l’opposé du but recherché.
Pour cela, il est fortement conseillé de mettre en place un dictionnaire de service permettant de :

  • Rechercher les services et les procédures exportées :
    • par leur nom
    • par leur fonction
    • par les tables mise à contribution
  • D’identifier les paramètres en entrée et en sortie de chaque procédure exportée.

En indiquant leur rôle et leur format.

  • De visualiser quelles tables sont utilisées par chaque procédure exportée.

Ceci permettra aux développeurs de trouver facilement le service qui répondra à leur besoin et évitera qu’une même fonctionnalité fasse l’objet de plusieurs services.

Migration progressive d’une base de données DB2 à une base de données SQL

Sans rentrer dés à présent dans le processus de conversion massive de toute la base de données DB2 en base SQL, il est possible de commencer à se dire que toute nouvelle création d’élément de la base de données se fera en SQL.
Ceci en remplaçant les créations de fichiers physiques ou logiques DB2, par des créations de tables, index ou vues SQL.

Ceci permettra de commencer progressivement la bascule de la base de données vers SQL, tout en permettant aux équipes à s’habituer à ce nouveau process.

Accès aux données avec SQL

Cette étape est un peu particulière car il ne s’agit pas juste de dire : il faut faire du SQL EMBEDDED. C’est-à-dire qu’accéder aux données, dans les programmes RPG, par SQL c’est une chose, mais il faut le faire bien.

En effet, cela ne consiste pas simplement à remplacer un CHAIN classique par un SELECT SQL. Cela va bien au-delà de ça.

Par exemple :

Utiliser un CURSEUR SQL, faire une boucle de lecture du curseur, pour ensuite faire différents SELECT à partir des données de chaque enregistrement lu dans le curseur est un non-sens.
Le programme va effectivement accéder aux données par SQL mais sans profiter de la puissance offerte par SQL et les temps de réponses seront donc quasiment similaires à ceux obtenus par un accès « classique » à la base de données.
Alors que si le curseur est fait à partir d’une requête unique comportant des jointures sur les tables lues par les différents SELECT évoqués précédemment ; alors il est plus que probable qu’il y aura un gain de performance significatif.

Outre les gains de performance, SQL apporte également de nombreuses fonctions qui faciliteront les développements.

SQL est un langage qui évolue constamment, et c’est également le cas sur l’IBMi.

De nouvelles fonctions font leur apparition régulièrement.

Et ces fonctions permettent par exemple :

  • De générer un fichier XML en quelques lignes
  • De lire et intégrer un fichier JSON en une seule requête
  • D’envoyer un mail avec le résultat de la requête sous forme de fichier Excel très simplement

Ce ne sont que quelques exemples parmi tant d’autres…

Il est aujourd’hui inconcevable de se passer de SQL même et surtout en tant que développeur IBMi.

Vos équipes auront peut-être, selon leur niveau, besoin de formations avancées sur SQL mais il est indispensable qu’elles sachent utiliser à bon escient les jointures, les tables temporaires, les fonctions SQL afin qu’elles puissent mettre en place des requêtes optimisées, performantes et maintenables facilement dans leurs programmes.

Sans quoi les gains en performance seront restreints alors qu’ils peuvent être tellement importants lorsque les requêtes tirent pleinement profit des possibilités offertes par SQL.

C’est pourquoi, il faudra également présenter aux équipes de développement les outils d’optimisation SQL mis à disposition sous ACS tels que :

  • Visual Explain
  • SQL Performance Center
  • Le Conseil à la création d’index

Implication des équipes de développement

Ces étapes de modernisation sont réalisées par les équipes de développements.
Nous l’avons vu, elles vont avoir besoin de temps pour les mettre en œuvre, mais pas seulement. Il va falloir, si nécessaire, les impliquer en les faisant monter en compétence.

Ceci en :

  • Les formant au RPG FREEFORM si elles ne le connaissent pas déjà
  • Les formant aux concepts des programmes de services
  • Les formant au SQL avancé
  • Les incitant à assister aux événement IBMi qui sont si riches, si formateurs et desquels elles retiendront de nombreuses nouveautés à mettre en pratique.

La démarche de modernisation peut être perçue comme une contrainte mais si c’est le cas c’est que :

  • soit elle a été mal introduite,
  • soit les développeurs n’ont pas les moyens (le temps toujours le temps) de les mettre en pratique et d’en tirer profit.

Si on lui laisse la possibilité de profiter de la modernisation pour monter en compétence, il n’y a aucune raison pour qu’un développeur perçoive la démarche comme une contrainte et n’y adhère pas. Ou alors il est totalement réfractaire au changement mais ça c’est une autre histoire… 

Pour conclure

Ces premières actions ne règleront pas tout, il vous faudra certainement vous outiller ou faire appel à des spécialistes pour répondre à la mise en place du DEVOPS, pour convertir de façon automatique tous vos sources RPG/RPGLE en FREEFORM et pour transformer toutes vos bases DB2 en bases SQL. C’est un fait.

Mais ces actions sont, elles, à la portée de tous et constituent un grand pas dans la démarche de modernisation.

Je détaillerai dans de futures publications comment réaliser telles ou telles étapes abordées de façon synthétique dans ce premier post.

N’hésitez pas à me faire part de vos remarques et/ou de vos questions, je me ferai un plaisir d’y répondre.

Je remercie, encore une fois Pierre-Louis BERTHOIN et Nathanaël BONNET pour la tribune qu’ils m’ont offerte.

J’espère que cet article vous a intéressé et qu’il apportera sa contribution à vos différents projets de modernisation.

Je vous remercie et vous dit à bientôt…

, Mettre des contrôles dans un DSPF

Sur un formulaire de saisie, on va différencier 3 type de contrôles

1) de valeur

exemple doit contenir 1, 2, 3

2) de cohérence

exemple date de fin > date de debut

3) applicatifs

qui nécessite un accès à une ressource externe

exemple

controler que le client existe

Sur une application de type web, on a un formulaire de saisie et les contrôles 1 et 2 sont faits par javascript
et la partie 3 est faite applicativement

Si on considère maintenant un applicatif 5250, on peut faire une grande partie des contrôles 1 directement dans l’écran ,
la partie 2 et 3 seront faites applicativement

Nous allons prendre un DSPF et faire des controles directement dedans

l’écran DSPF


     A*%%TS  SD  20241104  105842  PLB         REL-V7R4M0  5770-WDS
     A*%%EC
     A                                      DSPSIZ(24 80 *DS3)
     A                                      CA03(03)
     A          R FMT01
     A*%%TS  SD  20241104  105842  PLB         REL-V7R4M0  5770-WDS
     A                                  4 29'Ecran de saisie'
     A                                  8 15'Code   :'
     A            CODE           4A  B  8 24DSPATR(MDT)
     A N45                                  DFTVAL('001')
     A                                      CHECK(MF)
     A                                      RANGE('0001' '9999')
     A                                  8 30'Zone remplie obligatoire'
     A                                 11 15'Nom    :'
     A            NOM           30A  B 11 24CHECK(LC)
     A                                      DSPATR(MDT)
     A                                      COMP(NE ' ')
     A                                 12 30'Zone obligatoire '
     A                                 13 30'Minuscules autorisées'
     A                                 15 15'Option :'
     A            OPTION         1N  B 15 24VALUES('1' '2' '4')
     A N45                                  DFTVAL('2')
     A                                 15 30'1 Créer'
     A                                 16 30'2 Modifier'
     A                                 17 30'4 Supprimer'
     A                                 22  5'F3=Exit'
     A                                  9 30'Chiffre uniquement'

Nous allons contrôler que
la zone CODE est remplie
la zone NOM n’est pas vide
la zone OPTION doit prendre comme valeur 1, 2 et 4

On dispose des contrôles
de saisie souvent des CHECK
de validité, COMP, RANGE, VALUE

Pour que le contrôle soit déclenché, la zone devra être modifiée ou on forcera le DSPATR(MDT), pour faire comme si c’était le cas.

Remarque
Les contrôles de saisie sont effectués dans tous les cas (CFXX, ENTER, CAXX)
Les contrôles de validité sont effectués uniquement dans cas (CFXX, ENTER)

Le programme RPGLE pour tester

**free
ctl-opt DFTACTGRP(*NO) ;
dcl-f Controle WORKSTN ;
  dou *in03 ;
    exfmt fmt01 ;
    if not *in03;
    endif ;
  // Contrôle des zones
   *in45 = *on ;
  enddo ;
  *inlr = *on ;

Remarque :
Dans cet exemple, on utilisera l’indicateur 45 pour ne plus affecter de valeur par défaut

Vous pouvez ainsi simplifier votre application d’une grande partie des contrôles basics

Vous pouvez indiquer , un message différent par le mot clé CHCKMSGID()

, , Utilisez de l’Unicode en 5250

Unicode permet d’encoder des caractères complexes sous deux octets

Un site pour avoir des informations supplémentaires

https://fr.wikipedia.org/wiki/Unicode

Vous voulez afficher des caractères Unicode dans votre session 5250,

parce que vous travaillez avec la chine par exemple.

Voici un petit exemple pour vous indiquer les grandes étapes

Rappel:

Pour avoir des caractères Unicode, vos zones doivent être déclarées comme ceci

NOM VARGRAPHIC(30) CCSID 1200 NOT NULL

Vous pouvez insérer des caractères dans votre table par SQL par exemple

Exemple chinois et russe

INSERT INTO NOMTBL (NOM) VALUES(
(‘张’), (‘Иванов’) )

Dans votre DSPF, vous pouvez déclarer zones par référence

niveau fichier
A REF(*LIBL/NOMTBL)

niveau zone
A NOM R O 6 4REFFLD(PERSONNES/NOM *LIBL/NOMTBL)

Vous obtiendrez le résultat suivant ;

Vous devrez également indiquer sur la commande de compile de l’écran (CRTDSPF),

le paramètre IGCDTA(*YES)

Votre session ACS devra supporté l’Unicode comme ceci

Votre programme en RPGLE par exemple n’aura aucune différence par rapport à des caractères latins

Voici le résultat d’un affichage

Remarque :


Vous pouvez faire beaucoup de choses
Tout n’est pas parfait , pas de solution simple pour utiliser les MSGID et MSGCON …

Vous devrez avoir un clavier qui vous permet de saisir les caractères souhaités

, , Utilisez DRDA sur #IBMi

Dans ACS vous avez des exemples comme si dessous

Vous indiquer le nom de votre base de données distantes et vous exécuter votre requête sur le système distant.

derrière cette requête ce cache un protocole nommé DRDA , comme ODBC il permet de ce connecté à une base de donnée distante.

Nous allons voir comment le mettre en œuvre .

sur le système source
Vous devez créer une entrée pour la base de données

le plus simple c’est de passer par la commande WRBRDBDIRE , vous ajouterez une connexion IP à votre système distant.

Sur le système cible
Vous devez paramétrer le service par la commande CHGDDMTCPA , il faut avoir le même mode d’authentification que la base de données distante, par défaut user + mot de passe
vous devez démarrer le service STRTCPSVR *DDM

voila c’est tout
vous pouvez à partir de votre système source faire un connect SQL sur votre système cible si vous avez un mot de passe.

Si vous ne voulez pas renseigner de mot de passe comme dans les exemples ACS vous allez devoir utiliser sur votre système source les postes poste d’authentification serveur.
Pour les ajouter vous avez la commande ADDSVRAUTE, vous devrez également avoir mis la valeur système QRETSVRSEC à ‘1’ pour que vos mots de passe soit enregistrés

il est conseillé d’ajouter un poste générique, par exemple QDDMDRDASERVER en indiquant un user et un mot de passe du système cible !

il n’y a pas de commande WRKSRVAUTE mais vous pouvez en trouver une ici https://github.com/Plberthoin/PLB/tree/master/GTOOLS/

Exemple :

A partir de ce moment la mot de passe sera passé directement.

Vous pouvez facilement, par des services sql comparer 2 partitions (valeurs systèmes, fonctions , etc …)

Remarques

Les noms doivent être en majuscule
il est conseillé de mettre un programme d’exit de contrôle
Attention, vous pouvez vous connecter avec un utilisateur *disabled
Les fichier DDM sur IP s’appuient sur cette technologie

, Utilisez NFS sur votre IBMi

NFS est un protocole de partage de fichier issu du monde Unix, SMB est celui de windows c’est celui qui est utilisé dans NETSERVER.

https://fr.wikipedia.org/wiki/Network_File_System

Nous allons voir comment l’utiliser NFS sur l’IBMi qui peut être client et serveur par exemple pour partager un fichier d’installation ou de paramétrage.

Sur le serveur

Vous devez démarrer le serveur.

STRNFSSVR SERVER(*ALL)

Vous devez créer le répertoire à exporter

CRTDIR (‘/SHARE_NFS’)

Vous devez monter l’export

Paramétrage dans exports vous avez un fichier

EDTF STMF(‘/etc/exports’)
/SHARE_NFS/URANUS -ro

pour exporter

EXPORTFS

Si tout se passe bien vous aurez ce message :

Demande d’exportation exécutée.
1 postes exportés, 0 postes non exportés.

Vous pouvez être obligé de rajouter des droits sur votre partage :

CHGNFSEXP OPTIONS(‘-I -O RW=,ANON=0’) DIR(‘/SHARE_NFS/URANUS’)

Votre répertoire est maintenant exporté.

Sur le client

Vous devez démarrer le même serveur.

STRNFSSVR SERVER(*ALL)

Vous devez créer un répertoire pour le montage

MKDIR DIR(‘/MNT/NEPTUNE’)

Vous devez faire le montage

MOUNT TYPE(*NFS) MFS(‘NEPTUNE:/SHARE_NFS/URANUS’)
MNTOVRDIR(‘/MNT/NEPTUNE’)

Si tout va bien vous aurez ce message :


Système de fichiers monté.

Vous pouvez contrôler par :

DSPMFSINF OBJ(‘/MNT/NEPTUNE’)

Objet . . . . . . . . . . . . : /MNT/NEPTUNE

Type de système de fichiers . : Syst. de fichiers réseau (NFS)

Taille de bloc . . . . . . . . : 32768
Nombre total de blocs . . . . : 23303175
Blocs libres . . . . . . . . . : 5182808
Nombre maximal de liens à des
objets . . . . . . . . . . . : 32767
Nombre maximal de liens à un
répertoire . . . . . . . . . : 1000000
Longueur maximale d’un
composant de nom de chemin . : 255
Longueur maximale de nom de
chemin . . . . . . . . . . . : Pas de maximum

Pour accéder au fichier par exemple :

wrklnk (‘/mnt/NEPTUNE/*’)

Répertoire . . . . : /mnt/NEPTUNE

Vous pourrez voir votre fichier par 5

Remarque :

Vous pouvez l’utiliser que en serveur ou en client avec un système distant sous Linux le plus souvent.

C’est un protocole très connu par les administrateurs Unix.

Pour échanger entre IBMi, vous pouvez également utiliser QFileSvr.400

, , Nommer un groupe d’activation pour des programmes RPGLE

Vous voulez nommer votre groupe d’activation pour toute une application
donc sans indiquer d’option dans le source qui seraient prioritaires par rapport à votre commande de compile

On va parler ici des BIND c’est l’opération que fait une commande pour compiler le module et l’assembler pour en faire un programme

Pour les sources RPGLE

C’est simple vous avez un paramètre

CRTBNDRPG PGM(GDATA/AAACTGRP)
SRCFILE(GDATA/QRPGLESRC)
SRCMBR(AAACTGRP)
DFTACTGRP(NO) ACTGRP(GAIA) <======== c’est ici

Pour les SQLRPGLE

Vous n’avez pas le paramètre ACTGRP dans la commande CRTSQLRPGI

il faut donc passer par les options de compile c’est le paramètre COMPILEOPT

CRTSQLRPGI OBJ(GDATA/AAACTGRP2)
SRCFILE(GDATA/QRPGLESRC)
SRCMBR(AAACTGRP2)
OBJTYPE(PGM) REPLACE(NO)
COMPILEOPT(‘DFTACTGRP(*NO) ACTGRP(GAIA)’) <====== comme ceci

On est obligé de mettre les 2 paramètres même si DFTACTGRP(*NO) dans le source ????

Attention, il n’y a pas de contrôle de syntaxe sur le paramètre

Remarque

Bien sur mes informations concernent les binds, pour l’assemblage de modules l’option est dans la commande CRTPGM directement

, , , Connaitre la bibliothèque du programme en cours

Vous voulez connaitre la bibliothèque d’un programme en cours d’exécution, pour ajouter cette bibliothèque par exemple, pour contextualiser un exit programme, un watcher, un trigger ou pour limiter un environnement prod, versus dev.
Le tout, sans harcoder une bibliothèque qui figera votre code et vos environnements.

Voici 2 exemples

En RPGLE

dcl-ds *N PSDS ;                  
  bibli_du_pgm CHAR(10) POS(81);  
  nom_du_pgm CHAR(10) POS(1);     
 End-ds ;                          
dcl-s present ind ;
// on tente d'ajouter la bibliothèque
 exec sql                                                                  
 call qcmdexc('Addlible ' concat :bibli_du_pgm concat ' *FIRST') ;         
if sqlcode = 0 ;
  present = *on ;
endif ;
// votre traitement ici
// on enlève si on a ajouté 
if present = *on ;
 exec sql                                                                  
 call qcmdexc('Rmvlible ' concat :bibli_du_pgm ) ;         
endif ;

En CLLE

PGM                                                    
            DCL        VAR(&DATA) TYPE(*CHAR) LEN(80)  
            DCL        VAR(&LIB) TYPE(*CHAR) LEN(10)   
            DCL        VAR(&PGM) TYPE(*CHAR) LEN(10)   
            DCL        VAR(&TEMOIN) TYPE(*LGL)
 /* Paramétrage de l'appel */                          
            CHGVAR     VAR(%BIN(&DATA  1 4)) VALUE(80) 
            CHGVAR     VAR(%BIN(&DATA  5 4)) VALUE(80) 
            CHGVAR     VAR(%BIN(&DATA  9 4)) VALUE( 0) 
            CHGVAR     VAR(%BIN(&DATA 13 4)) VALUE( 0) 
 /* Appel de la procédure */                           
            CALLPRC    PRC('_MATPGMNM') PARM(&DATA)    
 /* Extraction des informations  */                    
            chgvar &pgm %SST(&DATA 51 10)              
            chgvar &lib %SST(&DATA 19 10) 
/* ajout de la bibliothèque */
ADDLIBLE &LIB *FIRST
monmsg cpf2103 exec(do)
chgvar &temoin '1'
enddo 
/* Votre traitement ici */
/* on enlève si on a ajouté */
if cond(*not &temoin) then(do)
RMVLIBLE &LIB
enddo          
ENDPGM          

Remarque :

On a mis également le programme en cours dans les exemples

On a mis le code pour enlever la bibliothèque après le traitement, uniquement si c’est notre programme qui l’a ajouté.


En RPGLE si vous avez un fichier vous devrez déclarer votre fichier en USROPN et ouvrir le fichier par un OPEN, après avoir ajouté la bibliothèque

, , Fichier SQLPRE de QTEMP

Vous avez des sources SQLRPGLE qui sont différents des tailles par défaut de 100

Vous pouvez avoir ce message à la compile RNF0733
C’est le fichier, QTEMP/QSQLPRE de pré-compilation qui est trop court QTEMP/QSQLPRE
Ce fichier est utilisé dans les commandes CRTBNDRPG , CRTRPGMOD, ou CRTSQLRPGI

Vous avez une variable d’environnement QIBM_RPG_PPSRCFILE_LENGTH qui permet de changer la valeur par défaut qui est de 112.
Elle doit avoir la longueur de votre donnée + 12
Exemple
SRCDTA = 140
Vous devrez indiquer 152

Pour ajouter la variable :

ADDENVVAR ENVVAR(QIBM_RPG_PPSRCFILE_LENGTH.)
VALUE(152)
LEVEL(*SYS)

*SYS pour l’ajouter à tout le système

Pour ne savoir plus ici

https://www.ibm.com/support/pages/node/6857461

, , Trigger sur insert

Vous voulez créer un trigger qui vous indique la création d’un enregistrement dans un fichier par exemple pour superviser, dans notre exemple on enverra un email , il est conseillé de faire un fichier de paramétrage

En CLLE soit le programme Alerte_msg


             PGM        PARM(&BUFFER &BUFLEN)             
/* Paramètres */                                          
             DCL        VAR(&BUFFER) TYPE(*CHAR) LEN(200) 
             DCL        VAR(&BUFLEN) TYPE(*CHAR) LEN(4)   
/* Variables de travail */                                
             DCL        VAR(&USR) TYPE(*CHAR) LEN(10)     
             DCL        VAR(&JOB) TYPE(*CHAR) LEN(10)     
             DCL        VAR(&NBR) TYPE(*CHAR) LEN(06)
             DCL        VAR(&EMAIL) TYPE(*CHAR) LEN(50)
             DCL        VAR(&SUJET) TYPE(*CHAR) LEN(100)
             DCL        VAR(&NOTES) TYPE(*CHAR) LEN(200)
             RTVJOBA    JOB(&JOB) USER(&USR) NBR(&NBR)    
             CHGVAR     VAR(&EMAIL) VALUE('votre@mail.fr')
             CHGVAR     VAR(&SUJET) VALUE('Enregistrement crée')
             CHGVAR     VAR(&NOTES) VALUE('Job :' +
                          *BCAT &NBR *TCAT '/' *TCAT &USR *TCAT '/' +
                          *TCAT &USR)                                    
 SNDSMTPEMM RCP((&EMAIL)) SUBJECT(&SUJET) NOTE(&NOTES) +
             CONTENT(*HTML)            
  MONMSG     MSGID(CPF0000) EXEC(GOTO CMDLBL(ERREUR))
goto fin                                                           
/* Gestion des erreurs  */                                         
erreur:                                                            
             SNDUSRMSG  MSG('Envoi email impossible pour msgint ' +
                          *bcat &job *bcat &usr *bcat &nbr ) +     
                          MSGTYPE(*INFO)                           
fin:                                                               
ENDPGM 

Pour attacher votre programme et enregistrer votre trigger

 ADDPFTRG   FILE(&LIB/REP_VALID) TRGTIME(*AFTER)     
              TRGEVENT(*INSERT) PGM(&LIB/ALERT_MSG) 
              TRGLIB(&LIB) 

&lib sera le nom de votre bibliothèque

En SQL ca créera un programme CEE et ca l’associera au trigger

CREATE OR REPLACE TRIGGER ALERTE_MSG                                   
 AFTER  INSERT ON REP_VALID                                            
 REFERENCING NEW AS N                                                  
 FOR EACH ROW                                                          
 MODE DB2ROW                                                           
-- email destinataire                                                  
 BEGIN                                                                 
DECLARE W_EMAIL CHAR(50);                                              
DECLARE W_SUJET CHAR(100);                                             
DECLARE W_NOTES CHAR(200);                                             
DECLARE EXIT HANDLER FOR SQLSTATE '38501'                              
 RESIGNAL SQLSTATE '38501' SET MESSAGE_TEXT = 'ENVOI MAIL IMPOSSIBLE.';
SET W_NOTES = 'Job : ' concat trim(N.REPNBR)                  
concat '/' concat trim(N.REPUSER) concat '/' concat trim(N.REPJOB) ;
SET W_EMAIL = 'votre@email.fr' ;                 
SET W_SUJET = 'Enregistrement crée' ;   
CALL QCMDEXC('SNDSMTPEMM RCP((''' concat trim(w_email) concat           
''')) SUBJECT(''' concat trim(replace(w_sujet , '''', '"'))             
concat ''') NOTE('''                                                    
concat trim(replace(W_NOTES , '''' , '"')) concat''') CONTENT(*HTML)') ;
END;  

Remarques :

Dans les 2 cas si l’utilisateur n’est pas inscrit à la liste de distribution votre email ne sera pas envoyé
c’est plus simple de gérer l’erreur en CLP.
Si vous devez accéder aux données du buffer ca sera plus rapide et plus simple en SQL ici n.zone

C’est des triggers après , puisque l’information doit être écrite dans tous les cas .

, , Afficher plusieurs colonnes d’enregistrements dans un sous-fichier

Contexte

Un sous-fichier nous permet d’afficher un nombre de lignes qui est limité par la taille de l’écran.
Cette taille est définie dans le script source de l’écran par le paramètre SFLPAG.

On possède un fichier que l’on souhaite afficher et qui contient plus de 19 enregistrement. Il serait donc intéressant de l’afficher sur plusieurs colonnes.

Solution

Une petite modification du script source permet de créer un sous fichier qui contient plusieurs colonnes. Il faut donc indiquer le nombre total de données que l’on souhaite voir à l’écran dans SFLPAG ainsi que le nombre de caractère qui séparent deux colonnes

La maquette se présente ainsi, le paramètre de SFLLIN correspond à l’espace (en caractères) entre deux colonnes.

En exécutant le programme, on obtient :