dimanche 8 février 2009

Tutoriel developper des EJB3 remix





















Parti en expédition sur les terres du JEE, j'ai trouvé refuge dans le comté d'EJB3, comté certes séduisant en apparence, mais la simplicité faisant défaut a ses habitants j'ai décidé de faire un tutoriel largement inspiré de celui existant sur éclipse totale (http://www.eclipsetotale.com/articles/Introduction_EJB3_avec_Eclipse.html). Étant rebelle, je n'utiliserais pas Eclipse mais Netbeans, et j'utiliserais Glassfish en lieu et place de JBoss.
Pourquoi ces choix ? Tout d'abord pourquoi Glassfish ? Parce que ce serveur d'application JEE est léger il prend moins de 100 MO à vide contrairement à JBoss qui prend plus de 300 MO à vide, Parce que Glassfish est certifié JEE 5 et pas JBoss. Glassfish est certes peu connu (contrairement à JBoss) mais il est quand même conçu par Sun ce qui lui apporte une certaine crédibilité, il aurait d'ailleurs déposé Weblogic et Websphere dans le benchmark SPECjAppServer. Pourquoi Netbeans ? Là je dois avouer que c'est plus subjectif, les deux environnement se valent, Eclipse est plus réactif (grâce à SWT ?) et dispose de bien plus de plugins, il a de plus résolu ses problèmes de stabilité, Netbeans lui n'a pas beaucoup évolué et n'as pas vraiment comblé ses lacunes par rapport à Eclipse, mais son plugin pour Glassfish semble mieux fonctionner que celui d' Eclipse. J'ai eu l'occasion d'essayer JDevelopper d' Oracle, c'est de loin l' EDI le plus réussi esthétiquement parlant, mais la stabilité du logiciel est déplorable, elle est digne d'une version alpha. Bref, trêve de tergiversations, passons au tutoriel. La version de Netbeans utilisée ici est la 6.5, la version de Glassfish est la version 2.1 et la versions du JDK utilisé est la 6 update 11.

Créez un nouveau projet Java EE de type EJB Module dans Netbeans, ce projet est intitulé IntroEJB3, la version de JEE utilisé sera la 5 et le serveur utilisé sera bien évidement Glassfish V2.
Créez un package «com.et».Dans l'onglet « projects » faites un clic droit sur « Entreprise beans » cliquez sur « Session Bean » vous appellerez ce bean « PremierEJB3 » ce bean est de type « stateless » son interface est de type « remote » (décochez la case « Local »), ce bean sera dans le package «com.et». Deux fichier sont créés : « PremierEJB3Remote.java» et « PremierEJB3Bean.java», le premier correspond a l'interface « remote » du bean le second correspond à la classe d'implémentation du bean. Ouvrez le fichier « PremierEJB3Bean.java » faites un clic droit à l'interieur, cliquez sur « insert code » puis sur « add business method », appelez cette méthode « ditBonjour » donnez lui le type String comme « return type », ajoutez lui un paramètre de type String nommé « aQui ». Le contenu de cette méthode sera le suivant « return "Bonjour " + aQui + " !!!"; » . Il ne vous aura pas échappé que le prototype de la méthode a été rajouté dans l'interface « PremierEJB3Remote ». Vous pouvez tester votre travail en lancant le serveur, pour ce faire faites un clic droit sur le projet « IntroEJB3 » et en cliquant sur « Run », après quelques secondes un message doit vous afficher que le serveur est bien lancé et que le projet IntroEJB3 a été chargé par Glassfish, en cas de soucis n'hésitez pas à augmenter le timeout (surtout si votre machine est peu véloce) du lancement du serveur.

Passons au client, créez un projet Java de type « Java Application », appelez le « ClientEJB3 », créez un package « com.et ». Créez dans ce package une classe « ClientPremierEJB3 » qui contient le code suivant :

package com.et;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;


public class ClientPremierEJB3 {
public static void main(String[] args) {
try {
Hashtable hashtableEnvironment = new Hashtable();
hashtableEnvironment.put("java.naming.factory.initial",
"com.sun.enterprise.naming.SerialInitContextFactory");
hashtableEnvironment.put("java.naming.factory.url.pkgs",
"com.sun.enterprise.naming");
hashtableEnvironment.put("java.naming.factory.state",
"com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");
hashtableEnvironment.put("org.omg.CORBA.ORBInitialHost",
"localhost");
hashtableEnvironment.put("org.omg.CORBA.ORBInitialPort",
"3700");
Context context = new InitialContext(hashtableEnvironment);
PremierEJB3Remote beanRemote = (PremierEJB3Remote)
context.lookup("com.et.PremierEJB3Remote");
System.out.println(beanRemote.ditBonjour("ClientPremierEJB3"));
} catch (NamingException e) {
e.printStackTrace();
}
}
}

Vous notez ici quelques différence avec le tutoriel d'eclipse totale, d'une part j'ai renseigné les paramètres JNDI dans une hashtable et non pas dans un fichier « jndi.properties » et d'autre par la chaine de caractère passé en paramètre à la méthode « lookup » de l'objet « context », n'est pas la même.
Je n'ai pas utilisé de fichier « jndi.properties » pour des raisons de simplicité. La chaine passé en paramètre à la méthode « lookup » est différente parce que celle présente sur le tutoriel d'éclipse totale ne permet pas de retrouver le bean « PremierEJB3Bean ». De plus, quel est l'intérêt de créer une interface si le client cherche un bean à partir du nom de sa classe d'implémentation ? Si l'on utilise l'interface « remote » du bean « PremierEJB3Bean » dans la méthode « lookup » quel est l'intérêt de rajouter « /remote » à la fin de la chaine de caractère ? Afin de vous évitez quelques déconvenue je vous recommande l'ajout des jar suivantes : « appserv-rt.jar » et « javaee.jar ». La jar « appserv-rt.jar » vous évitera l'exception « classnotfoundexception » en effet vous avez besoin de la classe « com.sun.enterprise.naming.SerialInitContextFactory » qui se trouve justement dans ce jar. Il en est de même pour la jar « javaee.jar » qui vous permettra d'éviter le « classnotfoundexception » avec la classe « javax.security.jacc.PolicyException », ces jar doivent bien évidement êtres accessible lors de l'exécution du programme. N'oubliez pas de référencez le projet « IntroEJB3 » dans les librairies de « ClientEJB3 » pour la compilation et l'exécution du programme.

Utilisez la chaine "PremierEJB3Bean/remote" en paramètre de la méthode « lookup » et vous obtiendrez une magnifique « javax.naming.NameNotFoundException ». Si vous décidez d'utiliser la chaine "PremierEJB3Remote/remote"  en paramètre a cette même méthode vous obtiendrez une autre « javax.naming.NameNotFoundException ». En utilisant "com.et.PremierEJB3Remote/remote" vous obtiendrez une curieuse « javax.naming.NameAlreadyBoundException: com.et.PremierEJB3Remote », curieuse dans la mesure où nous n'essayons pas de refaire un binding, nous aurions utilisé la fonction «bind » pour cela. La chaine "com.et.PremierEJB3Remote", elle permettra à votre client de s'exécuter convenablement. Cela me semble logique dans la mesure ou en utilisant l'interface de type « remote » il est évident que l'on souhaite accéder à un bean distant, le suffixe « /remote » deviens donc inutile. Préfixer le nom de l'interface par son package me parait là aussi logique.