Recherche sur le blog

vendredi 2 décembre 2011

[Java] Différentes possibilités avec l'AS/400

Les librairies Java fournies par IBM contiennent de nombreuses classes qui permettent de se connecter au système i, d'appeler des programmes CL ou RPG-LE, ou qui autorisent l'accès à la base de données DB2. Il existe même deux méthodes pour lancer un programme : l'utilisation du langage PCML (respectant un schéma XML) qui va rendre possible la conversion automatique des données, ou la méthode plus complexe qui consiste à d'abord convertir toutes les données dans le format AS/400 puis de les envoyer sous forme de bytes, ce qui est tout de suite plus fastidieux. Nous allons voir ensemble, dans cet article, les méthodes de connexion ainsi que le langage PCML.

Se connecter pour exécuter des commandes

Lorsque l'on veut exécuter des commandes ou appeler un programme sur l'AS/400, nous devons nous connecter au système. Nous allons avoir besoin du package suivant et de toutes ses classes : com.ibm.as400.access. Pour l'ajouter, une ligne de code suffit.
import com.ibm.as400.access.*;
La suite est on ne peut plus simple : on déclare une variable de type AS400 avec le nom que l'on souhaite. On doit ensuite l'initialiser avec l'un des constructeurs en lui passant certains paramètres. Dans le cas ici présent, on renseigne, dans l'ordre, l'adresse du serveur, le nom d'utilisateur et le mot de passe.
AS400 mySystem = null;
mySystem = new AS400(server, user, password);
Si aucune erreur n'est renvoyée (n'oubliez pas de tester les exceptions !), on peut commencer à exécuter des commandes ou à appeler des programmes. Plus de détails sur les différents constructeurs : AS400 Class Javadoc (v5r1).

Exécuter une commande

Puisqu'on a importé le package et toutes ses classes grâce à l'instruction "import" ci-dessus, il n'y a plus qu'à déclarer une variable de type CommandCall, qui permettra l'appel d'une commande interne. Par exemple, on souhaiterait changer les librairies utilisées par le job en cours (qui a été créé lors de la connexion). Voici un exemple de code qui effectue la déclaration de la variable mais aussi l'appel de la commande :
CommandCall cc;
cc = new CommandCall(mySystem);
cc.run("CHGLIBL LIBL(" + sMyLibraries + ")");
Ajoutez à cela le traitement des messages renvoyés par le système pour afficher les éventuelles erreurs. Sur le support d'IBM, vous trouverez un exemple concret. Voici également la documentation de la classe CommandCall (v5r2), qui vous permettra d'obtenir des informations supplémentaires sur les instructions utilisées.

Se déconnecter de tous les services

Pour mettre fin au job en cours et arrêter toutes les commandes en cours pour celui-ci, on va se déconnecter proprement du système. En effet, ne pas couper la connexion peut laisser plusieurs jobs en suspend jusqu'à saturation, ce qui rendra impossible de futures connexions. La fonction utilisée est "disconnectAllServices()"de l'objet AS400.
mySystem.disconnectAllServices();
Il est également possible de déconnecter un seul service à la fois avec la fonction "disconnectService". On spécifie en paramètre le numéro du service à arrêter (ex : PRINT, FILE, COMMAND,...).

ProgramCall Markup Language

Le langage PCML est un langage spécifique défini par IBM qui permet de décrire les programmes sur l'AS/400 (RPG-LE ou CL) et peut être utilisé dans un programme Java ou même avec Easycom for WinDev. Le document PCML est écrit avec des éléments de type XML qui respectent un certain schéma. Il va permettre d'établir les conversions de données et le passage de paramètres aux programmes du système. La documentation IBM vous donnera plus de détails sur ce langage et sur sa syntaxe: "Building iSeries program calls with PCML".

Comment obtenir ce fichier

Pour créer le fichier PCML il vous suffit, lors de la compilation, de renseigner deux paramètres supplémentaires : PGMINFO, qui prendra la valeur *PCML, et INFOSTMF qui est le chemin du fichier à générer dans l'IFS (exemple : /home/myprog.pcml). Si vous n'avez pas accès à l'IFS sous Windows, vous pouvez soit le configurer, soit copier le fichier via l'émulateur en copiant les lignes à l'écran (sélection puis copier). La compilation peut également être effectuée via une ligne de commande.

Le contenu 
     
Pour résumé, le fichier contient toutes les définitions des paramètres du programme à appeler, ainsi que la longueur. Si vous n'avez pas pu le générer, il est toujours possible de l'écrire sur base d'un existant. Pour chacun des paramètres, on peut définir le type (packed, char, zoned, etc), la longueur, la précision (pour les nombres uniquement), ainsi que l'utilisation (entrée, sortie, ou les deux). Voici un exemple de document qui décrit un programme appelé CALCC dans la librairie EMARADISP (cf. image).


Le code Java

