Looking for Computer Science & Information Technology online
courses ?
Check my new web site: https://www.yesik.it !
JNDI [1] est un service d'annuaire qui permet à un composant d'accéder à des objets gérés par son serveur d'application. Dans ce tutoriel, nous allons voir comment enregistrer un pilote de base de données auprès de JNDI pour le rendre accessible aux différentes applications hébergées par JBoss AS.
Objectifs | A la fin de ce tutoriel, vous saurez:
|
---|---|
Prérequis |
|
Moyens |
Préparation
Avant de commencer, nous allons créer une base de données "de test" dans MySQL:
CREATE DATABASE JNDITest; USE JNDITest; CREATE TABLE Dance (name VARCHAR(30) PRIMARY KEY NOT NULL); INSERT INTO Dance VALUES ("Hip-Hop"), ("Krump"), ("Jazz"), ("Street"), ("Belly Dancing"), ("Tribal Fusion") ;
Il est fortement déconseillé de laisser des applications accéder à un SGBD avec les autorisations super-utilisateur. Par conséquent nous allons ajouter un nouvel utilisateur, et lui donner toutes les permissions sur les tables de la base que nous venons de créer:
GRANT ALL PRIVILEGES ON JNDITest.* TO jbosstest@localhost IDENTIFIED BY 'secret-password' ;
Vous pouvez tester que la création de la base de données et de l'utilisateur associé ont bien fonctionné en utilisant la commande suivante à partir du shell:
sh$ echo 'SELECT * FROM Dance' | mysql -u jbosstest -psecret-password -D JNDITest name Belly Dancing Hip-Hop Jazz Krump Street Tribal Fusion
Enregistrer le driver
Tout d'abord, il faut rendre le driver pour votre SGBD accessible à JBoss. Pour ce faire, copier simplement le pilote JDBC dans le répertoire server/default/lib de votre installation de JBoss AS:
sh$ cp /path/to/mysql-connector-java-5.0.7-bin.jar $JBOSS_HOME/server/default/lib
Maintenant que JBoss peut accéder au driver, il faut l'enregistrer dans l'annuaire JNDI. A nouveau dans JBoss la procédure et assez simple, puisqu'il suffit de créer le fichier mysql-test-ds.xml puis de le copier dans le répertoire $JBOSS_HOME/server/default/deploy.

Remarque:
Le nom du fichier doit impérativement se terminer par -ds.xml pour être détecté par le système de déploiement automatique de JBoss.

