Comme nous travaillons régulièrement sur le système AS/400 d’IBM, plus précisément sur une machine iSeries 520 en version V5R3 sur laquelle on retrouve une base de données SQL de type DB2 UDB, il m’est venu l’idée de tester les fameuses librairies (« IBM Toolbox for Java« ) fournies par IBM lui-même afin d’exécuter une simple requête de sélection pour interroger un fichier en particulier (ou une table, pour les puristes).
Voici donc une liste de pré-requis pour faire fonctionner le code qui va suivre:
- Posséder une machine AS/400 iSeries, mise en réseau bien entendu.
- Télécharger IBM Toolbox for Java. Pour ma part, j’ai pris la version estampillée « jtopen_7_3.zip« . Il faut ensuite décompresser ces libraires dans un endroit particulier.
- Avoir intégré les librairies via la configuration du projet (par exemple, si vous utilisez NetBeans, ce qui est mon cas, ou un autre IDE en particulier comme Eclipse).
Créer le projet
Comment créer le projet et importer les librairies?
Après avoir créé un nouveau projet avec NetBeans dans lequel on y intègre les archives « .jar » téléchargées (voir aperçu écran ci-dessus), il faut créer une nouvelle fenêtre de type JFrame.
On y insérera une table qu’on appellera simplement « jTableSt » et dont on va personnaliser le modèle avec une classe héritant de AbstractTableModel. On aura aussi besoin d’établir la connexion à l’AS/400. Toutes ces étapes vont être détaillées dans la suite.
Créer une table dynamique
Ici l’effet attendu est que la table ait un nombre de colonnes différent selon la requête exécutée. Pour cela il faut créer un nouveau modèle qui sera utilisé par la table (on pourra le définir dans le code de la fonction principale).
On l’appellera DynamicTableModel et il devra hériter de la classe AbstractTableModel, grâce au mot-clé « extends« .
public class DynamicTableModel extends AbstractTableModel
{
ArrayList cache;
int colCount;
String[] headers;
Connection db;
Statement statement;
// ...
}
- La variable cache contiendra les valeurs pour chacune des colonnes. On aurait pu utiliser une variable vecteur mais cela pose un problème de synchronisation et son utilisation est déconseillée (deprecated).
- L’entier sert à stocker le nombre de colonnes et pourra être renvoyé grâce à un getter.
- Le tableau de chaînes « headers » contiendra les titres des colonnes.
- Les deux dernières variables sont utilisées pour la connexion à la base de données et l’exécution de la requête. On initialisera ces variables grâce à un setter de la classe.
- Toutes les méthodes seront publiques.
Voici quelques méthodes de la classe, dont la méthode (execute) qui exécute la requête SQL sur la base de données. Dans celle-ci, on crée les titres des colonnes grâce aux métadonnées et ont crée les lignes avec toutes les valeurs. Ensuite, on signale à tous que la table a été modifiée (fire*), et on ferme les variables « ResultSet » et « Statement« .
Remarque : le setter qui initialise les variables pour la connexion n’a pas été repris car il est simple à écrire. Les fonctions qui doivent être implémentées sont décrites dans la documentation Java. A vous de découvrir ce qu’il faut indiquer…
public DynamicTableModel() {cache = new ArrayList();}
// ...
public void execute(String query)
{
cache = new ArrayList();
try
{
ResultSet rs = statement.executeQuery(query);
ResultSetMetaData meta = rs.getMetaData();
colCount = meta.getColumnCount();
headers = new String[colCount];
for (int h = 1; h <= colCount; h++)
{
headers[h - 1] = meta.getColumnName(h);
}
while (rs.next())
{
String[] rsRow = new String[colCount];
for (int i = 0; i < colCount; i++)
{
rsRow[i] = rs.getString(i + 1);
}
cache.add(rsRow);
}
fireTableChanged(null);
rs.close();
statement.close();
}
catch (Exception e)
{
cache = new ArrayList();
System.err.println(e.getMessage());
}
}
Créer la connexion
Connection conn;
DriverManager.registerDriver(
new com.ibm.as400.access.AS400JDBCDriver()
);
conn = DriverManager.getConnection(
"jdbc:as400://ip/LIB"
);
On va indiquer et enregistrer la classe du driver JDBC fournie par IBM afin de pouvoir récupérer un objet connexion. Les informations à donner lors de la connexion sont l’adresse IP de l’AS/400 (ou le nom de l’hôte) et la librairie dans laquelle on veut travailler.
On pourrait aussi spécifier les informations d’identification ou les librairies de la *LIBL dans une variable Properties, mais cela fera l’objet d’un nouvel article. Dans notre cas, une fenêtre apparaitra pour demander les informations de connexion de l’utilisateur, avant d’exécuter le reste du code.
Créer la table, exécuter la requête
DynamicTableModel qtm = new DynamicTableModel();
jTableSt.setModel(qtm);
qtm.setConnection(conn);
qtm.execute("select * from pegecl");
Dans la fonction ci-dessus, on crée une nouvelle instance du modèle précédemment écrit. Ensuite, on le définit pour la table grâce à la fonction setModel().
Ensuite, on utilise le setter du modèle pour définir la connexion utilisée et on appelle la fonction « execute » pour que la requête soit exécutée. La table sera alors générée, il ne reste plus qu’à fermer la connexion. Et voilà le résultat que nous avons obtenu après une ou deux secondes :
Alors, qui a dit que Java n’était pas adapté à tous les problèmes?
Bon développement.
Merci beaucoup, c'est ça ce que j'ai été entrain de chercher, je vais le tester 😉
Salut!
J'ai tester un simple code ci-dessous:
**************************************
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class Connexion {
public static void main(String[] args) throws SQLException{
Connection cn;
Statement st = null;
DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());
cn = DriverManager.getConnection("jdbc:as400://62.176.136.104");
st = cn.createStatement ();
ResultSet rs = st.executeQuery("select*from personne");
while(rs.next()){
System.out.println(rs.getInt(1)+" "+rs.getString(2));
}
cn.close();
}
}
******************************************
mais j'ai obtenu l'erreur suivant:
*****************************************
Usage: AAClientAccessDataStreamStress
Starting. replyStreams.size() = 1
java.lang.ArrayIndexOutOfBoundsException: 0
at com.ibm.as400.access.AAClientAccessDataStreamStress.main(AAClientAccessDataStreamStress.java:18)
***************************************
Aidez-moi svp!
– En renseignant une librairie pour la connexion ?
– En utilisant uniquement des getString() plutôt qu'un getInt() ?
Maintenant ça marche parfaitement,merci.
DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());
Cette commande ne veut pas passer
J'utilise éclipse
Opens the new class wizard to create the type.
la classe n'existe pas . Que ce soit avec jtopen_7_3.zip ou jtopen_7_6.zip
Je débute Java et donc ma connaissance sont bien plus lite que d'autre langage
J'ai le message suivant :
com.ibm.as400 ne peut être résolue en type:
Quelle est le soucis?
Pour que la classe soit trouvée, elle doit se trouver dans le classpath. Dans la configuration du projet sur Eclipse, on peut normalement ajouter des librairies au projet : il suffit de sélectionner les .JAR et ils sont intégrés.
L'autre méthode consiste à placer les librairies dans le dossier du JDK utilisé pour qu'elles soient accessibles lors du développement. Voici les répertoires où je les ai placées chez moi (cela peut varier d'une machine à l'autre) :
C:Program FilesJavajdk1.5.0_07lib
C:Program FilesJavajdk1.5.0_07jrelibext
J'utilise en effet le JDK 1.5 dans NetBeans, mais j'ai aussi intégré les JAR au projet.
Enfin, sur la machine où le code doit s'exécuter, ou sur le serveur, il faut placer les librairies dans le dossier du Java Runtime Environnement. Comme j'ai développé en JDK 1.5, je les ai placées dans le répertoire suivant (qui peut aussi varier).
C:Program FilesJavajre1.5.0_07libext
Pour l'erreur de type, il me faudrait plus de détails, comme le bout de code que vous avez écrit…
Plusieurs marqueurs sur cette ligne
– DriverManager ne peut pas être résolu
-com.ibm.as400.access.AS400JDBCDriver ne peut pas être résolu en type
Ce message est systématique quelque soit l'exemple utiliser.
il y a bien
import java.sql.*;
import com.ibm.*;
JTopen7.6 est installer dans le package eclipse.
Est-ce que les librairies sont dans le JRE de ton JDK ou dans le JRE de l'environnement d'exécution?
Peut-être que ceci est en rapport mais je ne suis pas sûr :
a.courreges.free.fr/blog/index.php/2007/12/28/11-the-type-javalangobject-cannot-be-resolved-avec-eclipse
Sinon divers topics en serchant sur Google peuvent peut-être aider ?
– philip.yurchuk.com/2008/12/03/eclipse-cannot-be-resolved-to-a-type-error/
– java.syntaxerrors.info/index.php?title=Cannot_resolve_type
– ubuntuforums.org/showthread.php?t=987259 (Ubuntu)
Etc.
Class.forName("com.ibm.as400.access.AS400JDBCDriver").newInstance();
DriverManager.registerDriver(new com.ibm.as400.access.AS400JDBCDriver());
Quelle différences y a t'il entre ces deux commandes?
Selon ce que j'ai lu ici :
publib.boulder.ibm.com/infocenter/iadthelp/v7r5/index.jsp?topic=/com.ibm.etools.iseries.toolbox.doc/jdbcdrvr.htm
Il semblerait que la première méthode soit la plus courante pour charger le driver. On dirait que la première instruction charge la classe et le pilote en même temps. Cependant, les deux instructions peuvent être utilisées sans problème et le résultat est le même…
en réponse au lancement:
SQLException: No suitable driver
SQLState: 08001
Bien que le fichier jar soit affecté dans les propriété du projet.
qu'il est aussi dans le projet!
– Le JAR est-il bien dans le répertoire "lib" du projet ? Sinon le créer et le référencer…
Eclipse – Classpath :
eclim.org/vim/java/classpath.html
Netbeans :
netbeans.org/kb/docs/java/project-setup.html
– Le JAR se trouve-t-il bien dans les classes supplémentaires du JDK et/ou du JRE, au cas où il tenterait de lancer la machine virtuelle par cet endroit ? (répertoires "ext" me semble-t-il).
– Quel est l'éditeur utilisé ?
Autres liens pouvant aider :
* eclipse.org/forums/index.php/t/263040/
* java.developpez.com/faq/java/?page=langage#LANGUAGE_CLASSPATH
Bonsoir, merci pour votre article. Je débute en java et il me serait util d'avoir le code entier à copier/coller pour bien comprendre. Pourquoi ne donner que des bouts de paragraphes ? Bien à vous.
Bonjour,
Voici le projet complet sous NetBeans : dl.dropbox.com/u/40510509/DynamicTableModel.zip
Si vous utilisez NetBeans, il faudra redéfinir les dépendances. Les librairies nécessaires sont fournies et sont déjà présentes dans le répertoire distlib. Il est possible de les réintégrer dans le projet…
Bonjour, Je fait référence à "J'ai tester un simple code ci-dessous".
J'ai utilisé cet exemple simple, avec les remarques.
La table/fichier utilisée à 3 champs tous de type Char
J'ai donc modifié la ligne affichant ceux-ci par:
System.out.println(rs.getString(1) + " " + rs.getString(2) +" " + rs.getString(3));
Le problème que je constate est sur la valeur retourner pour ce 3 ième champ ( l'application me renvoi "F6F8…" ) et la valeur originel pour les 2 premier.
7 juin 2012 11:32 :
Rectification : les 2 premiers champ sont de type char et le 3ième est un varchar.
Je n'ai pas très bien compris d’où venait le problème. Quel est le contenu de la table et surtout, que devait contenir le troisième champ en Varchar ?