Au préalable, il faut placer le document PCML dans le répertoire des classes de notre projet ou bien du serveur si le code s'exécute sur Apache Tomcat ou Glassfish. Ce répertoire doit être inclus dans le "classpath" du projet/du serveur. Ensuite, nous allons avoir besoin d'un objet de la classe ProgramCallDocument, que l'on déclare dans le code.On va la lier au système et définir les différents paramètres au moyen de fonction "set". On récupérera les paramètres de retour avec des fonctions de type "get". Voici un code d'exemple.
ProgramCallDocument pcml = null;
pcml = new ProgramCallDocument(mySystem, "PROGRAM");
pcml.setValue("PROGRAM.PARM1", s);
pcml.setValue("PROGRAM.PARM2", new Integer(5));
pcml.setValue("PROGRAM.PARM3", new Integer(0));

// ...

if (pcml.callProgram("PROGRAM") != true)
{
	// handle error.
}
else
{
	variable = pcml.getValue("PROGRAM.PARM3") + "#";
}
Explications :
  • On a déclaré une variable de type ProgramCallDocument et on l'a liée au système. On a également indiqué le nom du programme, qui est en fait lié à l'élément <program> dans notre document PCML.
  • On a utilisé plusieurs fois la fonction "setValue" pour définir les différents paramètres. Pour chacun, il a été obligé de spécifier le nom du programme ainsi que le nom du paramètre, pour faire référence aux différents éléments du document.
  • On appelle la fonction "callProgram" de l'objet ProgramCallDocument en spécifiant à nouveau le nom du programme à appeler. La fonction renvoie vrai ou faux pour indiquer si tout s'est bien passé.
Pour plus de détails sur la classe et ses fonctions, vous êtes invité à consulter la documentation Java officielle qui se trouve ici : ProgramCallDocument Class Javadoc. Comme pour tous les autres liens, c'est en anglais uniquement.

Se connecter à la base de données

Cette opération est réalisée grâce au pilote JDBC fourni par IBM. La méthode de connexion avait déjà été décrite dans un article sur ce blog : "Se connecter à un système AS/400". Cependant, des propriétés supplémentaires ont été définies dans une variable de type Properties, pour redéfinir notamment la library list (sorte de "path" sur l'AS/400) et le système de convention pour SQL. Le nom d'utilisateur et le mot de passe y sont également stockés.
p.put("user",mainProp.get("user").toString());
p.put("password",mainProp.get("pwd").toString());
p.put("naming", "system");
p.put("libraries", slib);    
DriverManager.registerDriver(
   new com.ibm.as400.access.AS400JDBCDriver()
);

conn = DriverManager.getConnection(
   "jdbc:as400://" + server, p
);
Choisir d'utiliser le système de convention interne à l'AS/400 permet d'exécuter des requêtes en indiquant le nom de la bibliothèque suivi du nom de la table. Par défaut, le driver JDBC est configuré pour utiliser l'appel standard "schéma.table". Grâce aux propriétés, on a donc modifié le comportement du pilote.

Et après ?
 
Vous voilà maintenant prêts pour générer un web service qui se connecte à l'AS/400, ou même un simple programme. L'avantage d'utiliser Java ? Il sera multiplateforme puisque la machine virtuelle peut s'installer sur tous les systèmes d'exploitation du marché (Linux, Windows, Mac OS X). Dans la dernière partie de ce dossier, vous apprendrez à appeler votre web service fraichement développé. Revenez donc dans quelques jours pour la suite... et la fin ! Bon développement à toutes et à tous.


Quelques liens :

4 commentaires:

Anonyme a dit…

Soit une programme RPGILE avec en entête

H PGMINFO(*PCML)

compilation

CRTBNDRPG PGM(Mabib/Mopgm) SRCFILE(Mabib/QRPGLESRC) SRCMBR(Mopgm) OPTION(*EVENTF) DBGVIEW(*SOURCE) INDENT(*NONE) LANGID(*JOBRUN) REPLACE(*YES) TGTRLS(*CURRENT) ENBPFRCOL(*FULL) PGMINFO(*PCML *STMF) INFOSTMF('\home\toto')


résultat de la compilation

*RNF1353: Le nombre de paramètres indiqués pour le mot clé PGMINFO est insuffisant.

et pas d'infos sur la doc d'IBM quand a d'autre paramètre dans
PGMINFO(*PCML)

Anonyme a dit…

H PGMINFO(*PCML:*MODULE)
divers doc sur v6r1 : laisse entendre que ce paramètre évolue.

Ceci étant même en modifiant :
INFOSTMF('/TEST/FNC_D1.pcml') pour corrigé le problème d'adresse IFS, le compilateur renvoi

RNF0320: Des erreurs ont été détectées pendant la génération des informations programme à placer dans le module.
RNS9308: Arrêt de la compilation. Erreurs de gravité 30 détectées dans le programme.

il créer néanmoins la partie PCLM

Anonyme a dit…

Je répond moi même a mon problème:
Tous les type de données ne peuvent être utiliser dans le cas des échanges effectué :
notamment

D DateS S D DATFMT(*EUR)

C *ENTRY PLIST
C PARM DateN
C PARM DateS

L'utilisation du type date comme paramètre pose problème et généré une erreur.













En fait ,le compilateur transforme ce type date en type char(10).

Vincent a dit…

Merci pour l'information, ça peut être utile pour beaucoup de personnes.