Le site francophone consacré au projet Eclipse et à OSGi
 
 

 

 

(publié le 16/03/2007 - Versions utilisées : Eclipse 3.2.1 - WTP 1.5.2 - JBoss 4.0.5 - JDK 5.0)

 

Tutorial : développer des EJB 3 avec Eclipse et JBoss


La spécification EJB 3 dispose d'atouts indéniables pour redorer le blason des EJB. D'une part elle simplifie le processus de développement en allégeant le code, d'autre part les lacunes des EJB Entity sont largement comblées par une nouvelle spécification qui traite spécialement du problème de la persistance : JPA (Java Persistence API).

Ce tutorial à pour but de détailler les étapes de mise en place d'un environnement technique (Eclipse et JBoss) permettant de découvrir le développement d'EJB 3.

 

Sommaire


 

 

Mise en place

Pour ce tutorial, la mise en place consiste en l'installation d'un JDK, d'Eclipse Web Tools et de JBoss.
La procédure d'installation de WTP est décrite dans notre tutorial 'Développement de Servlets et JSP avec Eclipse WTP'.

 


Installation de JBoss avec le support des EJB 3

Pour pouvoir développer et tester des EJB 3 il faut naturellement disposer d'un serveur intégrant le support de cette nouvelle version de la spécification EJB. JBoss 4.0.5 répond à ce besoin.
Le téléchargement de base (fichier zip) de JBoss 4.0.5 n'intègre pas le conteneur EJB 3. Pour installer JBoss avec le support des EJB 3, il faut utiliser l'installeur graphique : télécharger ce fichier contenant JBoss 4.0.5 et son installeur graphique.

Une fois téléchargé, exécuter l'installeur en double-cliquant sur le fichier (si les fichiers JAR ne sont pas associés à Java, l'exécution de l'installeur peut se faire en utilisant la ligne de commande suivante : java -jar ems-installer-1.2.0.CR1.jar ).

Suivre les étapes de l'installeur, après avoir indiqué l'emplacement il faut choisir un type d'installation : sélectionner 'ejb3' :

 

Dans les pages suivantes de l'installeur, conserver les valeurs par défaut, excepté pour la page 'JMX Security'. Dans cette page décocher toutes les cases et saisir un mot de passe pour la console d'administration ('admin' pour faire simple) :

(PS: décocher ces cases permet d'éviter des problèmes lors de l'arrêt du serveur JBoss à partir de la vue 'Serveurs' de WTP).

 


Déclaration du serveur JBoss dans WTP

Pour associer le serveur JBoss à WTP nous allons procéder de la même façon que pour le serveur Tomcat (cf notre tutorial 'Développement de Servlets et JSP avec Eclipse WTP') :

- Ouvrir la page de préférences Préférences->Serveur->Environnements d'exécution installés.
- Dans la liste proposée par le bouton 'Ajouter...', sélectionner le type de serveur 'JBoss v4.0'.
- Dans la page suivante de l'assistant, indiquer l'emplacement du serveur JBoss.

- Ouvrir la perspective J2EE et sélectionner la vue 'Serveurs'.
- Utiliser le menu contextuel : 'Création->Serveur'.
- Vérifier que le type de serveur sélectionné est 'JBoss v4.0' et cliquer sur 'Terminer' pour demander la création du serveur.

Une fois ces étapes de configuration effectuées, tester le bon fonctionnement du serveur en demandant son exécution à partir de la vue 'Serveurs'.

 

 


Développement d'EJB 3



Création et configuration d'un projet

WTP 1.5 cible J2EE 1.4, les assistants ne prennent donc pas en compte les particularités des EJB 3. C'est le cas notamment de l'assistant de création de projet EJB qui cible les EJB2.
L'utilisation d'un projet de type EJB présente tout de même un intérêt : la vue 'Serveurs' gère la publication des projets de type EJB vers le serveur de test.


Utiliser le menu contextuel de la vue 'Explorateur de projets' pour créer un projet EJB :