Soyez bon avec JBoss
Procédez bien en deux temps:
- d'abord éditer le fichier,
- puis le recopier dans le répertoire de déploiement.
Si vous travaillez directement dans ce dernier, à chaque enregistrement vous forcez JBoss à redéployer le pilote de base de données!
<datasources> <local-tx-datasource> <jndi-name>MySQLTestDS</jndi-name> <connection-url>jdbc:mysql://localhost/JNDITest</connection-url> <driver-class>com.mysql.jdbc.Driver</driver-class> <user-name>jbosstest</user-name> <password>secret-password</password> </local-tx-datasource> </datasources>
Le contenu du fichier mysql-test-ds est assez facile à interpréter. C'est un fichier XML qui enregistre une nouvelle source de données (datasource) avec les caractéristiques suivantes:
- Nom dans l'annuaire JNDI: MySQLTestDS
- URL de la base de données associée: jdbc:mysql://localhost/JNDITest
- Classe du driver: com.mysql.jdbc.Driver
- Identifiant de l'utilisateur de la base de données: jbosstest
- Mot de passe associé: secret-password
Une fois votre fichier édité, vous pouvez le copier dans le répertoire de déploiement de JBoss:
sh$ cp /path/to/mysql-test-ds.xml $JBOSS_HOME/server/default/deploy
Si tout se passe bien, vous devriez voir apparaître la ligne suivante dans le journal de JBoss:
10:53:55,627 INFO [ConnectionFactoryBindingService] Bound ConnectionManager 'jboss.jca:service=DataSourceBinding,name=MySQLTestDS' to JNDI name 'java:MySQLTestDS'
Maintenant, tout ce qu'à besoin de connaître une application hébergée par JBoss AS pour accéder à votre base de données, c'est son nom JNDI java:MySQLTestDS.
Tester
Pour tester, nous allons écrire une petite servlet. Celle-ci va se connecter à la base de données et renvoyer le contenu de la table Dance.
package fr.esicom.demo; import java.io.*; import javax.sql.*; import java.sql.*; import javax.naming.InitialContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class for Servlet: JNDITestServlet * */ public class JNDITestServlet extends javax.servlet.http.HttpServlet { /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#HttpServlet() */ public JNDITestServlet() { super(); } /* (non-Java-doc) * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType("text/plain"); PrintWriter os = new PrintWriter(response.getOutputStream()); Connection conn = null; Statement stmt = null; ResultSet rs = null; try { /* * Recherche de la source de données * dans l'annuaire JNDI */ InitialContext ctx = new InitialContext(); DataSource ds = (DataSource) ctx.lookup("java:MySQLTestDS"); /* * Requête JDBC */ conn = ds.getConnection(); stmt = conn.createStatement(); rs = stmt.executeQuery("SELECT name FROM Dance"); /* * Génère le réponse * (HTTP/200 OK) */ response.setStatus(200); os.println("Esicom Dance Skool"); while(rs.next()) { String danceName = rs.getString("name"); os.println("- "+danceName); } } catch (Exception e) { /* * Rapporte l'erreur détectée * (HTTP/500 Internal Server Error) */ response.setStatus(500); os.println(e.toString()); } finally { /* * Dans tous les cas, libérer les ressources */ os.close(); try { rs.close(); } catch(Exception ignored) {} try { stmt.close(); } catch(Exception ignored) {} try { conn.close(); } catch(Exception ignored) {} } } }
La seule différence entre le code ci-dessus et celui d'une servlet qui accède directement au driver de la base de données se trouve dans les lignes:
/* ... */ InitialContext ctx = new InitialContext(); DataSource ds = (DataSource) ctx.lookup("java:MySQLTestDS"); /* ... */
L'objet ctx représente le contexte initial dans lequel s'exécute la servlet. C'est au travers de cet objet qu'il est possible d'interroger JNDI. L'appel à la méthode ctx.lookup fait effectivement l'interrogation de l'annuaire, et recherche l'objet enregistré sous le nom java:MySQLTestDS.

Remarque:
Comme l'annuaire peut stocker n'importe quel type d'objet, la méthode lookup renvoie une référence sur un Object.
Avant de pouvoir manipuler la référence renvoyée, il est donc nécessaire de convertir celle-ci en une référence vers une instance du type réel de l'objet (ici DataSource). C'est à ça que sert la coercission (DataSource).
Une fois la Servlet compilée et déployée, vous pouvez la tester à l'aide d'un client http (navigateur ou autre). Ici, nous testerons avec curl, afin de pouvoir visualiser également l'en-tête http renvoyé:
sh$ curl -D - 'http://localhost:8080/JNDITest/JNDITestServlet' HTTP/1.1 200 OK Server: Apache-Coyote/1.1 X-Powered-By: Servlet 2.4; JBoss-4.2.1.GA (build: SVNTag=JBoss_4_2_1_GA date=200707131605)/Tomcat-5.5 Content-Type: text/plain Content-Length: 90 Date: Tue, 08 Jan 2008 10:49:37 GMT Esicom Dance Skool - Belly Dancing - Hip-Hop - Jazz - Krump - Street - Tribal Fusion
A vous de jouer
Vous pouvez essayer de manipuler un peu cette Servlet pour tester comment elle réagit:
- En cas de recherche d'une ressource inexistante dans l'annuaire JNDI,
- ou en cas d'erreur dans la requête SQL,
- ou encore si le serveur de base de données est arrêté.
Normalement, dans tous les cas, vous devriez obtenir une réponse http 500 Internal Server Error.