IUT Bordeaux 1 - Département Informatique Semestre 4 JEE 2010–2011 TP JEE (1) Développement EJB - Prise en main Ce TP a pour but de prendre en main les concepts de la programmation JEE. Cette prise en main se fera par l’intermédiaire d’un exemple simple. Les EJB (Enterprise JavaBeans) 3.0 permettent de découpler la logique de présentation (site web, application riche, services web) de la logique métier (implémentation de services, interaction avec la base de données). En conséquence, la logique métier doit être exécutée dans un objet différent de celui qui gère l’affichage. De plus, ils autorisent la communication avec d’autres services répartis sur d’autres serveurs d’applications : mécanisme de communication comme JNDI (Java Naming and Directory Interface). Dans tous les cas, il est nécessaire d’avoir un conteneur d’EJB. C’est le rôle du serveur d’applications. Dans ce TP, nous utiliserons JBoss (projet opensource). Il y a deux sortes d’EJB : – EJB sessions : il s’agit d’objets qui rendent un service et qui permettent d’assurer une transaction. – EJB Entity : il s’agit d’objets qui correspondent à des enregistrements d’une base de données et qui gèrent l’accès à la base de données. 1 Développement de l’EJB Entity : "Etudiant" 1.1 Conteneur JBoss et Eclipse 1. Lancer Eclipse et ouvrir les préférences : Window/Preferences/Server/Runtime Environments puis cliquer sur Add. 2. Dans la liste proposée, sélectionner le type JBoss v4.2, puis la configuration défaut pour JBoss. Pour la JRE, nous utiliserons la version par défaut. 3. Sélectionner le répertoire de localisation de JBoss : C ://JBoss.4.x.GA. 1.2 Création du projet EJB et l’EJB Entity Afin de simplifier le partage des tâches dans le cadre du développement d’un projet, chaque couche est identifiée par un package. Par exemple, le package etudiant.beans contiendra les beans du projet et etudiant.services contiendra les services. 1. Créer un nouveau projet EJB du nom de votre choix (ex. : EtudiantEJB). 1 Attention à bien sélectionner la version 3.0 du module EJB (ne pas sélectionner "Generate Deployment Descriptor"). 2. Ajouter une nouvelle classe (Bean) nommée "Etudiant" dans le package correspondant. 3. Compléter cette classe avec les attributs et méthodes nécessaires. 4. Ajouter les annotations Java permettant de "transformer" cette classe en tant qu’entité (cf. Fig. 1) : on annotera la classe Entity (@Entity) et on indiquera son attribut clé (@Id ). L’annotation @Table indique le nom de la table qui stockera cette entité. [...] @Entity @Table ( name = " Etudiant " ) p u b l i c c l a s s Etudiant implements Serializable{ @Id p r i v a t e i n t id ; } Figure 1 – Exemple d’un EJB Entité. 2 Développement de l’EJB Session : ServiceEtudiants Dans un souci de maintenir la cohérence des objets manipulés, la conception de projets JEE exige de ne pas exposer directement les EJB Entité aux clients. Pour gérer et assurer la cohérence des données, nous utilisons le modèle de conception (design pattern) Façade, qui a pour but d’exposer des services aux clients par l’intermédiaire d’une interface distante pour la manipulation de beans. Ici nous allons créer cette interface (ex. : ServiceEtudiants) puis la classe qui l’implémente. L’interface définit les méthodes à exposer aux clients. Nous maintiendrons ici une liste d’étudiants à l’aide d’une ArrayList par exemple. 2.1 Création de l’interface du bean 1. Ajouter une nouvelle interface au projet nommée ServiceEtudiants (package etudiants.services). 2. Compléter l’interface avec les méthodes nécessaires. 3. Ajouter les annotations Java permettant au conteneur JBoss de comprendre qu’il s’agisse d’une interface distante EJB : @Remote pour spécifier au conteneur d’EJB qu’il s’agisse d’une interface distante d’EJB (cf. Fig. 2). 2 [...] @Remote p u b l i c i n t e r f a c e ServiceEtudiant { p u b l i c s t a t i c String JNDI = " S e r v i c e E t u d i a n t I m p l / remote " ; p u b l i c v o i d add ( Etudiant e ) ; [...] } Figure 2 – Exemple d’un EJB Session. 2.2 Implémentation de l’interface du bean 1. Ajouter une nouvelle classe implémentant l’interface précédente. 2. Ajouter les annotations nécessaires ; c’est notamment dans cette classe que le choix est fait entre un service dit "sans état" (@Stateless) et "avec état" (@Stateful ). [...] @Stateless @Remote ( ServiceEtudiant . c l a s s ) p u b l i c c l a s s ServiceEtudiantImpl implements ServiceEtudiant{ [...] } Figure 3 – Exemple d’un EJB Session. 3 Déploiement du modele EJB au sein du serveur Très important, avant de commencer. Pour éviter des soucis lors de la publication dans le serveur JBoss, nettoyez le répertoire de déploiement du serveur. Plus précisement, dans le répertoire C :\jboss-4.0.4.GA\server\default\deploy, supprimez tous les fichiers *.ear et *.jar qui s’y trouvent et déplacez le fichier mailapplication.xml pour le temps du TP. 1. Dans Eclipse, choisir la vue "server" puis ajouter un serveur JBoss (clique droit). 2. Ajouter le projet au serveur créé. 3. Lancer le serveur. 4. Vérifier les erreurs de lancement et corriger les si besoin. 3 4 Développement du client 1. Créer un nouveau projet client Java "classique". 2. Ajouter une classe ClientEtudiants. 3. Sélectionner le répertoire src puis ajouter un fichier de nom jndi.properties contenant les lignes de la Figure 4. java . naming . factory . initial=org . jnp . interfaces . N a m i n g C o n t e x t F a c t o r y java . naming . factory . url . pkgs=org . jboss . naming : org . jnp . interfaces java . naming . provider . url=jnp : / / localhost : 1 0 9 9 Figure 4 – Fichier jndi.properties. 4. Ajouter une référence au projet EJB (EtudiantEJB) dans le build-path du client. 5. Ecrire le code du client (cf. Fig. 5). 6. Expliquer pourquoi l’annotation @Sateless n’est pas le bon choix. [...] p u b l i c c l a s s MonClient { p u b l i c s t a t i c v o i d main ( String [ ] args ) { try { Context context = new InitialContext ( ) ; ServiceEtudiant s = ( ServiceEtudiant ) context . lookup ( ServiceEtudiant . JNDI ) ; s . add ( " t o t o " , " t i t i " ) ; } c a t c h ( javax . naming . NamingException ne ) { ne . printStackTrace ( ) ; } } } Figure 5 – Exemple d’un accès client. 5 Utilisation d’une base de donnée Plutôt que de maintenir une liste d’étudiants par l’intermédiaire d’une simple liste, nous allons apprendre a manipuler une base de données à travers des EJB Session. 4 Lors du déploiement, le serveur d’application groupe les EJB Entité dans des unités de persistance. Chaque unité de persistance doit être associée à une source de données. L’EntityManager est le service qui permet de gérer ces unités. Le fichier persistence.xml est le descripteur de déploiement qui contient la configuration de l’EntityManager. A l’instar de PHPMyAdmin pour MySQL, JBoss intègre un outil graphique permettant d’accéder aux bases de données. Pour y accéder, il suffit de se rendre sur la console d’administration de JBoss via l’url : http ://localhost :8080/jmx-console, dans la section nommée jboss , cliquer sur database=localDB,service=Hypersonic. Dans la page qui s’affiche, cliquer sur le bouton Invoke qui se trouve sous la signature de méthode void startDatabaseManager(). L’outil HSQL Database Manager est alors lancé. 1. Créer un nouveau fichier dans le répertoire META-INF nommé persistence.xml. <p e r s i s t e n c e> <p e r s i s t e n c e −u n i t name="MyEntity "> <j t a −data−s o u r c e>java: / DefaultDS</ j t a −data− s o u r c e> <p r o p e r t i e s> <p r o p e r t y name=" h i b e r n a t e . hbm2ddl . auto " v a l u e=" update " /> </ p r o p e r t i e s> </ p e r s i s t e n c e −u n i t> </ p e r s i s t e n c e> Figure 6 – Fichier persistence.xml du dossier META-INF. 2. Modifier la classe ServiceEtudiantImpl pour qu’elle utilise une instance d’un objet EntityManager qui se chargera d’interagir avec la base de données (cf. Fig. 7). [...] @Stateless public class ServiceEtudiantsImpl implements ServiceEtudiants { @PersistenceContext ( name="MyEntity " ) private EntityManager em ; public boolean ajouter ( Etudiant e ) { em . persist ( e ) ; } [...] Figure 7 – Exemple de modification de la classe d’implémentation du service. 5 3. Tester avec le client. 6 Diagnostiques Si lors du lancement de JBoss, le port "1099" sur lequel se bind JBoss est déjà alloué. Il est impossible de couper le serveur JBoss pour le relancer. Solution : détruire le processus de nom javaw.exe. L’affichage "error port 8080 already in use" correspond à l’exécution une seconde fois du serveur JBoss et plus précisément le container web Tomcat qui tourne sur le port 8080. Solution : pour exécuter le client, Run As − > Run as Java Application. 6