Dans la première page de l'assistant indiquer le nom du projet et sélectionner 'JBoss v4.0' comme 'environnement d'exécution cible'. L'association du projet à un EAR n'est pas nécessaire, il est donc inutile de cocher la case correspondante. Les autres pages de l'assistant ne nécessitent pas de modification, cliquer sur le bouton 'Terminer'.

 

Une fois le projet créé, supprimer le répertoire META-INF pour éviter que WTP affiche des erreurs liées à la validation du fichier ejb-jar.xml. Le fichier 'META-INF/ejb-jar.xml' est optionnel pour le développement des EJB 3, les informations qui apparaissaient dans ce fichier peuvent maintenant être placées directement dans le code en utilisant le mécanisme d'annotations du JDK 5.0.


Le chemin de compilation du projet doit être complété avec l'ajout des fichiers jar permettant l'utilisation de l'API EJB3. Dans la section 'Chemin de génération Java' de la page de propriétés du projet, sélectionner l'onglet 'Bibliothèques', et utiliser le bouton 'Ajouter des fichiers JAR externes...' pour ajouter les 3 fichiers JAR nécessaires :

(NB: pour éviter de reproduire cette opération à la création de chaque projet, il est possible d'utiliser la notion de 'bibliothèque utilisateur' en passant par le bouton 'Ajouter une bibliothèque').

 

 


Développement d'un EJB Session

La création d'un EJB Session est largement simplifiée par la spécification EJB 3 : il n'y a pas de contrainte d'héritage et aucune méthode particulière à implémenter.
Le développement d'un EJB 3 Session se fait en trois étapes.


Définition de l'interface du composant. Créer une interface contenant le code suivant :

package com.et;

public interface PremierEJB3 {
   public String ditBonjour(String aQui);
}


Implémentation du composant. Créer cette classe :

package com.et;

public class PremierEJB3Bean implements PremierEJB3 {
   public String ditBonjour(String aQui) {
      return "Bonjour " + aQui + " !!!";
   }
}


Ajout des annotations EJB 3 :

Ajouter les annotations nécessaires (@Remote et @Stateless). L'éditeur d'Eclipse 3.2 gère complètement la notion d'annotations du JDK 5.0, la complétion (Ctrl+espace) fonctionne pour les annotations et permet d'ajouter simplement la directive 'import' nécessaire :


Code de l'interface après l'ajout de l'annotation @Remote :

package com.et;

import javax.ejb.Remote;

@Remote
public interface PremierEJB3 {
   public String ditBonjour(String aQui);
}


Code de la classe après l'ajout de l'annotation @Stateless :

package com.et;

import javax.ejb.Stateless;

@Stateless
public class PremierEJB3Bean implements PremierEJB3 {
   public String ditBonjour(String aQui) {
      return "Bonjour " + aQui + " !!!";
   }
}

 


Tester l'EJB Session

Le code de notre EJB étant écrit, nous pouvons le tester. Pour ce faire, il faut d'une part déployer le projet EJB dans le serveur JBoss et d'autre part écrire une application cliente.


Déployer le projet EJB.

A partir de la vue 'Serveurs', sélectionner le serveur JBoss et utiliser l'option 'Ajouter et supprimer des projets...' du menu contextuel pour déployer le projet EJB :

Démarrer le serveur JBoss (en mode déboguage de préférence) pour voir si le projet est bien pris en compte.
Si l'EJB est correctement déployé les lignes suivantes doivent apparaître dans la console :

22:14:06,312 INFO [Ejb3Deployment] EJB3 deployment time took: 312
22:14:06,453 INFO [JmxKernelAbstraction] installing MBean: jboss.j2ee:jar=IntroEJB3.jar,name=PremierEJB3Bean,service=EJB3 with dependencies:
22:14:06,906 INFO [EJBContainer] STARTED EJB: com.et.PremierEJB3Bean ejbName: PremierEJB3Bean
22:14:07,078 INFO [EJB3Deployer] Deployed: file:/C:/Produits/jboss-4.0.5.GA/server/default/deploy/IntroEJB3.jar

 

Créer une application de test .

Créer un projet Java et configurer son 'Chemin de génération Java' :

- Dans l'onglet 'Projets' ajouter le projet contenant les EJB :

- Dans l'onglet 'Bibliothèques' ajouter les JAR nécessaires à l'application cliente :

 

A la racine du projet créer un fichier nommé jndi.properties contenant les informations qui permetteront à l'application cliente de se connecter au service de nommage du serveur JBoss :

java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=localhost:1099

 

Créer la classe de test suivante pour invoquer l'EJB précédemment créé :

package com.et;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class ClientPremierEJB3 {

   public static void main(String[] args) {
      try {
         Context context = new InitialContext();
         PremierEJB3 beanRemote = (PremierEJB3)
         context.lookup("PremierEJB3Bean/remote");
         System.out.println(beanRemote.ditBonjour("ClientPremierEJB3"));
      } catch (NamingException e) {
         e.printStackTrace();
      }
   }
}

 

(Pour l'exécution : sélectionner la classe dans la vue 'Explorateur de projets' et utiliser le menu 'Exécuter->Exécuter en tant que->Application Java').

 

 


Développement d'un EJB Entity

La spécification EJB 3 revoit très largement le développement des Entity Beans. Les EJB Entity sont décrits dans une spécification complémentaire nommée JPA (Java Persistence API) dont les principaux apports sont :

- Simplification du code via l'utilisation de l'approche 'POJO' (Plain Old Java Object) : un EJB Entity consiste en une classe Java standard (pas de contrainte d'héritage, pas de méthode particulière à implémenter).

- Fonctionnalités de mapping objet-relationnel plus riches : par exemple dans les versions précédentes le format de définition de la correspondance entre les objets et les structures de données relationnelles (le mapping objet-relationnel) n'était pas standardisée. La spécification JPA propose d'utiliser les annotations pour définir le mapping. Des problématiques comme l'héritage ou l'optimisation via l'utilisation de requêtes SQL sont prises en compte. De façon générale, JPA aborde de façon complète et pragmatique le problème de persistance alors que les spécifications EJB précédentes adoptaient une approche plutôt dogmatique et faisaient l'impasse sur des fonctionnalités essentielles permettant de mieux gérer le compromis entre transparence et optimisation.

- Utilisation possible en dehors d'un serveur d'applications J2EE : JPA peut être utilisée dans une application cliente, la présence d'un conteneur d'EJB n'est plus nécessaire. Des solutions intermédiaires sont aussi possibles : déploiement dans Tomcat d'une application à base de Servlets et JSP utilisant JPA.

 

Le développement d'un EJB Entity est relativement simple. Ajouter la classe suivante au projet précédemment créé :

package com.et;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Produit implements Serializable {

   @Id
   private String id;
   private String libelle;
   private int quantiteEnStock;

   public Produit() {
      super();
   }

   public Produit(String id) {
      this.id = id;
   }

   public Produit(String id, String libelle, int quantiteEnStock) {
      this.id = id;
      this.libelle = libelle;
      this.quantiteEnStock = quantiteEnStock;
   }

   public String getLibelle() {
      return libelle;
   }

   public void setLibelle(String libelle) {
      this.libelle = libelle;
   }

   public int getQuantiteEnStock() {
      return quantiteEnStock;
   }

   public void setQuantiteEnStock(int quantiteEnStock) {
      this.quantiteEnStock = quantiteEnStock;
   }

   public String getId() {
      return id;
   }

   public String toString() {
      return "Produit n°" + id + " - " + libelle + " - quantité disponible : " + quantiteEnStock;
   }

}

Seules les annotations @Entity et @Id distinguent cette classe d'une classe non persistente.

 

La spécification JPA propose des API pour gèrer le cycle de vie d'un objet persistant. Pour illustrer de façon simple ces APIs, nous allons créer un EJB Session. Dans le projet EJB créer l'interface et la classe suivante :

package com.et;

import java.util.List;
import javax.ejb.Remote;

@Remote
public interface GestionDeStock {
   public void ajouter(Produit produit);
   public Produit rechercherProduit(String id);
   public List<Produit> listerTousLesProduits();
}


package com.et;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@Stateless
public class GestionDeStockBean implements GestionDeStock {

   @PersistenceContext
   EntityManager em;

   public void ajouter(Produit produit) {
      em.persist(produit);
   }

   public Produit rechercherProduit(String id) {
      return em.find(Produit.class, id);
   }

   public List<Produit> listerTousLesProduits() {
      return em.createQuery("SELECT p FROM Produit p ORDER BY p.quantiteEnStock").getResultList();
   }

}

 

 

 


Tester l'EJB Entity

La spécification JPA standardise l'utilisation d'un fichier, nommé persistence.xml, qui permet de préciser des paramètres techniques liés au mapping objet-relationnel, par exemple le nom de la 'DataSource' à utiliser pour se connecter à la base de données.

Pour tester notre EJB entity, nous devons définir le fichier persistence.xml et préciser la DataSource que nous voulons utiliser. Pour simplifier la mise en oeuvre nous proposons d'utiliser la bases de données HSQLDB intégrée au serveur JBoss. Cette base de données est bien adaptée pour cette prise en main des EJB 3 : elle est démarrée automatiquement avec le serveur JBoss et une DataSource est déjà définie vers cette base. D'autre part, l'implémentation JPA de JBoss, qui se base sur Hibernate, est en mesure de créer automatiquement la structure relationnelle correspondant à notre EJB.

 

Dans le projet EJB, créer le sous-répertoire META-INF et y placer le fichier persistence.xml suivant :

<persistence>
   <persistence-unit name="IntroEJB3">
      <jta-data-source>java:/DefaultDS</jta-data-source>
      <properties>
         <property name="hibernate.hbm2ddl.auto" value="update"/>
      </properties>
   </persistence-unit>
</persistence>

(Le nom 'IntroEJB3' est purement arbitraire, le nom de la DataSource est celui défini par JBoss, la valeur 'update' de la propriété 'hibernate.hbm2ddl.auto' indique que nous souhaitons qu'Hibernate crée la structure de données automatiquement et la mette à jour si nécessaire).

 

Redémarrer le serveur JBoss (la création des tables ne se fait que lors du lancement). JBoss intègre un outil permettant de manipuler la base de données HSQLDB. Cet outil peut nous permettre de lister les tables, de consulter les données qui s'y trouvent ainsi que d'exécuter diverses requêtes SQL. Pour ouvrir cet outil : accéder à 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é (NB: cet outil est une application cliente, il ne s'affiche pas dans le navigateur). Vérifier la présence de la table 'PRODUIT' :

 

Créer l'application cliente suivante pour tester le fonctionnement des EJB :

package com.et;

import java.util.Iterator;
import java.util.List;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;

public class GestionDeStockClient {

   public static void main(String[] args) {
      try {
         Context context = new InitialContext();
         GestionDeStock stock = (GestionDeStock) context.lookup("GestionDeStockBean/remote");

         // Ne pas faire l'ajout plusieurs fois, commenter ces lignes après la première exécution.
         stock.ajouter(new Produit("001", "Tomate", 100));
         stock.ajouter(new Produit("002", "Pomme de terre", 5680));
         stock.ajouter(new Produit("003", "Orange", 23));
         stock.ajouter(new Produit("004", "Carotte", 115));
         stock.ajouter(new Produit("005", "Muscadet", 48));

         List<Produit> produits = stock.listerTousLesProduits();
         for (Iterator iter = produits.iterator(); iter.hasNext();) {
            Produit eachProduit = (Produit) iter.next();
            System.out.println(eachProduit);
         }

      } catch (NamingException e) {
         e.printStackTrace();
      }
   }
}

 

Vérifier avec l'outil 'HSQL Database Manager' que les données ont bien été insérées :

 

 


Conclusion

Ce tutorial a montré comment faire ses premiers pas avec les EJB 3 en utilisant Eclipse WTP et JBoss. Dans un futur article, nous étudierons le sous-projet Dali dont l'objectif est de fournir des outils pour le développement d'applications utilisant JPA.

 

 

 


 

 

 

 


 

 

(c) EclipseTotale - contact(arobase)eclipsetotale.com