Je vais essayer de vous expliquer le routage des travaux interactifs.
Un travail interactif est routé vers un sous système par rapport au nom de son unité.
Vous l’indiquez dans la commande ADDWSE Vous avez 2 paramètres WRKSTN() nom écran ou nom générique WRKSTNTYPE type d’écran
l’ordre c’est nom nom générique type
Par contre ce n’est pas dynamique un écran affecté ne sera pas réaffecté dynamiquement, si par exemple votre sous système spécifique est démarré après QINTER.
Il peut être important pour des questions d’administration d’avoir les travaux dans le bon système.
On peut donc ajouter un programme SDA (sélection dynamique à l’arrivée), parce que le critère de nom n’est pas forcément suffisant , ou que suite à un redémarrage, on veut replacer le travail dans le bon sous système, ou tout autre raison.
C’est dans les données de routage qu’il va falloir agir, par défaut PGM(QCMD), mais vous pouvez indiquer un programme à vous. Ce programme ne reçoit pas de paramètre extérieur et il va par rapport à un algorithme que vous aurez déterminé transférer le travail vers une JOBQ, c’est la commande TFRJOB qui permet de transférer Le plus souvent on utilise comme critère l’utilisateur ou le nom de l’unité, mais on peut ajouter beaucoup d’autres critéres
Voici un exemple très simple et relativement classique, à mettre sur QINTER qui est souvent le sous système par défaut puisqu’il a une entrée par type
/*------------------------------------------------------------------*/
/* Ce programme est utilisé dans un sous système interactif */
/* dans les données de routage il va rerouter une jobq */
/* ADDRTGE ... PGM(MALIB/REROOT) */
/* Ce programme doit être en adoption de droit par rapport QSECOFR */
/*------------------------------------------------------------------*/
PGM
dcl &user *char 10 /* Utilisateur en cours */
dcl &grp *char 10 /* Groupe de l'utilisateur */
dcl &unit *char 10 /* nom de l'unité */
dcl &status *char 2
/* information pour adresse ip */
dcl var(&IPV4ADDR) type(*char) len(15)
DCL VAR(&JOBI) TYPE(*CHAR) LEN(700) VALUE(' ')
DCL VAR(&JOBILEN) TYPE(*DEC) LEN(4 0) VALUE(700)
DCL VAR(&FMTNAME) TYPE(*CHAR) LEN(8) VALUE(JOBI0600)
DCL VAR(&QUALJN) TYPE(*CHAR) LEN(26) VALUE('*')
DCL VAR(&INJOB) TYPE(*CHAR) LEN(16) VALUE(' ')
/*-------------------------------------------------*/
/* Extraction des informations de routage */
/* ici Utilisateur, groupe et nom unité */
/*-------------------------------------------------*/
RTVJOBA USER(&USER) job(&unit)
RTVUSRPRF GRPPRF(&GRP)
/* Call QUSRJOBI to retrieve job information */
CALL PGM(QSYS/QUSRJOBI) PARM(&JOBI &JOBILEN &FMTNAME +
&QUALJN &INJOB)
/* Extract data from the output of QUSRJOBI */
CHGVAR VAR(&IPV4ADDR) VALUE(%SST(&JOBI 308 15))
/*-------------------------------------------------*/
/* Règles de routage sur utilisateur et groupe */
/*-------------------------------------------------*/
if cond(&GRP = 'COMPTA') then(do)
TFRJOB JOBQ(COMPTA)
enddo
/*-------------------------------------------------*/
/* Règles de routage sur unité */
/* reroutage de l'unité de secours dans QCTL */
/* Pour faire des operations en mode restreint */
/*-------------------------------------------------*/
if cond(&UNIT = 'SECOURS') then(do)
TFRJOB JOBQ(QCTL)
enddo
/*-------------------------------------------------*/
/* Règles de routage sur nom d'ecran */
/* AAAAAAxxxxx vers JOBQ AAAAAAJOBQ */
/* AAAAAA racine de l'ecran */
/* xxxx numéro */
/*-------------------------------------------------*/
chgvar &status 'OK'
CHKOBJ OBJ((%SST(&UNIT 1 6) *TCAT 'JOBQ')) +
OBJTYPE(*JOBQ)
monmsg cpf9800 exec(do)
chgvar &status 'KO'
enddo
/* si JOBQ existe */
if cond(&status = 'OK') then(do)
TFRJOB JOBQ((%SST(&UNIT 1 6) *TCAT 'JOBQ'))
enddo
/*-------------------------------------------------*/
/* Règles de routage sur adresse ip */
/* Ici controle adresse ip avec refus si pas reseau*/
/* 172 */
/*-------------------------------------------------*/
if cond(%sst(&IPV4ADDR 1 3) *ne '172') +
then(do)
SNDMSG MSG('Tentative de connexion refusée,' *BCAT +
&IPV4ADDR *BCAT ', sur adresse IP' *BCAT +
&UNIT) TOMSGQ(*HSTLOG)
ENDJOB JOB(*)
enddo
/*-------------------------------------------------*/
/* Les autres ne sont pas reroutés */
/*-------------------------------------------------*/
endpgm
Dans notre exemple, on a ajouté un contrôle sur l’adresse IP avec un blocage si pas le réseau attendu
Remarques :
La limite c’est votre imagination, vous devez bien réfléchir et cibler votre besoin , vous pouvez par exemple ajouter du paramétrage
Vous pouvez également utiliser le programme d’exit (QIBM_QTG_DEVINIT) , mais plus compliqué à mettre en œuvre
Vous devez vous assurer que le programme utilisé pour SDA ne plante pas
Les unités peuvent être créer automatiquement c’est la valeur système QAUTOVRT
Si vous choisissez de l’utiliser, préférez un nombre (exemple : 500 ) plutôt que *NOMAX et tous les 6 mois faites un coup de ménage sur les unités inutilisées
===> DSPOBJD OBJ(ALL) OBJTYPE(DEVD)
Vous pouvez les identifier facilement :
Par défaut les unités s’appellent QPADEVxxxx , ne pas hésiter à les supprimer 2 fois par an
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2025-07-23 14:06:242025-07-27 11:28:07Routage des travaux interactifs
Vous avez une instruction SQL , MERGE qui est assez PUISSANTE pour fusionner des fichiers Voici un exemple complet :
Il intègre les éléments suivants -La création -La mise à jour -La suppression
On a 2 tables Products et Mouvements
Les règles choisies sont les suivantes :
-Si le produit existe on ajoute la quantité -S’ il est nouveau, on le créé -Si nom du produit est SUPPRESSION, on supprime
J’ai utilisé la convention de nommage *SYS
et dans tous les cas on met à jour la date de modification
-- voici les scripts pour tester
-- Création de la table des produits
-- Option *SYS et *NONE
CREATE TABLE GDATA/PRODUCTS (
PRODUCT_NUMBER DECIMAL(10, 0) NOT NULL ,
PRODUCT_NAME VARCHAR(100) NOT NULL,
QUANTITY DECIMAL(10, 0) NOT NULL DEFAULT 0,
LAST_UPDATE_TS TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (PRODUCT_NUMBER)
);
-- alimentation du fichier
INSERT INTO GDATA/PRODUCTS VALUES(1, 'CLOU', 50, current timestamp) ;
INSERT INTO GDATA/PRODUCTS VALUES(2, 'VIS', 20, current timestamp) ;
INSERT INTO GDATA/PRODUCTS VALUES(3, 'ECROU', 25, current timestamp) ;
INSERT INTO GDATA/PRODUCTS VALUES(4, 'RONDELLE', 120, current timestamp) ;
-- Création de la table des mouvements
CREATE TABLE GDATA/MOUVEMENTS (
PRODUCT_NUMBER DECIMAL(10, 0) NOT NULL ,
PRODUCT_NAME VARCHAR(100) NOT NULL,
QUANTITY DECIMAL(10, 0) NOT NULL DEFAULT 0,
LAST_UPDATE_TS TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (PRODUCT_NUMBER)
);
-- alimentation de la tables des mouvements
INSERT INTO GDATA/MOUVEMENTS VALUES(1, 'CLOU', 30, current timestamp) ; -- changement de quantité
INSERT INTO GDATA/MOUVEMENTS VALUES(3, 'SUPPRESSION', 0, current timestamp) ; -- suppression
INSERT INTO GDATA/MOUVEMENTS VALUES(5, 'RESSORT', 100, current timestamp); -- Nouveau
-- Fusion des 2 tables
MERGE INTO GDATA/PRODUCTS AS T -- T est l'alias de la table CIBLE (PRODUCTS)
USING GDATA/MOUVEMENTS AS S -- S est l'alias de la table SOURCE (MOUVEMENT)
ON (T.PRODUCT_NAME = S.PRODUCT_NAME) -- La jointure se fait sur le nom du produit
-- 1. Gérer la suppression si le produit correspond ET que la source indique 'SUPPRESSION'
WHEN MATCHED AND S.PRODUCT_NAME = 'SUPPRESSION' THEN
DELETE
-- 2. Gérer la mise à jour si le produit correspond ET que la source N'indique PAS 'SUPPRESSION'
WHEN MATCHED AND S.PRODUCT_NAME <> 'SUPPRESSION' THEN
UPDATE SET T.QUANTITY = T.QUANTITY + S.QUANTITY,
T.LAST_UPDATE_TS = CURRENT_TIMESTAMP
-- 3. Gérer l'insertion si le produit NE correspond PAS ET que la source N'indique PAS 'SUPPRESSION'
WHEN NOT MATCHED AND S.PRODUCT_NAME <> 'SUPPRESSION' THEN
INSERT (PRODUCT_NUMBER, PRODUCT_NAME, QUANTITY, LAST_UPDATE_TS)
VALUES (S.PRODUCT_NUMBER, S.PRODUCT_NAME, S.QUANTITY, CURRENT_TIMESTAMP);
Remarque :
Vous pouvez également utiliser la commande CPYF avec le paramètre MBROPT(*UPDADD) mais plus compliqué de gérer les suppressions.
Access Client Solutions 1.1.9.8, disponible depuis avril 2025, amène son lot d’évolutions. Une m’a particulièrement intéressée : l’affichage des index considérés.
Visual Explain, les index ?
Visual Explain permet d’afficher le plan d’exécution de la requête SQL : l’ensemble des étapes nécessaires à l’obtention du résultat, de la façon la plus optimisée possible.
Pour déterminer la façon la plus optimisée, le moteur SQL va réécrire la requête, considérer les index/LF existants, exploiter les statistiques de chaque table, index ou clé sous-jacents aux tables utilisées dans la requête.
Dans le plan affiché, pour une première analyse macroscopique, on cherche en général les éléments suivants :
Scan de table : on préfère utiliser des accès par index plutôt que parcourir l’ensemble de la table. Il s’agit d’analyser pourquoi aucun index ne satisfait les conditions de la requête
Les index utilisés : même si l’on se félicite de l’utilisation d’index, il est souvent possible de faire mieux
Les index recommandés : justement pour faire mieux !
Une information est disponible mais difficilement exploitable : l’optimiseur explique pour chaque index trouvé pourquoi il a été utilisé, ou pourquoi il ne l’a pas été.
Un exemple
Nous avons une table dans laquelle nous consolidons certains événements logués par nos serveurs web (access_log générés par Apache). Aujourd’hui cette table HTTPLOG contient environ 240 millions d’entrées, et dispose bien évidemment d’un certains nombres d’index existants :
Prenons une requête basique :
L’affichage de Visual Explain nous montre :
En sélectionnant l’étape « Test de table », le volet de droite indique :
Ce sont la liste des index que l’optimiseur a regardé et le chiffre correspond au code qui indique pourquoi il n’a pas été utilisé. Il est possible d’aller chercher le détail des codes dans les messages (il faut activer les messages de débogage).
Cette information est accessible pour chaque étape du plan, dans le cas de jointure ou de sous-requête.
Index considérés
Prenons une autre requête SQL permettant d’analyser toutes les requêtes HTTP authentifiées et dont le retour provoque un warning ou une erreur (autre que code HTTP 200 OK).
Visual Explain nous donne :
Nous retrouvons bien entendu nos informations sur les index :
Mais il est maintenant possible de demander ces informations pour l’ensemble de la requête :
Et d’obtenir des libellés plus parlants :
Cela vous donne plus d’informations quant à l’usage des index. Pour compléter, l’index advisor nous donne :
A noter que l’optimiseur ne propose pas d’index dérivé par exemple, ou difficilement les index EVI … Gardez donc un œil critique sur ces informations, mais leur compréhension est nécessaire.
En SQL embarquée la gestion des erreurs est différente par rapport à un RPGLE classique.
Essentiellement sur 2 points
1) Ca ne plante pas Vous pouvez donc avoir des erreurs silencieuses Il est très important de traiter les SQLCODE Même si vous pensez ne pas en avoir besoin Les 3 lignes suivantes peuvent être ajoutées sans risque !
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2025-07-12 09:07:372025-07-12 09:09:04Gestion du SQLCODE dans un SQL embarqué
Vous connaissez l’option ACS qui vous permet de gérer vos SPOOLs , c’est une alternative intéressante à la commande WRKSPLF et si vos utilisateurs ont beaucoup de spools à gérer, ca peut leurs simplifier la tache, n’hésitez pas à leurs donner l’option, c’est relativement intuitif .
Vous pouvez par exemple faire simplement un fichier PDF et le joindre à un mail .
Vous voulez simplifiez la vie de vos utilisateurs en leurs présentant cette option à la place d’un WRKSPLF dans vos applications existantes
Voici une ébauche de solution
Un programme de lancement
Vous devrez d’abord écrire un programme qui lance l’option ACS à partir de votre programme IBMi à base des commandes STRPCO et STRPCCMD
Voici un exemple RPGLE
**free
// Ce programme permet de remplacer les commandes WRKSPLF par
// L'explorateur de spool ACS
// ici le javabundle est dans \Users\Public\IBM\ClientSolutions\
//
dcl-s cmd CHAR(1024) ;
// démarrage de PCO
cmd ='STRPCO' ;
exec sql call qsys2.qcmdexc(:cmd) ;
// Démarrage de l'explorer de spools
cmd =' +
STRPCCMD PCCMD(''java -jar C:\Users\Public\IBM\ClientSolutions\acsbundle.jar +
/PLUGIN=splf /system=neptune +
Picked up _JAVA_OPTIONS: -Djava.net.preferIPv4Stack=true'') PAUSE(*NO)' ;
exec sql
call qsys2.qcmdexc(:cmd) ;
*inlr= *on ;
On a fixé le répertoire du programme ici \Users\Public\IBM\ClientSolutions\
Si vous lancez ce programme, vous ouvrez alors l’écran ACS de gestion des spools, il est possible que cela vous redemande le mot de passe en fonction de votre paramétrage.
Un programme pour Associer à la commande WRKSPLF
Si vous voulez automatiser, vous pouvez utiliser un programme d’exit sur l’exit point QIBM_QCA_CHG_COMMAND
Vous avez la commande ADDEXITPGM pour ajouter un programme d’exit , vous pouvez également passer par la commande ==>WRKREGINF et faire l’option 8
Remarque :
Vous pouvez comme ici mettre une commande WRKSPLF dans une bibliothèque avant QSYS, qui vous permettra de bien gérer que les interactifs et de bypasser si besoin en faisant ==>QSYS/WRKSPLF .
Vous aurez intérêt a identifier les utilisateurs qui doivent bénéficier de la fonctionnalité, une solution très simple c’est l’utilisation d’une liste d’autorisation
https://www.gaia.fr/wp-content/uploads/2017/02/team3.png600600Pierre-Louis BERTHOIN/wp-content/uploads/2017/05/logogaia.pngPierre-Louis BERTHOIN2025-07-05 16:06:412025-07-07 11:22:16Gestion des spools par ACS
Avec la version V7R6, une nouvelle fonction usage est disponible, elle sert à éviter les soumissions pour un autre profil, paramétre USER( ) dans un SBMJOB,
Même si vous êtes autorisé au profil, vous ne pourrez pas soumettre pour lui
exemple :
Avant
Paramétrage
Sous navigator for i
Après
Conclusions :
Sur certains profils sensibles vous pouvez interdire leurs usage dans un SBMJOB , même pour des utilisateurs *ALLOBJ par exemple
Grand merci à Nathanael pour la mise à disposition de cette V7R6
https://www.gaia.fr/wp-content/uploads/2025/02/DT-1-e1739799848306.png205175Damien Trijasson/wp-content/uploads/2017/05/logogaia.pngDamien Trijasson2025-06-30 15:42:392025-06-30 15:52:34Sécurité : Utilisation des classes java toolbox vs job technique OS
Nous sommes de plus en plus nombreux à utiliser Code for IBM i !
Nous avons de nombreuses questions sur cet outil, en constante évolution.
Cette semaine, nous avons choisi de parler des profils, et de la confusion entre le profiles Visual Studio Code et les profils Code for IBM i.
Et les profils IBM i ?
Nous n’en parlerons pas ici !
Un profil IBM vous permet de vous connecter à la machine et n’existe que côté serveur.
La notion de profils dans Visual Studio Code (noté VSCode pour la suite) concerne la configuration des environnements de travail dans l’IDE.
Profil Code for IBM i
A la connexion à votre IBM i, VSCode établi une communication via un job SSH. Ensuite, l’interface propose plusieurs éléments de configuration et de navigation :
User Library List (partie utilisateur de la liste de bibliothèque) + current library (bibliothèque en cours)
Object browser (filtres sur objets / membres)
IFS shortcuts (filtres sur répertoires / fichiers)
Une fois connecté, la liste de bibliothèque affichée est celle utilisée à votre dernière connexion.
Vous pouvez modifier la bibliothèque en cours par click droit sur current library (ouvre un prompt) ou sur click droit sur une bibliothèque à définir comme en cours :
De même pour la liste de bibliothèque : ajout / suppression / réorganisation :
Une fois votre environnement configuré, la sauvegarde sous forme de profil vous permet de mémoriser cette configuration et de pouvoir revenir dessus plus rapidement par la suite :
Donner un nom à l’enregistrement :
Une nouvelle option de gestion des profils est alors affichée :
Elle vous permet de revenir à la situation d’origine de votre profil (si vous avez ajouter/supprimer des bibliothèques par exemple) :
Mais surtout vous pouvez créer d’autres profils, correspondants à d’autres situations :
Développement projet 1
Développement projet n …
Tests projet 1
Production
…
Vous pouvez aussi créer un profil directement en indiquant une commande de mise en place de l’environnement, basiquement un CHGLIBL :
Pour plus de souplesse, surtout lors de travail en équipe, nous vous conseillons de créer une *JOBD par « projet » côté serveur, avec une commande qui met en place les bibliothèque de la *JOBD. Cela vous permet de modifier la *JOBD sans intervenir sur l’ensemble des clients :
En réalité, le profil permet de stocker l’ensemble des éléments suivants :
Le profil Visual Studio Code vous permet d’avoir plusieurs configurations de VSCode avec une installation unique : des attributs de l’environnement peuvent être modifiés via un fichier de configuration.
Depuis le menu des paramètres, aller dans les profils :
Nous pouvons alors gérer les profils, en créer/supprimer, modifier les attributs :
Il est par exemple possible de créer un profil :
Par copie d’un profil existant, ou totalement vide. Et lors de la copie, vous choisissez les éléments de paramétrages, de personnalisation de clavier etc … Une icône spécifique peut être attribuée pour identifier rapidement les profils.
Certains profils types sont également fournis :
Une fois le profil créé, vous pouvez passer de l’un à l’autre :
Ou bien ouvrir une autre fenêtre avec un profil différent :
Depuis les propriétés du profil, les différentes catégories (Settings, keyboard shortcuts etc …) correspondent à des fichiers de configuration différents. Lorsque vous double-cliquer sur « Settings » :
Vous pouvez modifier les propriétés en direct, le changement est pris en compte à l’enregistrement du fichier :
Vous remarquez que l’ensemble des informations des profils Code for IBM i sont stockés ici, dans les profils Visual Studio Code :
Vous pouvez donc facilement éditer, modifier, échanger (regarder les options d’import/export) toutes les configurations afférentes.
Avec un peu d’habitude, vous pouvez ouvrir différentes instances pour différents usage.
https://www.gaia.fr/wp-content/uploads/2017/02/team1.png600600Nathanaël Bonnet/wp-content/uploads/2017/05/logogaia.pngNathanaël Bonnet2025-06-23 22:04:512025-06-23 22:04:52Visual Studio Code et Code for IBM i : profils
/wp-content/uploads/2017/05/logogaia.png00Habib Saad/wp-content/uploads/2017/05/logogaia.pngHabib Saad2025-06-17 09:56:552025-06-17 09:57:58Série IBM i et Sports de Combat : Le Jiu Jitsu Brésilien