Guide des travaux pratiques logiciels libres
centré sur Java Enterprise Edition 6
Cours donnés à l'ESIEA
Contributeurs :
M.-A. DARCHE (Auteur original)
Laurent GODARD (Aide LibreOffice)
Dernière mise à jour :2011-09-22
Table des matières Table des matières
1 Utilisation de Mercurial
5 2 Nouveautés introduites dans Java 5
7 3 Développement d'une application Java EE
8 3.1 Documentation de référence en ligne
8 3.2 Sujets des applications à développer
8 4 Points vérifiés pour la notation
9 4.1 Génération d'une structure de projet avec Maven
9 4.2 Arborescence des sources à respecter
11 4.4 En-têtes des auteurs et des licences des fichiers source
12 4.5 Format du fichier de construction Ant à respecter
13 4.6 Sources Java demandées
14 5 Étapes de la réalisation
15 5.1 Développement du projet dans Eclipse
15 5.1.1 Création d'un projet dans Eclipse
15 5.1.2 Définition des bibliothèques pour la compilation
15 5.2 Mise en place des traitements avec Ant
16 5.3 Création d'une distribution WAR
17 5.3.1 Structure du WAR
17 5.3.2 Création de la TestServlet et de JSP
17 5.3.3 Correspondances des URL et des services (Servlets, JSP)
18 5.4 Création des distributions JAR et EAR
19 5.4.1 Création des classes Entity
19 5.4.2 Création d'un EJB Stateless
19 5.5 Création d'un EJB Stateful
19 5.5.1 Création de la ControlServlet communiquant avec les EJB Session
20 5.5.2 Structure de l'EJB JAR
20 5.5.3 Structure du EAR
20 5.5.4 Correspondances des URL et des services (Servlets, JSP)
20 5.6 Génération des WebServices
21 5.7 Utilisation de JSF
21 6 Précisions techniques
22 6.1 Démarrage/arrêt /déploiement avec serveur d'application JEE
22 6.2 Répertoires de déploiement
22 6.2.1 Démarrage/arrêt/déploiement avec GlassFish
22 6.2.1.1 Permissions et droits d'accès
23 6.2.2 Démarrage de JBoss
23 6.3 JNDI service de JBoss
23 6.4 Références JNDI des EJB
23 6.5 Sources de données
24 6.7 Vérifications dans GlassFish
25 6.7.1 Visiter et vérifier la connexion à la base de données
26 6.7.2 Vérifier les paramètres d'auto-déploiement
26 6.7.3 Vider le contenu de la base de données Derby
26 6.7.4 Vérifier le contenu de la base de données Derby
26 Résumé
Ceci est le guide à suivre pour le déroulement du TP logiciels libres à l'ESIEA.
Ce guide indique la liste des points que l'étudiant devra suivre et qui serviront de base à la notation du TP par l'enseignant.
Voici ci-dessous le schéma des interactions qui sont à réaliser dans le cadre du TP :
EJB Stateful Session
EJB Stateless Session
ControlServlet
Navigateur web
Gestionnaire de persistance
Entities
Utilisation de Mercurial
Utilisation de Mercurial (hg), logiciel de gestion de version décentralisé, sur un référentiel local et sur un référentiel distant.
Le préalable est de créer et renseigner son fichier personnel de configuration pour Mercurial. C'est le fichier ~/.hgrc. Il faut a minima y faire figurer l'information suivante :
[ui]
username = Pierre DUPONT <pierre.dupont@example.net>
Voici les premières commandes à utiliser :
$ hg –help
$ hg init
$ hg add README.txt
$ hg commit -m"Explain the reason of the modification" README.txt
Pour mettre immédiatement à disposition un accès web en lecture seule à son dépôt de sources :
$ hg serve --help
$ hg serve
$ hg serve –daemon
Le contenu du dépôt de sources sera alors disponible à l'adresse
http://localhost:8000/Pour que cet accès web permette également les modifications,
modifier le fichier .hg/hgrc du dépôt de sources Mercurial comme suit :
[web]
push_ssl = false
allow_push = *
La méthode
hg serve est très efficace mais limitée. Pour réaliser des paramétrages de permissions plus poussés on se reportera à la documentation
http://mercurial.selenic.com/wiki/PublishingRepositories .
Pour récupérer le contenu d'un dépôt de sources :
$ hg pull
$ hg update
À l'issue du TP, le travail réalisé (les sources) par chaque étudiant sera récupéré par l'enseignant directement à partir du référentiel de sources Mercurial mis en place par chaque étudiant.
Nouveautés introduites dans Java 5
Le code développé utilisera les nouveautés suivantes du langage Java introduites dans sa version 5 :
les generics
les annotations
Documentation : http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html GenericsExemples de generics :Set<String> set = new HashSet<String>();List<Ticket> list = new ArrayList<Ticket>(); AnnotationsExemples d'annotations :@Entity@PersistenceContextExemples d'utilisation d'annotations :@Idpublic String getEmail() { return email;}@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;@OneToMany(cascade = CascadeType.ALL)public List<Ticket> getAssignedTickets() { return assignedTickets;} Développement d'une application Java EEDéveloppement d'une application Java EE (JEE) en testant le bon fonctionnement sur plusieurs plateformes :le serveur d'application GlassFish
le serveur d'application JBoss
Documentation de référence en ligneOn pourra s'aider du tutoriel suivant :http://download.oracle.com/javaee/6/tutorial/doc/ Sujets des applications à développerChaque étudiant se verra attribuer un sujet parmi les sujets ci-dessous :Sujet A : Service de passage d'ordres bancaires. L'application doit avoir une notion de client, de compte bancaire (un client peut avoir plusieurs comptes), et permettre de passer des ordres bancaires (virement, achat de titre, vente de titre). Il est demandé à minima de développer une interface web de guichet pour la création et la consultation de compte client, la création de compte bancaire. Ensuite il faudra développer une console de passage d'ordres bancaires qui sera utilisée par les employés de la banque.
Sujet B : Application de réservation de salles sur un seul site. Il doit être possible de créer, supprimer, des salles et de réserver et supprimer des réservations. Il est demandé à minima de créer un frontal web de gestion des salles. Ensuite on s'attachera à créer une interface web de réservation de salles.
Points vérifiés pour la notationLa notation des travaux pratiques s'effectuera pour la plus grande partie de manière automatique par un programme de l'enseignant qui vérifiera les points suivants directement sur les sources récupérées par le biais de Mercurial sur le dépôt de sources de l'étudiant. Génération d'une structure de projet avec MavenSi on dispose de Maven sur son système, on peut générer une structure de projet de manière automatique pour exemple. Par contre on utilisera tout de même Ant pour la génération des livrables pour la compréhension que cela apporte.Pour générer la structure du projet, il faut exécuter la commande ci-dessous. Cela peut prendre longtemps en fonction de la connexion réseau car Maven va récupérer les versions les plus récentes des artefacts. Il peut également être nécessaire de relancer la commande plusieurs fois si certains serveurs coupent les connexions qui prennent trop de temps.$ mvn archetype:generate -DgroupId=fr.esiea_ouest.inf5043.sujet_a -DartifactId=TP_Java_EE -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=falseLe résultat alors obtenu est le suivant :TP_Java_EE
├── pom.xml
└── src
├── main
│ └── java
│ └── fr
│ └── esiea_ouest
│ └── inf5043
│ └── sujet_a
│ └── App.java
└── testOn peut alors lancer la construction des livrables avec la commande suivante :mvn packageLe résultat alors obtenu est le suivant :TP_Java_EE
├── pom.xml
├── src
│ ├── main
│ │ └── java
│ │ └── fr
│ │ └── esiea_ouest
│ │ └── inf5043
│ │ └── sujet_a
│ │ └── App.java
│ └── test
└── target
├── classes
│ └── fr
│ └── esiea_ouest
│ └── inf5043
│ └── sujet_a
│ └── App.class
├── maven-archiver
│ └── pom.properties
└── TP_Java_EE-1.0-SNAPSHOT.jar Arborescence des sources à respecterArborescence type à respecter :Nom_du_projet├── bin│ ├── jeesetallpaths│ ├── jeestart│ └── jeestop├── build.properties├── build.xml├── ChangeLog.txt├── conf│ ├── application.xml│ ├── faces-config.xml│ ├── persistence.xml│ └── web.xml├── dist├── LICENSE.txt├── pom.xml├── README.txt├── src│ └── org│ └── aful│ └── example1│ ├── client│ │ └── Runner.java│ ├── ejb│ │ ├── TicketDeskBean.java│ │ ├── TicketDesk.java│ │ ├── UserAccountBoardBean.java│ │ └── UserAccountBoard.java│ ├── entity│ │ ├── Ticket.java│ │ └── UserAccount.java│ └── server│ ├── CalculatorUiController.java│ ├── ControlServlet.java│ ├── EjbUtil.java│ ├── TestServlet.java│ └── TicketUiController.java└── web ├── calculator.jsp ├── calculator-results.jsp ├── index.jsp ├── ticket-create.jsp ├── ticket-create-servlet.jsp ├── ticket-creation-result.jsp ├── ticket-list.jsp ├── timer-create.jsp ├── user-create.jsp └── user-list.jspLe fichier README.txt doit contenir une première ligne avec le nom et prénom (dans cet ordre) de l'étudiant ou des étudiants, et en deuxième ligne le nom du sujet. Ne pas respecter ce format empêchera le projet d'être reconnu et ne pourra donc pas donner lieu à une note.
Le fichier LICENSE.txt doit contenir le texte de la ou les licences « logiciel libre » choisie(s) pour le projet.
Packages JavaToutes les classes Java doivent avoir un nom de package spécifié. Ce nom doit refléter l'adresse Internet de la structure à laquelle l'auteur appartient.Pour les étudiants de l'ESIEA Paris et de l'ESIEA Ouest à Laval les packages des classes Java doivent commencer respectivement par fr.esiea.inf5043. et fr.esiea_ouest.inf5043.Exemple de code Java à insérer en début d'un fichier .java pour spécifier le package :package fr.esiea_ouest.inf5043.ejb.sujet_aOn notera qu'on ne peut pas utiliser le tiret « - » dans un nom de package. En-têtes des auteurs et des licences des fichiers sourceTous les fichiers sources (particulièrement tous les fichiers qui décrivent l'intelligence du programme, en pratique on néglige souvent les fichiers de configuration n'apportant pas de valeur ajoutée) doivent avoir une en-tête (les premières lignes du fichier) spécifiant les contributeurs du fichier ainsi que la ou les licences de distribution.Pour du code Java et JavaScript l'en-tête sera de la forme suivante :/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * Contributor(s): * M.-A. Darche <ma.darche@aful.org> (Original Author) *
* ***** END LICENSE BLOCK ***** */Pour du code XML l'en-tête sera de la forme suivante (attention de ne pas mettre l'en-tête des auteurs et des licences avant la déclaration XML) :<?xml version='1.0' encoding='UTF-8' ?><!-- * **** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * * Contributor(s): * M.-A. Darche <ma.darche@aful.org> (Original Author) *
* ***** END LICENSE BLOCK ***** -->Et on adaptera ainsi le bloc de licence en fonction de la syntaxe à utiliser pour les commentaires dans chaque type de langage de programmation, chaque type de configuration, etc. Format du fichier de construction Ant à respecterChaque projet doit comporter un fichier de construction Ant : build.xml. Ce fichier build.xml est utilisé pour construire et déployer l'application en dehors de tout environnement graphique interactif.Le fichier build.xml des étudiants devra impérativement comporter les propriétés suivantes pour être facilement portable et testable, notamment sur le système de l'enseignant :<property file="build.properties" /><property name="jee.home" location="XXXX" /><property name="jee.lib" location="YYYY" />Le fichier build.xml devra également avoir toutes les targets fonctionnelles suivantes :prepare (crée les répertoires build et dist si ils n'existent pas)
clean (supprime les répertoires build et dist si ils existent)
war
war-deploy
ejb
ejb-deploy
ear
ear-deploy
build (effectue les tâches war, ejb, ear)
dist (génère le livrable à fournir au professeur à la fin du TP)
La target dist devra générer une archive avec un nom de fichier de la forme suivante :Année_promo-Ville-Nom_étudiant-Nom_sujet.(tar.gz|zip) Sources Java demandéesLes sources de l'application, devront comprendre au moins :une Servlet de test nommée TestServlet
deux classes de type Entity
un Stateless Session Bean
un Stateful Session Bean
une Servlet de service nommée ControlServlet
enchaînement de pages avec JSF
Étapes de la réalisation Développement du projet dans Eclipse Création d'un projet dans EclipseSi le projet existe déjà sur le système de fichiers on procédera comme suit :File -> New -> Java ProjectDécocher « Use default location »
et préciser l'emplacement dans « Location »Sur les anciennes versions d'Eclipse l'assistant de création de projet est un peu différent et on procédera comme suit :File -> New -> Java Project« Create project from existing source »Si le projet Eclipse a été généré à partir de Maven :File -> Import -> General -> Existing Projects into Workspace Définition des bibliothèques pour la compilationLa définition du CLASSPATH est utile pour le bon fonctionnement d'Eclipse, mais il faut définir quelles bibliothèques (library) utiliser pour la compilation (et la vérification au fil de l'eau) du projet.
Définition d'une User Library et ajout de la User Library dans le Build Path du projet :Window -> Preferences -> Java -> Build Path -> User Libraries -> NewJEE -> Add JARs Mise en place des traitements avec AntMise en place des traitements (compilation, déploiement, etc.) en définissant un fichier build.xml utilisé par Ant.PS : Ne pas utiliser les tâches optionnelles de Ant, car le plus souvent obsolètes et/ou non portables.Documentation : http://ant.apache.org/ Création d'une distribution WARCréation d'une archive WAR à l'aide de Ant pour y stocker des Servlets et des JSP.On fera bien attention de ne pas mettre de JAR contenant des EJB dans le WAR. Les seuls JAR autorisés dans le WAR sont des JAR de bibliothèques (par exemple des utilitaires, etc.). Le ou les JAR contenant des EJB doivent être placés dans un EAR.À noter que le tutoriel Java EE contient des exemples de code, notamment des exemples de fichiers web.xml.La spécification complète de Java Platform Enterprise Edition où on pourra trouver la syntaxe des fichiers de configuration XML comme web.xml, application.xml, persistence.xml :http://java.sun.com/javaee/technologies/ Structure du WAR$ unzip -l dist/inf5043-example-1.war META-INF/META-INF/MANIFEST.MFWEB-INF/WEB-INF/web.xmlWEB-INF/classes/WEB-INF/classes/fr/WEB-INF/classes/fr/esiea_ouest/WEB-INF/classes/fr/esiea_ouest/example1/WEB-INF/classes/fr/esiea_ouest/example1/server/WEB-INF/classes/fr/esiea_ouest/example1/server/CalculatorUiController.classWEB-INF/classes/fr/esiea_ouest/example1/server/ControlServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/EjbUtil.classWEB-INF/classes/fr/esiea_ouest/example1/server/TestServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/TicketUiController.classWEB-INF/faces-config.xmlindex.jspticket-create-servlet.jspticket-create.jspticket-creation-result.jspticket-list.jsptimer-create.jspuser-create.jspuser-list.jsp Création de la TestServlet et de JSPCréation et déploiement d'une Servlet et de JSP. On commencera par une Servlet de test (nommée TestServlet) héritant de la classe http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.htmlTestServlet devra juste afficher un message « Bonjour N » avec « N » étant un compteur qui sera incrémenté à chaque rechargement de la page. Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test sera de la forme suivante : http://localhost:8080/inf5043-example-1/testLes correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par deux paramètres :le nom du .war qui va déterminer le nom de l'application web (webapp) juste après l'adresse du serveur d'application (dans l'exemple le war a pour nom inf5043-example-1.war)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Création des distributions JAR et EARCréation d'artefacts JAR et WAR à l'aide de Ant pour y stocker respectivement les Entity, les EJB (Stateless Session Bean et Stateful Session Bean) et les ressources de l'application.
Création des classes EntityCréation au minimum de deux classes Entity. Création du fichier persistence.xml avec définition de la persistence-unit. Création d'un EJB StatelessCréation d'un EJB Stateless qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.war Création d'un EJB StatefulCréation d'un EJB Stateful qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.warLa différence avec l'EJB Stateless viendra du fait que les méthodes de l'EJB Stateful se feront dans le cadre d'un contexte persistant. Création de la ControlServlet communiquant avec les EJB SessionRécupération d'une référence sur les EJB Session par JNDI de manière générique :Context jndiContext = new InitialContext();String refName = BeanInterface.class.getName();BeanInterface beanObject = (BeanInterface) jndiContext.lookup(refName);Exemple de code avec des noms de classes réels :Context jndiContext = new InitialContext();String refName = TicketDesk.class.getName();TicketDesk ticketDesk = (TicketDesk) jndiContext.lookup(refName); Structure de l'EJB JAR$ unzip -l dist/inf5043-example-1-ejb.jar META-INF/META-INF/MANIFEST.MForg/org/aful/org/aful/example1/org/aful/example1/ejb/org/aful/example1/ejb/TicketDesk.classorg/aful/example1/ejb/TicketDeskBean.classorg/aful/example1/ejb/UserAccountBoard.classorg/aful/example1/ejb/UserAccountBoardBean.classorg/aful/example1/entity/org/aful/example1/entity/Ticket.classorg/aful/example1/entity/UserAccount.classMETA-INF/persistence.xml Structure du EAR$ unzip -l dist/inf5043-example-1.ear META-INF/META-INF/MANIFEST.MFMETA-INF/application.xmlaful-example-1-ejb.jaraful-example-1.war Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test deviendra de la forme suivante : http://localhost:8080/project-name/test Ce qui change de la forme précédente qui était : http://localhost:8080/inf5043-example-1/testCeci vient du fait que maintenant les correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par les deux paramètres suivants :le context-root définit dans le fichier application.xml (dans l'exemple le contexte root vaut project-name)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Les correspondances entre les URL et les services déployés (Servlets, JSP) sont définies dans le fichier web.xml et le fichier application.xml. Génération des WebServicesGénération des Web services (en SOAP) pour les EJB Stateless Session à l'aide de l'annotation suivante :@WebMethodSeuls les Stateless Session Beans peuvent implémenter un Web service. Utilisation de JSFUtilisation de JSF pour la génération et la gestion des interactions des pages web. Précisions techniquesCette section décrit l'ensemble des précisions techniques utiles lors de l'utilisation de GlassFish et JBoss. Démarrage/arrêt /déploiement avec serveur d'application JEE Répertoires de déploiementGlassfish et JBoss n'ont pas la même structure d'arborescence, et leur répertoire de déploiement ne se trouve pas au même endroit :GlassFish : GLASSFISH_HOME/domains/domain1/autodeployJBoss : JBOSS_HOME/server/default/deployAussi il faut bien penser à modifier le build.xml lors d'un déploiement avec Ant, selon qu'on déploit sur GlassFish ou JBoss.Lorsque vous avez des erreurs de déploiement au niveau du serveur d'application, pensez bien à supprimer du répertoire de déploiement toutes les versions des JAR ou autres artefacts que vous avez pu déployer. L'idée est d'avoir une situation parfaitement propre avant de déployer quelque chose. Démarrage/arrêt/déploiement avec GlassFish$ cd GLASSFISH_HOME$ bin/asadmin start-domain domain1=> http://localhost:8080/Il est nécessaire de démarrer la base de données Derby embarquée si on souhaite l'utiliser comme c'est notre cas :$ bin/asadmin start-databaseArrêt des services :$ bin/asadmin stop-domain domain1$ bin/asadmin stop-database Permissions et droits d'accèsPour administrer GlassFish il peut être nécessaire de passer sous l'utilisateur glassfish :$ sudo su - glassfishDe plus, pour qu'un utilisateur puisse déployer des artefacts dans GlassFish il est nécessaire qu'il ait les droits nécessaires pour écrire dans le dossier autodeploy de GlassFish. Dans le cadre du TP, uniquement dans le cadre de tests et surtout pas en production, on pourra donc réaliser la manipulation suivante qui compromet la sécurité de l'application mais qui permet le déploiement par tous les utilisateurs :$ sudo su – glassfish
$ chmod a+rwx /opt/java-ee-6/glassfish/domains/domain1/autodeploy Démarrage de JBoss$ cd JBOSS_HOME$ bin/run.sh=> http://localhost:8080/ JNDI service de JBossLe fichier JBOSS_HOME/server/default/conf/jndi.properties doit bien comporter les propriétés suivantes :java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfacesjava.naming.provider.url=jnp://localhost:1099On peut vérifier que les EJB sont bien présents, et avec quel nom, au niveau du service de nommage JNDI à partir de la JMX Console :http://localhost:8080/ -> JMX Console -> service=JNDIView -> java.lang.String list() -> InvokeOn obtient alors une sortie du type de celle incluse dans le fichier jndiview-list.txt. Références JNDI des EJBLes références JNDI des EJB peuvent varier de JBoss à Glassfish.Attention le code suivant n'est pas portable :@Stateless(mappedName="fr.esiea_ouest.example1.ejb.TicketDesk") Sources de donnéesBien penser à changer la source de données spécifiées dans persistence.xml quand on passe de JBoss à GlassFish ou inversement. Vérifications LogsLorsqu'on déploie des artefacts (des JAR, des WAR, des EAR), les opérations effectuées sont listées en temps réel dans les logs de l'application. Les causes d'erreurs de non-déploiement (par exemple mauvaise configuration de la persistance cf. section plus loin) ou le fait que les composants ont bien été déployés sont détaillés.Glassfish et JBoss n'ont pas la structure d'arborescence, notamment les fichiers de log sont différents :GlassFish : GLASSFISH_HOME/domains/domain1/logs/server.logJBoss : JBOSS_HOME/server/default/log/server.log VérificateurJEE est fournie avec un outil de vérification des artefacts : verifier. On peut utiliser cet outil sur n'importe quel artefact préalablement à tout déploiement, ça permet d'aller un peu plus vite que l'attente d'un déploiement, mais surtout les résultats de l'analyse du vérificateur sont généralement un peu plus clairs lorsqu'ils sont isolés du reste des logs de l'application.$ JEE_HOME/bin/verifier example-ejb.jar$ JEE_HOME/bin/verifier example-webapp.war$ JEE_HOME/bin/verifier example-application.ear Vérifications dans GlassFishAvec Glassfish il est nécessaire de paramétrer un certain nombre de paramètre dans l'interface d'administration.http://localhost:4848/admin / javaadmin Visiter et vérifier la connexion à la base de données Resources> JDBC> JDBC Resources> jdbc/__defaultStatus : Enabled=> Save Vérifier les paramètres d'auto-déploiement Application Server -> Advanced :Reload : EnabledAuto Deploy : EnabledVerifier : EnabledPrecompile : Enabled=> Save Vider le contenu de la base de données DerbyAvant de supprimer le contenu de la base Derby, il faut s'assurer qu'elle n'est pas utilisée par l'application Glassfish. Une fois arrêtée on peut supprimer son contenu :$ rm -rf /media/cdrom/jee5/databases/*Les structures nécessaires au bon fonctionnement de la base seront créées à nouveau lors du prochain démarrage de la base Derby. Vérifier le contenu de la base de données DerbyAvant de se connecter à la base Derby, il faut s'assurer qu'elle n'est pas démarrée pour être utilisée avec l'application GlassFish. Une fois arrêtée on peut y accéder comme suit : $ export DERBY_HOME=/opt/SDK/javadb/tmp/jee5-databases$ bash /opt/SDK/javadb/bin/ijversion ij 10.2ij> help; Les commandes prises en charge sont les suivantes : PROTOCOL 'protocole JDBC' [ AS identificateur ]; -- définit un protocole par défaut ou indiqué DRIVER 'classe de pilote'; -- charge la classe indiquée CONNECT 'url de la base de données' [ PROTOCOL ProtocoleIndiqué ] [ AS NomDeConnexion ]; -- se connecte à l'URL de la base de données -- et peut affecter un identificateur SET CONNECTION NomDeConnexion; -- bascule vers la connexion indiquée SHOW CONNECTIONS; -- répertorie toutes les connexions AUTOCOMMIT [ ON | OFF ]; -- active ou désactive le mode de validation automatique pour la connexion DISCONNECT [ CURRENT | NomDeConnexion | ALL ]; -- interrompt la connexion en cours, la connexion indiquée ou toutes les connexions; -- la valeur par défaut est CURRENT SHOW SCHEMAS ; -- répertorie tous les schémas de la base de données actuelle SHOW [ TABLES | VIEWS | PROCEDURES | SYNONYMS ] { IN schéma }; ; -- répertorie les tables, les vues, les procédures ou les synonymesij> connect 'jdbc:derby:/opt/SDK/databases/sun-appserv-samples';ij> show tables;TABLE_SCHEM |TABLE_NAME |REMARKS------------------------------------------------------------------------SYS |SYSALIASES |SYS |SYSCHECKS |SYS |SYSCOLPERMS |SYS |SYSCOLUMNS |SYS |SYSCONGLOMERATES |SYS |SYSCONSTRAINTS |SYS |SYSDEPENDS |SYS |SYSFILES |SYS |SYSFOREIGNKEYS |SYS |SYSKEYS |SYS |SYSROUTINEPERMS |SYS |SYSSCHEMAS |SYS |SYSSTATEMENTS |SYS |SYSSTATISTICS |SYS |SYSTABLEPERMS |SYS |SYSTABLES |SYS |SYSTRIGGERS |SYS |SYSVIEWS |SYSIBM |SYSDUMMY1 |APP |SEQUENCE |APP |TICKET |APP |USERACCOUNTBEAN |22 lignes sélectionnéesij> exit;
Generics
Exemples de generics :
Set<String> set = new HashSet<String>();
List<Ticket> list = new ArrayList<Ticket>();
Annotations
Exemples d'annotations :
@Entity
@PersistenceContext
Exemples d'utilisation d'annotations :
@Id
public String getEmail() {
return email;
}
@PersistenceContext(unitName = "ejb1-example")
private EntityManager emanager;
@OneToMany(cascade = CascadeType.ALL)
public List<Ticket> getAssignedTickets() {
return assignedTickets;
}
Développement d'une application Java EE
Développement d'une application Java EE (JEE) en testant le bon fonctionnement sur plusieurs plateformes :
le serveur d'application GlassFish
le serveur d'application JBoss
Documentation de référence en ligneOn pourra s'aider du tutoriel suivant :http://download.oracle.com/javaee/6/tutorial/doc/ Sujets des applications à développerChaque étudiant se verra attribuer un sujet parmi les sujets ci-dessous :Sujet A : Service de passage d'ordres bancaires. L'application doit avoir une notion de client, de compte bancaire (un client peut avoir plusieurs comptes), et permettre de passer des ordres bancaires (virement, achat de titre, vente de titre). Il est demandé à minima de développer une interface web de guichet pour la création et la consultation de compte client, la création de compte bancaire. Ensuite il faudra développer une console de passage d'ordres bancaires qui sera utilisée par les employés de la banque.
Sujet B : Application de réservation de salles sur un seul site. Il doit être possible de créer, supprimer, des salles et de réserver et supprimer des réservations. Il est demandé à minima de créer un frontal web de gestion des salles. Ensuite on s'attachera à créer une interface web de réservation de salles.
Points vérifiés pour la notationLa notation des travaux pratiques s'effectuera pour la plus grande partie de manière automatique par un programme de l'enseignant qui vérifiera les points suivants directement sur les sources récupérées par le biais de Mercurial sur le dépôt de sources de l'étudiant. Génération d'une structure de projet avec MavenSi on dispose de Maven sur son système, on peut générer une structure de projet de manière automatique pour exemple. Par contre on utilisera tout de même Ant pour la génération des livrables pour la compréhension que cela apporte.Pour générer la structure du projet, il faut exécuter la commande ci-dessous. Cela peut prendre longtemps en fonction de la connexion réseau car Maven va récupérer les versions les plus récentes des artefacts. Il peut également être nécessaire de relancer la commande plusieurs fois si certains serveurs coupent les connexions qui prennent trop de temps.$ mvn archetype:generate -DgroupId=fr.esiea_ouest.inf5043.sujet_a -DartifactId=TP_Java_EE -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=falseLe résultat alors obtenu est le suivant :TP_Java_EE
├── pom.xml
└── src
├── main
│ └── java
│ └── fr
│ └── esiea_ouest
│ └── inf5043
│ └── sujet_a
│ └── App.java
└── testOn peut alors lancer la construction des livrables avec la commande suivante :mvn packageLe résultat alors obtenu est le suivant :TP_Java_EE
├── pom.xml
├── src
│ ├── main
│ │ └── java
│ │ └── fr
│ │ └── esiea_ouest
│ │ └── inf5043
│ │ └── sujet_a
│ │ └── App.java
│ └── test
└── target
├── classes
│ └── fr
│ └── esiea_ouest
│ └── inf5043
│ └── sujet_a
│ └── App.class
├── maven-archiver
│ └── pom.properties
└── TP_Java_EE-1.0-SNAPSHOT.jar Arborescence des sources à respecterArborescence type à respecter :Nom_du_projet├── bin│ ├── jeesetallpaths│ ├── jeestart│ └── jeestop├── build.properties├── build.xml├── ChangeLog.txt├── conf│ ├── application.xml│ ├── faces-config.xml│ ├── persistence.xml│ └── web.xml├── dist├── LICENSE.txt├── pom.xml├── README.txt├── src│ └── org│ └── aful│ └── example1│ ├── client│ │ └── Runner.java│ ├── ejb│ │ ├── TicketDeskBean.java│ │ ├── TicketDesk.java│ │ ├── UserAccountBoardBean.java│ │ └── UserAccountBoard.java│ ├── entity│ │ ├── Ticket.java│ │ └── UserAccount.java│ └── server│ ├── CalculatorUiController.java│ ├── ControlServlet.java│ ├── EjbUtil.java│ ├── TestServlet.java│ └── TicketUiController.java└── web ├── calculator.jsp ├── calculator-results.jsp ├── index.jsp ├── ticket-create.jsp ├── ticket-create-servlet.jsp ├── ticket-creation-result.jsp ├── ticket-list.jsp ├── timer-create.jsp ├── user-create.jsp └── user-list.jspLe fichier README.txt doit contenir une première ligne avec le nom et prénom (dans cet ordre) de l'étudiant ou des étudiants, et en deuxième ligne le nom du sujet. Ne pas respecter ce format empêchera le projet d'être reconnu et ne pourra donc pas donner lieu à une note.
Le fichier LICENSE.txt doit contenir le texte de la ou les licences « logiciel libre » choisie(s) pour le projet.
Packages JavaToutes les classes Java doivent avoir un nom de package spécifié. Ce nom doit refléter l'adresse Internet de la structure à laquelle l'auteur appartient.Pour les étudiants de l'ESIEA Paris et de l'ESIEA Ouest à Laval les packages des classes Java doivent commencer respectivement par fr.esiea.inf5043. et fr.esiea_ouest.inf5043.Exemple de code Java à insérer en début d'un fichier .java pour spécifier le package :package fr.esiea_ouest.inf5043.ejb.sujet_aOn notera qu'on ne peut pas utiliser le tiret « - » dans un nom de package. En-têtes des auteurs et des licences des fichiers sourceTous les fichiers sources (particulièrement tous les fichiers qui décrivent l'intelligence du programme, en pratique on néglige souvent les fichiers de configuration n'apportant pas de valeur ajoutée) doivent avoir une en-tête (les premières lignes du fichier) spécifiant les contributeurs du fichier ainsi que la ou les licences de distribution.Pour du code Java et JavaScript l'en-tête sera de la forme suivante :/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * Contributor(s): * M.-A. Darche <ma.darche@aful.org> (Original Author) *
* ***** END LICENSE BLOCK ***** */Pour du code XML l'en-tête sera de la forme suivante (attention de ne pas mettre l'en-tête des auteurs et des licences avant la déclaration XML) :<?xml version='1.0' encoding='UTF-8' ?><!-- * **** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * * Contributor(s): * M.-A. Darche <ma.darche@aful.org> (Original Author) *
* ***** END LICENSE BLOCK ***** -->Et on adaptera ainsi le bloc de licence en fonction de la syntaxe à utiliser pour les commentaires dans chaque type de langage de programmation, chaque type de configuration, etc. Format du fichier de construction Ant à respecterChaque projet doit comporter un fichier de construction Ant : build.xml. Ce fichier build.xml est utilisé pour construire et déployer l'application en dehors de tout environnement graphique interactif.Le fichier build.xml des étudiants devra impérativement comporter les propriétés suivantes pour être facilement portable et testable, notamment sur le système de l'enseignant :<property file="build.properties" /><property name="jee.home" location="XXXX" /><property name="jee.lib" location="YYYY" />Le fichier build.xml devra également avoir toutes les targets fonctionnelles suivantes :prepare (crée les répertoires build et dist si ils n'existent pas)
clean (supprime les répertoires build et dist si ils existent)
war
war-deploy
ejb
ejb-deploy
ear
ear-deploy
build (effectue les tâches war, ejb, ear)
dist (génère le livrable à fournir au professeur à la fin du TP)
La target dist devra générer une archive avec un nom de fichier de la forme suivante :Année_promo-Ville-Nom_étudiant-Nom_sujet.(tar.gz|zip) Sources Java demandéesLes sources de l'application, devront comprendre au moins :une Servlet de test nommée TestServlet
deux classes de type Entity
un Stateless Session Bean
un Stateful Session Bean
une Servlet de service nommée ControlServlet
enchaînement de pages avec JSF
Étapes de la réalisation Développement du projet dans Eclipse Création d'un projet dans EclipseSi le projet existe déjà sur le système de fichiers on procédera comme suit :File -> New -> Java ProjectDécocher « Use default location »
et préciser l'emplacement dans « Location »Sur les anciennes versions d'Eclipse l'assistant de création de projet est un peu différent et on procédera comme suit :File -> New -> Java Project« Create project from existing source »Si le projet Eclipse a été généré à partir de Maven :File -> Import -> General -> Existing Projects into Workspace Définition des bibliothèques pour la compilationLa définition du CLASSPATH est utile pour le bon fonctionnement d'Eclipse, mais il faut définir quelles bibliothèques (library) utiliser pour la compilation (et la vérification au fil de l'eau) du projet.
Définition d'une User Library et ajout de la User Library dans le Build Path du projet :Window -> Preferences -> Java -> Build Path -> User Libraries -> NewJEE -> Add JARs Mise en place des traitements avec AntMise en place des traitements (compilation, déploiement, etc.) en définissant un fichier build.xml utilisé par Ant.PS : Ne pas utiliser les tâches optionnelles de Ant, car le plus souvent obsolètes et/ou non portables.Documentation : http://ant.apache.org/ Création d'une distribution WARCréation d'une archive WAR à l'aide de Ant pour y stocker des Servlets et des JSP.On fera bien attention de ne pas mettre de JAR contenant des EJB dans le WAR. Les seuls JAR autorisés dans le WAR sont des JAR de bibliothèques (par exemple des utilitaires, etc.). Le ou les JAR contenant des EJB doivent être placés dans un EAR.À noter que le tutoriel Java EE contient des exemples de code, notamment des exemples de fichiers web.xml.La spécification complète de Java Platform Enterprise Edition où on pourra trouver la syntaxe des fichiers de configuration XML comme web.xml, application.xml, persistence.xml :http://java.sun.com/javaee/technologies/ Structure du WAR$ unzip -l dist/inf5043-example-1.war META-INF/META-INF/MANIFEST.MFWEB-INF/WEB-INF/web.xmlWEB-INF/classes/WEB-INF/classes/fr/WEB-INF/classes/fr/esiea_ouest/WEB-INF/classes/fr/esiea_ouest/example1/WEB-INF/classes/fr/esiea_ouest/example1/server/WEB-INF/classes/fr/esiea_ouest/example1/server/CalculatorUiController.classWEB-INF/classes/fr/esiea_ouest/example1/server/ControlServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/EjbUtil.classWEB-INF/classes/fr/esiea_ouest/example1/server/TestServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/TicketUiController.classWEB-INF/faces-config.xmlindex.jspticket-create-servlet.jspticket-create.jspticket-creation-result.jspticket-list.jsptimer-create.jspuser-create.jspuser-list.jsp Création de la TestServlet et de JSPCréation et déploiement d'une Servlet et de JSP. On commencera par une Servlet de test (nommée TestServlet) héritant de la classe http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.htmlTestServlet devra juste afficher un message « Bonjour N » avec « N » étant un compteur qui sera incrémenté à chaque rechargement de la page. Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test sera de la forme suivante : http://localhost:8080/inf5043-example-1/testLes correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par deux paramètres :le nom du .war qui va déterminer le nom de l'application web (webapp) juste après l'adresse du serveur d'application (dans l'exemple le war a pour nom inf5043-example-1.war)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Création des distributions JAR et EARCréation d'artefacts JAR et WAR à l'aide de Ant pour y stocker respectivement les Entity, les EJB (Stateless Session Bean et Stateful Session Bean) et les ressources de l'application.
Création des classes EntityCréation au minimum de deux classes Entity. Création du fichier persistence.xml avec définition de la persistence-unit. Création d'un EJB StatelessCréation d'un EJB Stateless qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.war Création d'un EJB StatefulCréation d'un EJB Stateful qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.warLa différence avec l'EJB Stateless viendra du fait que les méthodes de l'EJB Stateful se feront dans le cadre d'un contexte persistant. Création de la ControlServlet communiquant avec les EJB SessionRécupération d'une référence sur les EJB Session par JNDI de manière générique :Context jndiContext = new InitialContext();String refName = BeanInterface.class.getName();BeanInterface beanObject = (BeanInterface) jndiContext.lookup(refName);Exemple de code avec des noms de classes réels :Context jndiContext = new InitialContext();String refName = TicketDesk.class.getName();TicketDesk ticketDesk = (TicketDesk) jndiContext.lookup(refName); Structure de l'EJB JAR$ unzip -l dist/inf5043-example-1-ejb.jar META-INF/META-INF/MANIFEST.MForg/org/aful/org/aful/example1/org/aful/example1/ejb/org/aful/example1/ejb/TicketDesk.classorg/aful/example1/ejb/TicketDeskBean.classorg/aful/example1/ejb/UserAccountBoard.classorg/aful/example1/ejb/UserAccountBoardBean.classorg/aful/example1/entity/org/aful/example1/entity/Ticket.classorg/aful/example1/entity/UserAccount.classMETA-INF/persistence.xml Structure du EAR$ unzip -l dist/inf5043-example-1.ear META-INF/META-INF/MANIFEST.MFMETA-INF/application.xmlaful-example-1-ejb.jaraful-example-1.war Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test deviendra de la forme suivante : http://localhost:8080/project-name/test Ce qui change de la forme précédente qui était : http://localhost:8080/inf5043-example-1/testCeci vient du fait que maintenant les correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par les deux paramètres suivants :le context-root définit dans le fichier application.xml (dans l'exemple le contexte root vaut project-name)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Les correspondances entre les URL et les services déployés (Servlets, JSP) sont définies dans le fichier web.xml et le fichier application.xml. Génération des WebServicesGénération des Web services (en SOAP) pour les EJB Stateless Session à l'aide de l'annotation suivante :@WebMethodSeuls les Stateless Session Beans peuvent implémenter un Web service. Utilisation de JSFUtilisation de JSF pour la génération et la gestion des interactions des pages web. Précisions techniquesCette section décrit l'ensemble des précisions techniques utiles lors de l'utilisation de GlassFish et JBoss. Démarrage/arrêt /déploiement avec serveur d'application JEE Répertoires de déploiementGlassfish et JBoss n'ont pas la même structure d'arborescence, et leur répertoire de déploiement ne se trouve pas au même endroit :GlassFish : GLASSFISH_HOME/domains/domain1/autodeployJBoss : JBOSS_HOME/server/default/deployAussi il faut bien penser à modifier le build.xml lors d'un déploiement avec Ant, selon qu'on déploit sur GlassFish ou JBoss.Lorsque vous avez des erreurs de déploiement au niveau du serveur d'application, pensez bien à supprimer du répertoire de déploiement toutes les versions des JAR ou autres artefacts que vous avez pu déployer. L'idée est d'avoir une situation parfaitement propre avant de déployer quelque chose. Démarrage/arrêt/déploiement avec GlassFish$ cd GLASSFISH_HOME$ bin/asadmin start-domain domain1=> http://localhost:8080/Il est nécessaire de démarrer la base de données Derby embarquée si on souhaite l'utiliser comme c'est notre cas :$ bin/asadmin start-databaseArrêt des services :$ bin/asadmin stop-domain domain1$ bin/asadmin stop-database Permissions et droits d'accèsPour administrer GlassFish il peut être nécessaire de passer sous l'utilisateur glassfish :$ sudo su - glassfishDe plus, pour qu'un utilisateur puisse déployer des artefacts dans GlassFish il est nécessaire qu'il ait les droits nécessaires pour écrire dans le dossier autodeploy de GlassFish. Dans le cadre du TP, uniquement dans le cadre de tests et surtout pas en production, on pourra donc réaliser la manipulation suivante qui compromet la sécurité de l'application mais qui permet le déploiement par tous les utilisateurs :$ sudo su – glassfish
$ chmod a+rwx /opt/java-ee-6/glassfish/domains/domain1/autodeploy Démarrage de JBoss$ cd JBOSS_HOME$ bin/run.sh=> http://localhost:8080/ JNDI service de JBossLe fichier JBOSS_HOME/server/default/conf/jndi.properties doit bien comporter les propriétés suivantes :java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfacesjava.naming.provider.url=jnp://localhost:1099On peut vérifier que les EJB sont bien présents, et avec quel nom, au niveau du service de nommage JNDI à partir de la JMX Console :http://localhost:8080/ -> JMX Console -> service=JNDIView -> java.lang.String list() -> InvokeOn obtient alors une sortie du type de celle incluse dans le fichier jndiview-list.txt. Références JNDI des EJBLes références JNDI des EJB peuvent varier de JBoss à Glassfish.Attention le code suivant n'est pas portable :@Stateless(mappedName="fr.esiea_ouest.example1.ejb.TicketDesk") Sources de donnéesBien penser à changer la source de données spécifiées dans persistence.xml quand on passe de JBoss à GlassFish ou inversement. Vérifications LogsLorsqu'on déploie des artefacts (des JAR, des WAR, des EAR), les opérations effectuées sont listées en temps réel dans les logs de l'application. Les causes d'erreurs de non-déploiement (par exemple mauvaise configuration de la persistance cf. section plus loin) ou le fait que les composants ont bien été déployés sont détaillés.Glassfish et JBoss n'ont pas la structure d'arborescence, notamment les fichiers de log sont différents :GlassFish : GLASSFISH_HOME/domains/domain1/logs/server.logJBoss : JBOSS_HOME/server/default/log/server.log VérificateurJEE est fournie avec un outil de vérification des artefacts : verifier. On peut utiliser cet outil sur n'importe quel artefact préalablement à tout déploiement, ça permet d'aller un peu plus vite que l'attente d'un déploiement, mais surtout les résultats de l'analyse du vérificateur sont généralement un peu plus clairs lorsqu'ils sont isolés du reste des logs de l'application.$ JEE_HOME/bin/verifier example-ejb.jar$ JEE_HOME/bin/verifier example-webapp.war$ JEE_HOME/bin/verifier example-application.ear Vérifications dans GlassFishAvec Glassfish il est nécessaire de paramétrer un certain nombre de paramètre dans l'interface d'administration.http://localhost:4848/admin / javaadmin Visiter et vérifier la connexion à la base de données Resources> JDBC> JDBC Resources> jdbc/__defaultStatus : Enabled=> Save Vérifier les paramètres d'auto-déploiement Application Server -> Advanced :Reload : EnabledAuto Deploy : EnabledVerifier : EnabledPrecompile : Enabled=> Save Vider le contenu de la base de données DerbyAvant de supprimer le contenu de la base Derby, il faut s'assurer qu'elle n'est pas utilisée par l'application Glassfish. Une fois arrêtée on peut supprimer son contenu :$ rm -rf /media/cdrom/jee5/databases/*Les structures nécessaires au bon fonctionnement de la base seront créées à nouveau lors du prochain démarrage de la base Derby. Vérifier le contenu de la base de données DerbyAvant de se connecter à la base Derby, il faut s'assurer qu'elle n'est pas démarrée pour être utilisée avec l'application GlassFish. Une fois arrêtée on peut y accéder comme suit : $ export DERBY_HOME=/opt/SDK/javadb/tmp/jee5-databases$ bash /opt/SDK/javadb/bin/ijversion ij 10.2ij> help; Les commandes prises en charge sont les suivantes : PROTOCOL 'protocole JDBC' [ AS identificateur ]; -- définit un protocole par défaut ou indiqué DRIVER 'classe de pilote'; -- charge la classe indiquée CONNECT 'url de la base de données' [ PROTOCOL ProtocoleIndiqué ] [ AS NomDeConnexion ]; -- se connecte à l'URL de la base de données -- et peut affecter un identificateur SET CONNECTION NomDeConnexion; -- bascule vers la connexion indiquée SHOW CONNECTIONS; -- répertorie toutes les connexions AUTOCOMMIT [ ON | OFF ]; -- active ou désactive le mode de validation automatique pour la connexion DISCONNECT [ CURRENT | NomDeConnexion | ALL ]; -- interrompt la connexion en cours, la connexion indiquée ou toutes les connexions; -- la valeur par défaut est CURRENT SHOW SCHEMAS ; -- répertorie tous les schémas de la base de données actuelle SHOW [ TABLES | VIEWS | PROCEDURES | SYNONYMS ] { IN schéma }; ; -- répertorie les tables, les vues, les procédures ou les synonymesij> connect 'jdbc:derby:/opt/SDK/databases/sun-appserv-samples';ij> show tables;TABLE_SCHEM |TABLE_NAME |REMARKS------------------------------------------------------------------------SYS |SYSALIASES |SYS |SYSCHECKS |SYS |SYSCOLPERMS |SYS |SYSCOLUMNS |SYS |SYSCONGLOMERATES |SYS |SYSCONSTRAINTS |SYS |SYSDEPENDS |SYS |SYSFILES |SYS |SYSFOREIGNKEYS |SYS |SYSKEYS |SYS |SYSROUTINEPERMS |SYS |SYSSCHEMAS |SYS |SYSSTATEMENTS |SYS |SYSSTATISTICS |SYS |SYSTABLEPERMS |SYS |SYSTABLES |SYS |SYSTRIGGERS |SYS |SYSVIEWS |SYSIBM |SYSDUMMY1 |APP |SEQUENCE |APP |TICKET |APP |USERACCOUNTBEAN |22 lignes sélectionnéesij> exit;
Documentation de référence en ligne
On pourra s'aider du tutoriel suivant :
Sujets des applications à développer
Chaque étudiant se verra attribuer un sujet parmi les sujets ci-dessous :
Sujet A : Service de passage d'ordres bancaires. L'application doit avoir une notion de client, de compte bancaire (un client peut avoir plusieurs comptes), et permettre de passer des ordres bancaires (virement, achat de titre, vente de titre). Il est demandé à minima de développer une interface web de guichet pour la création et la consultation de compte client, la création de compte bancaire. Ensuite il faudra développer une console de passage d'ordres bancaires qui sera utilisée par les employés de la banque.
Sujet B : Application de réservation de salles sur un seul site. Il doit être possible de créer, supprimer, des salles et de réserver et supprimer des réservations. Il est demandé à minima de créer un frontal web de gestion des salles. Ensuite on s'attachera à créer une interface web de réservation de salles.
Points vérifiés pour la notationLa notation des travaux pratiques s'effectuera pour la plus grande partie de manière automatique par un programme de l'enseignant qui vérifiera les points suivants directement sur les sources récupérées par le biais de Mercurial sur le dépôt de sources de l'étudiant. Génération d'une structure de projet avec MavenSi on dispose de Maven sur son système, on peut générer une structure de projet de manière automatique pour exemple. Par contre on utilisera tout de même Ant pour la génération des livrables pour la compréhension que cela apporte.Pour générer la structure du projet, il faut exécuter la commande ci-dessous. Cela peut prendre longtemps en fonction de la connexion réseau car Maven va récupérer les versions les plus récentes des artefacts. Il peut également être nécessaire de relancer la commande plusieurs fois si certains serveurs coupent les connexions qui prennent trop de temps.$ mvn archetype:generate -DgroupId=fr.esiea_ouest.inf5043.sujet_a -DartifactId=TP_Java_EE -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=falseLe résultat alors obtenu est le suivant :TP_Java_EE
├── pom.xml
└── src
├── main
│ └── java
│ └── fr
│ └── esiea_ouest
│ └── inf5043
│ └── sujet_a
│ └── App.java
└── testOn peut alors lancer la construction des livrables avec la commande suivante :mvn packageLe résultat alors obtenu est le suivant :TP_Java_EE
├── pom.xml
├── src
│ ├── main
│ │ └── java
│ │ └── fr
│ │ └── esiea_ouest
│ │ └── inf5043
│ │ └── sujet_a
│ │ └── App.java
│ └── test
└── target
├── classes
│ └── fr
│ └── esiea_ouest
│ └── inf5043
│ └── sujet_a
│ └── App.class
├── maven-archiver
│ └── pom.properties
└── TP_Java_EE-1.0-SNAPSHOT.jar Arborescence des sources à respecterArborescence type à respecter :Nom_du_projet├── bin│ ├── jeesetallpaths│ ├── jeestart│ └── jeestop├── build.properties├── build.xml├── ChangeLog.txt├── conf│ ├── application.xml│ ├── faces-config.xml│ ├── persistence.xml│ └── web.xml├── dist├── LICENSE.txt├── pom.xml├── README.txt├── src│ └── org│ └── aful│ └── example1│ ├── client│ │ └── Runner.java│ ├── ejb│ │ ├── TicketDeskBean.java│ │ ├── TicketDesk.java│ │ ├── UserAccountBoardBean.java│ │ └── UserAccountBoard.java│ ├── entity│ │ ├── Ticket.java│ │ └── UserAccount.java│ └── server│ ├── CalculatorUiController.java│ ├── ControlServlet.java│ ├── EjbUtil.java│ ├── TestServlet.java│ └── TicketUiController.java└── web ├── calculator.jsp ├── calculator-results.jsp ├── index.jsp ├── ticket-create.jsp ├── ticket-create-servlet.jsp ├── ticket-creation-result.jsp ├── ticket-list.jsp ├── timer-create.jsp ├── user-create.jsp └── user-list.jspLe fichier README.txt doit contenir une première ligne avec le nom et prénom (dans cet ordre) de l'étudiant ou des étudiants, et en deuxième ligne le nom du sujet. Ne pas respecter ce format empêchera le projet d'être reconnu et ne pourra donc pas donner lieu à une note.
Le fichier LICENSE.txt doit contenir le texte de la ou les licences « logiciel libre » choisie(s) pour le projet.
Packages JavaToutes les classes Java doivent avoir un nom de package spécifié. Ce nom doit refléter l'adresse Internet de la structure à laquelle l'auteur appartient.Pour les étudiants de l'ESIEA Paris et de l'ESIEA Ouest à Laval les packages des classes Java doivent commencer respectivement par fr.esiea.inf5043. et fr.esiea_ouest.inf5043.Exemple de code Java à insérer en début d'un fichier .java pour spécifier le package :package fr.esiea_ouest.inf5043.ejb.sujet_aOn notera qu'on ne peut pas utiliser le tiret « - » dans un nom de package. En-têtes des auteurs et des licences des fichiers sourceTous les fichiers sources (particulièrement tous les fichiers qui décrivent l'intelligence du programme, en pratique on néglige souvent les fichiers de configuration n'apportant pas de valeur ajoutée) doivent avoir une en-tête (les premières lignes du fichier) spécifiant les contributeurs du fichier ainsi que la ou les licences de distribution.Pour du code Java et JavaScript l'en-tête sera de la forme suivante :/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * Contributor(s): * M.-A. Darche <ma.darche@aful.org> (Original Author) *
* ***** END LICENSE BLOCK ***** */Pour du code XML l'en-tête sera de la forme suivante (attention de ne pas mettre l'en-tête des auteurs et des licences avant la déclaration XML) :<?xml version='1.0' encoding='UTF-8' ?><!-- * **** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * * Contributor(s): * M.-A. Darche <ma.darche@aful.org> (Original Author) *
* ***** END LICENSE BLOCK ***** -->Et on adaptera ainsi le bloc de licence en fonction de la syntaxe à utiliser pour les commentaires dans chaque type de langage de programmation, chaque type de configuration, etc. Format du fichier de construction Ant à respecterChaque projet doit comporter un fichier de construction Ant : build.xml. Ce fichier build.xml est utilisé pour construire et déployer l'application en dehors de tout environnement graphique interactif.Le fichier build.xml des étudiants devra impérativement comporter les propriétés suivantes pour être facilement portable et testable, notamment sur le système de l'enseignant :<property file="build.properties" /><property name="jee.home" location="XXXX" /><property name="jee.lib" location="YYYY" />Le fichier build.xml devra également avoir toutes les targets fonctionnelles suivantes :prepare (crée les répertoires build et dist si ils n'existent pas)
clean (supprime les répertoires build et dist si ils existent)
war
war-deploy
ejb
ejb-deploy
ear
ear-deploy
build (effectue les tâches war, ejb, ear)
dist (génère le livrable à fournir au professeur à la fin du TP)
La target dist devra générer une archive avec un nom de fichier de la forme suivante :Année_promo-Ville-Nom_étudiant-Nom_sujet.(tar.gz|zip) Sources Java demandéesLes sources de l'application, devront comprendre au moins :une Servlet de test nommée TestServlet
deux classes de type Entity
un Stateless Session Bean
un Stateful Session Bean
une Servlet de service nommée ControlServlet
enchaînement de pages avec JSF
Étapes de la réalisation Développement du projet dans Eclipse Création d'un projet dans EclipseSi le projet existe déjà sur le système de fichiers on procédera comme suit :File -> New -> Java ProjectDécocher « Use default location »
et préciser l'emplacement dans « Location »Sur les anciennes versions d'Eclipse l'assistant de création de projet est un peu différent et on procédera comme suit :File -> New -> Java Project« Create project from existing source »Si le projet Eclipse a été généré à partir de Maven :File -> Import -> General -> Existing Projects into Workspace Définition des bibliothèques pour la compilationLa définition du CLASSPATH est utile pour le bon fonctionnement d'Eclipse, mais il faut définir quelles bibliothèques (library) utiliser pour la compilation (et la vérification au fil de l'eau) du projet.
Définition d'une User Library et ajout de la User Library dans le Build Path du projet :Window -> Preferences -> Java -> Build Path -> User Libraries -> NewJEE -> Add JARs Mise en place des traitements avec AntMise en place des traitements (compilation, déploiement, etc.) en définissant un fichier build.xml utilisé par Ant.PS : Ne pas utiliser les tâches optionnelles de Ant, car le plus souvent obsolètes et/ou non portables.Documentation : http://ant.apache.org/ Création d'une distribution WARCréation d'une archive WAR à l'aide de Ant pour y stocker des Servlets et des JSP.On fera bien attention de ne pas mettre de JAR contenant des EJB dans le WAR. Les seuls JAR autorisés dans le WAR sont des JAR de bibliothèques (par exemple des utilitaires, etc.). Le ou les JAR contenant des EJB doivent être placés dans un EAR.À noter que le tutoriel Java EE contient des exemples de code, notamment des exemples de fichiers web.xml.La spécification complète de Java Platform Enterprise Edition où on pourra trouver la syntaxe des fichiers de configuration XML comme web.xml, application.xml, persistence.xml :http://java.sun.com/javaee/technologies/ Structure du WAR$ unzip -l dist/inf5043-example-1.war META-INF/META-INF/MANIFEST.MFWEB-INF/WEB-INF/web.xmlWEB-INF/classes/WEB-INF/classes/fr/WEB-INF/classes/fr/esiea_ouest/WEB-INF/classes/fr/esiea_ouest/example1/WEB-INF/classes/fr/esiea_ouest/example1/server/WEB-INF/classes/fr/esiea_ouest/example1/server/CalculatorUiController.classWEB-INF/classes/fr/esiea_ouest/example1/server/ControlServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/EjbUtil.classWEB-INF/classes/fr/esiea_ouest/example1/server/TestServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/TicketUiController.classWEB-INF/faces-config.xmlindex.jspticket-create-servlet.jspticket-create.jspticket-creation-result.jspticket-list.jsptimer-create.jspuser-create.jspuser-list.jsp Création de la TestServlet et de JSPCréation et déploiement d'une Servlet et de JSP. On commencera par une Servlet de test (nommée TestServlet) héritant de la classe http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.htmlTestServlet devra juste afficher un message « Bonjour N » avec « N » étant un compteur qui sera incrémenté à chaque rechargement de la page. Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test sera de la forme suivante : http://localhost:8080/inf5043-example-1/testLes correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par deux paramètres :le nom du .war qui va déterminer le nom de l'application web (webapp) juste après l'adresse du serveur d'application (dans l'exemple le war a pour nom inf5043-example-1.war)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Création des distributions JAR et EARCréation d'artefacts JAR et WAR à l'aide de Ant pour y stocker respectivement les Entity, les EJB (Stateless Session Bean et Stateful Session Bean) et les ressources de l'application.
Création des classes EntityCréation au minimum de deux classes Entity. Création du fichier persistence.xml avec définition de la persistence-unit. Création d'un EJB StatelessCréation d'un EJB Stateless qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.war Création d'un EJB StatefulCréation d'un EJB Stateful qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.warLa différence avec l'EJB Stateless viendra du fait que les méthodes de l'EJB Stateful se feront dans le cadre d'un contexte persistant. Création de la ControlServlet communiquant avec les EJB SessionRécupération d'une référence sur les EJB Session par JNDI de manière générique :Context jndiContext = new InitialContext();String refName = BeanInterface.class.getName();BeanInterface beanObject = (BeanInterface) jndiContext.lookup(refName);Exemple de code avec des noms de classes réels :Context jndiContext = new InitialContext();String refName = TicketDesk.class.getName();TicketDesk ticketDesk = (TicketDesk) jndiContext.lookup(refName); Structure de l'EJB JAR$ unzip -l dist/inf5043-example-1-ejb.jar META-INF/META-INF/MANIFEST.MForg/org/aful/org/aful/example1/org/aful/example1/ejb/org/aful/example1/ejb/TicketDesk.classorg/aful/example1/ejb/TicketDeskBean.classorg/aful/example1/ejb/UserAccountBoard.classorg/aful/example1/ejb/UserAccountBoardBean.classorg/aful/example1/entity/org/aful/example1/entity/Ticket.classorg/aful/example1/entity/UserAccount.classMETA-INF/persistence.xml Structure du EAR$ unzip -l dist/inf5043-example-1.ear META-INF/META-INF/MANIFEST.MFMETA-INF/application.xmlaful-example-1-ejb.jaraful-example-1.war Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test deviendra de la forme suivante : http://localhost:8080/project-name/test Ce qui change de la forme précédente qui était : http://localhost:8080/inf5043-example-1/testCeci vient du fait que maintenant les correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par les deux paramètres suivants :le context-root définit dans le fichier application.xml (dans l'exemple le contexte root vaut project-name)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Les correspondances entre les URL et les services déployés (Servlets, JSP) sont définies dans le fichier web.xml et le fichier application.xml. Génération des WebServicesGénération des Web services (en SOAP) pour les EJB Stateless Session à l'aide de l'annotation suivante :@WebMethodSeuls les Stateless Session Beans peuvent implémenter un Web service. Utilisation de JSFUtilisation de JSF pour la génération et la gestion des interactions des pages web. Précisions techniquesCette section décrit l'ensemble des précisions techniques utiles lors de l'utilisation de GlassFish et JBoss. Démarrage/arrêt /déploiement avec serveur d'application JEE Répertoires de déploiementGlassfish et JBoss n'ont pas la même structure d'arborescence, et leur répertoire de déploiement ne se trouve pas au même endroit :GlassFish : GLASSFISH_HOME/domains/domain1/autodeployJBoss : JBOSS_HOME/server/default/deployAussi il faut bien penser à modifier le build.xml lors d'un déploiement avec Ant, selon qu'on déploit sur GlassFish ou JBoss.Lorsque vous avez des erreurs de déploiement au niveau du serveur d'application, pensez bien à supprimer du répertoire de déploiement toutes les versions des JAR ou autres artefacts que vous avez pu déployer. L'idée est d'avoir une situation parfaitement propre avant de déployer quelque chose. Démarrage/arrêt/déploiement avec GlassFish$ cd GLASSFISH_HOME$ bin/asadmin start-domain domain1=> http://localhost:8080/Il est nécessaire de démarrer la base de données Derby embarquée si on souhaite l'utiliser comme c'est notre cas :$ bin/asadmin start-databaseArrêt des services :$ bin/asadmin stop-domain domain1$ bin/asadmin stop-database Permissions et droits d'accèsPour administrer GlassFish il peut être nécessaire de passer sous l'utilisateur glassfish :$ sudo su - glassfishDe plus, pour qu'un utilisateur puisse déployer des artefacts dans GlassFish il est nécessaire qu'il ait les droits nécessaires pour écrire dans le dossier autodeploy de GlassFish. Dans le cadre du TP, uniquement dans le cadre de tests et surtout pas en production, on pourra donc réaliser la manipulation suivante qui compromet la sécurité de l'application mais qui permet le déploiement par tous les utilisateurs :$ sudo su – glassfish
$ chmod a+rwx /opt/java-ee-6/glassfish/domains/domain1/autodeploy Démarrage de JBoss$ cd JBOSS_HOME$ bin/run.sh=> http://localhost:8080/ JNDI service de JBossLe fichier JBOSS_HOME/server/default/conf/jndi.properties doit bien comporter les propriétés suivantes :java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfacesjava.naming.provider.url=jnp://localhost:1099On peut vérifier que les EJB sont bien présents, et avec quel nom, au niveau du service de nommage JNDI à partir de la JMX Console :http://localhost:8080/ -> JMX Console -> service=JNDIView -> java.lang.String list() -> InvokeOn obtient alors une sortie du type de celle incluse dans le fichier jndiview-list.txt. Références JNDI des EJBLes références JNDI des EJB peuvent varier de JBoss à Glassfish.Attention le code suivant n'est pas portable :@Stateless(mappedName="fr.esiea_ouest.example1.ejb.TicketDesk") Sources de donnéesBien penser à changer la source de données spécifiées dans persistence.xml quand on passe de JBoss à GlassFish ou inversement. Vérifications LogsLorsqu'on déploie des artefacts (des JAR, des WAR, des EAR), les opérations effectuées sont listées en temps réel dans les logs de l'application. Les causes d'erreurs de non-déploiement (par exemple mauvaise configuration de la persistance cf. section plus loin) ou le fait que les composants ont bien été déployés sont détaillés.Glassfish et JBoss n'ont pas la structure d'arborescence, notamment les fichiers de log sont différents :GlassFish : GLASSFISH_HOME/domains/domain1/logs/server.logJBoss : JBOSS_HOME/server/default/log/server.log VérificateurJEE est fournie avec un outil de vérification des artefacts : verifier. On peut utiliser cet outil sur n'importe quel artefact préalablement à tout déploiement, ça permet d'aller un peu plus vite que l'attente d'un déploiement, mais surtout les résultats de l'analyse du vérificateur sont généralement un peu plus clairs lorsqu'ils sont isolés du reste des logs de l'application.$ JEE_HOME/bin/verifier example-ejb.jar$ JEE_HOME/bin/verifier example-webapp.war$ JEE_HOME/bin/verifier example-application.ear Vérifications dans GlassFishAvec Glassfish il est nécessaire de paramétrer un certain nombre de paramètre dans l'interface d'administration.http://localhost:4848/admin / javaadmin Visiter et vérifier la connexion à la base de données Resources> JDBC> JDBC Resources> jdbc/__defaultStatus : Enabled=> Save Vérifier les paramètres d'auto-déploiement Application Server -> Advanced :Reload : EnabledAuto Deploy : EnabledVerifier : EnabledPrecompile : Enabled=> Save Vider le contenu de la base de données DerbyAvant de supprimer le contenu de la base Derby, il faut s'assurer qu'elle n'est pas utilisée par l'application Glassfish. Une fois arrêtée on peut supprimer son contenu :$ rm -rf /media/cdrom/jee5/databases/*Les structures nécessaires au bon fonctionnement de la base seront créées à nouveau lors du prochain démarrage de la base Derby. Vérifier le contenu de la base de données DerbyAvant de se connecter à la base Derby, il faut s'assurer qu'elle n'est pas démarrée pour être utilisée avec l'application GlassFish. Une fois arrêtée on peut y accéder comme suit : $ export DERBY_HOME=/opt/SDK/javadb/tmp/jee5-databases$ bash /opt/SDK/javadb/bin/ijversion ij 10.2ij> help; Les commandes prises en charge sont les suivantes : PROTOCOL 'protocole JDBC' [ AS identificateur ]; -- définit un protocole par défaut ou indiqué DRIVER 'classe de pilote'; -- charge la classe indiquée CONNECT 'url de la base de données' [ PROTOCOL ProtocoleIndiqué ] [ AS NomDeConnexion ]; -- se connecte à l'URL de la base de données -- et peut affecter un identificateur SET CONNECTION NomDeConnexion; -- bascule vers la connexion indiquée SHOW CONNECTIONS; -- répertorie toutes les connexions AUTOCOMMIT [ ON | OFF ]; -- active ou désactive le mode de validation automatique pour la connexion DISCONNECT [ CURRENT | NomDeConnexion | ALL ]; -- interrompt la connexion en cours, la connexion indiquée ou toutes les connexions; -- la valeur par défaut est CURRENT SHOW SCHEMAS ; -- répertorie tous les schémas de la base de données actuelle SHOW [ TABLES | VIEWS | PROCEDURES | SYNONYMS ] { IN schéma }; ; -- répertorie les tables, les vues, les procédures ou les synonymesij> connect 'jdbc:derby:/opt/SDK/databases/sun-appserv-samples';ij> show tables;TABLE_SCHEM |TABLE_NAME |REMARKS------------------------------------------------------------------------SYS |SYSALIASES |SYS |SYSCHECKS |SYS |SYSCOLPERMS |SYS |SYSCOLUMNS |SYS |SYSCONGLOMERATES |SYS |SYSCONSTRAINTS |SYS |SYSDEPENDS |SYS |SYSFILES |SYS |SYSFOREIGNKEYS |SYS |SYSKEYS |SYS |SYSROUTINEPERMS |SYS |SYSSCHEMAS |SYS |SYSSTATEMENTS |SYS |SYSSTATISTICS |SYS |SYSTABLEPERMS |SYS |SYSTABLES |SYS |SYSTRIGGERS |SYS |SYSVIEWS |SYSIBM |SYSDUMMY1 |APP |SEQUENCE |APP |TICKET |APP |USERACCOUNTBEAN |22 lignes sélectionnéesij> exit;
Points vérifiés pour la notation
La notation des travaux pratiques s'effectuera pour la plus grande partie de manière automatique par un programme de l'enseignant qui vérifiera les points suivants directement sur les sources récupérées par le biais de Mercurial sur le dépôt de sources de l'étudiant.
Génération d'une structure de projet avec Maven
Si on dispose de Maven sur son système, on peut générer une structure de projet de manière automatique pour exemple. Par contre on utilisera tout de même Ant pour la génération des livrables pour la compréhension que cela apporte.
Pour générer la structure du projet, il faut exécuter la commande ci-dessous. Cela peut prendre longtemps en fonction de la connexion réseau car Maven va récupérer les versions les plus récentes des artefacts. Il peut également être nécessaire de relancer la commande plusieurs fois si certains serveurs coupent les connexions qui prennent trop de temps.
$ mvn archetype:generate -DgroupId=fr.esiea_ouest.inf5043.sujet_a -DartifactId=TP_Java_EE -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
Le résultat alors obtenu est le suivant :
TP_Java_EE
├── pom.xml
└── src
├── main
│ └── java
│ └── fr
│ └── esiea_ouest
│ └── inf5043
│ └── sujet_a
│ └── App.java
└── test
On peut alors lancer la construction des livrables avec la commande suivante :
mvn package
Le résultat alors obtenu est le suivant :
TP_Java_EE
├── pom.xml
├── src
│ ├── main
│ │ └── java
│ │ └── fr
│ │ └── esiea_ouest
│ │ └── inf5043
│ │ └── sujet_a
│ │ └── App.java
│ └── test
└── target
├── classes
│ └── fr
│ └── esiea_ouest
│ └── inf5043
│ └── sujet_a
│ └── App.class
├── maven-archiver
│ └── pom.properties
└── TP_Java_EE-1.0-SNAPSHOT.jar
Arborescence des sources à respecter
Arborescence type à respecter :
Nom_du_projet
├── bin
│ ├── jeesetallpaths
│ ├── jeestart
│ └── jeestop
├── build.properties
├── build.xml
├── ChangeLog.txt
├── conf
│ ├── application.xml
│ ├── faces-config.xml
│ ├── persistence.xml
│ └── web.xml
├── dist
├── LICENSE.txt
├── pom.xml
├── README.txt
├── src
│ └── org
│ └── aful
│ └── example1
│ ├── client
│ │ └── Runner.java
│ ├── ejb
│ │ ├── TicketDeskBean.java
│ │ ├── TicketDesk.java
│ │ ├── UserAccountBoardBean.java
│ │ └── UserAccountBoard.java
│ ├── entity
│ │ ├── Ticket.java
│ │ └── UserAccount.java
│ └── server
│ ├── CalculatorUiController.java
│ ├── ControlServlet.java
│ ├── EjbUtil.java
│ ├── TestServlet.java
│ └── TicketUiController.java
└── web
├── calculator.jsp
├── calculator-results.jsp
├── index.jsp
├── ticket-create.jsp
├── ticket-create-servlet.jsp
├── ticket-creation-result.jsp
├── ticket-list.jsp
├── timer-create.jsp
├── user-create.jsp
└── user-list.jsp
Le fichier README.txt doit contenir une première ligne avec le nom et prénom (dans cet ordre) de l'étudiant ou des étudiants, et en deuxième ligne le nom du sujet. Ne pas respecter ce format empêchera le projet d'être reconnu et ne pourra donc pas donner lieu à une note.
Le fichier LICENSE.txt doit contenir le texte de la ou les licences « logiciel libre » choisie(s) pour le projet.
Packages JavaToutes les classes Java doivent avoir un nom de package spécifié. Ce nom doit refléter l'adresse Internet de la structure à laquelle l'auteur appartient.Pour les étudiants de l'ESIEA Paris et de l'ESIEA Ouest à Laval les packages des classes Java doivent commencer respectivement par fr.esiea.inf5043. et fr.esiea_ouest.inf5043.Exemple de code Java à insérer en début d'un fichier .java pour spécifier le package :package fr.esiea_ouest.inf5043.ejb.sujet_aOn notera qu'on ne peut pas utiliser le tiret « - » dans un nom de package. En-têtes des auteurs et des licences des fichiers sourceTous les fichiers sources (particulièrement tous les fichiers qui décrivent l'intelligence du programme, en pratique on néglige souvent les fichiers de configuration n'apportant pas de valeur ajoutée) doivent avoir une en-tête (les premières lignes du fichier) spécifiant les contributeurs du fichier ainsi que la ou les licences de distribution.Pour du code Java et JavaScript l'en-tête sera de la forme suivante :/* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * Contributor(s): * M.-A. Darche <ma.darche@aful.org> (Original Author) *
* ***** END LICENSE BLOCK ***** */Pour du code XML l'en-tête sera de la forme suivante (attention de ne pas mettre l'en-tête des auteurs et des licences avant la déclaration XML) :<?xml version='1.0' encoding='UTF-8' ?><!-- * **** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * * Contributor(s): * M.-A. Darche <ma.darche@aful.org> (Original Author) *
* ***** END LICENSE BLOCK ***** -->Et on adaptera ainsi le bloc de licence en fonction de la syntaxe à utiliser pour les commentaires dans chaque type de langage de programmation, chaque type de configuration, etc. Format du fichier de construction Ant à respecterChaque projet doit comporter un fichier de construction Ant : build.xml. Ce fichier build.xml est utilisé pour construire et déployer l'application en dehors de tout environnement graphique interactif.Le fichier build.xml des étudiants devra impérativement comporter les propriétés suivantes pour être facilement portable et testable, notamment sur le système de l'enseignant :<property file="build.properties" /><property name="jee.home" location="XXXX" /><property name="jee.lib" location="YYYY" />Le fichier build.xml devra également avoir toutes les targets fonctionnelles suivantes :prepare (crée les répertoires build et dist si ils n'existent pas)
clean (supprime les répertoires build et dist si ils existent)
war
war-deploy
ejb
ejb-deploy
ear
ear-deploy
build (effectue les tâches war, ejb, ear)
dist (génère le livrable à fournir au professeur à la fin du TP)
La target dist devra générer une archive avec un nom de fichier de la forme suivante :Année_promo-Ville-Nom_étudiant-Nom_sujet.(tar.gz|zip) Sources Java demandéesLes sources de l'application, devront comprendre au moins :une Servlet de test nommée TestServlet
deux classes de type Entity
un Stateless Session Bean
un Stateful Session Bean
une Servlet de service nommée ControlServlet
enchaînement de pages avec JSF
Étapes de la réalisation Développement du projet dans Eclipse Création d'un projet dans EclipseSi le projet existe déjà sur le système de fichiers on procédera comme suit :File -> New -> Java ProjectDécocher « Use default location »
et préciser l'emplacement dans « Location »Sur les anciennes versions d'Eclipse l'assistant de création de projet est un peu différent et on procédera comme suit :File -> New -> Java Project« Create project from existing source »Si le projet Eclipse a été généré à partir de Maven :File -> Import -> General -> Existing Projects into Workspace Définition des bibliothèques pour la compilationLa définition du CLASSPATH est utile pour le bon fonctionnement d'Eclipse, mais il faut définir quelles bibliothèques (library) utiliser pour la compilation (et la vérification au fil de l'eau) du projet.
Définition d'une User Library et ajout de la User Library dans le Build Path du projet :Window -> Preferences -> Java -> Build Path -> User Libraries -> NewJEE -> Add JARs Mise en place des traitements avec AntMise en place des traitements (compilation, déploiement, etc.) en définissant un fichier build.xml utilisé par Ant.PS : Ne pas utiliser les tâches optionnelles de Ant, car le plus souvent obsolètes et/ou non portables.Documentation : http://ant.apache.org/ Création d'une distribution WARCréation d'une archive WAR à l'aide de Ant pour y stocker des Servlets et des JSP.On fera bien attention de ne pas mettre de JAR contenant des EJB dans le WAR. Les seuls JAR autorisés dans le WAR sont des JAR de bibliothèques (par exemple des utilitaires, etc.). Le ou les JAR contenant des EJB doivent être placés dans un EAR.À noter que le tutoriel Java EE contient des exemples de code, notamment des exemples de fichiers web.xml.La spécification complète de Java Platform Enterprise Edition où on pourra trouver la syntaxe des fichiers de configuration XML comme web.xml, application.xml, persistence.xml :http://java.sun.com/javaee/technologies/ Structure du WAR$ unzip -l dist/inf5043-example-1.war META-INF/META-INF/MANIFEST.MFWEB-INF/WEB-INF/web.xmlWEB-INF/classes/WEB-INF/classes/fr/WEB-INF/classes/fr/esiea_ouest/WEB-INF/classes/fr/esiea_ouest/example1/WEB-INF/classes/fr/esiea_ouest/example1/server/WEB-INF/classes/fr/esiea_ouest/example1/server/CalculatorUiController.classWEB-INF/classes/fr/esiea_ouest/example1/server/ControlServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/EjbUtil.classWEB-INF/classes/fr/esiea_ouest/example1/server/TestServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/TicketUiController.classWEB-INF/faces-config.xmlindex.jspticket-create-servlet.jspticket-create.jspticket-creation-result.jspticket-list.jsptimer-create.jspuser-create.jspuser-list.jsp Création de la TestServlet et de JSPCréation et déploiement d'une Servlet et de JSP. On commencera par une Servlet de test (nommée TestServlet) héritant de la classe http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.htmlTestServlet devra juste afficher un message « Bonjour N » avec « N » étant un compteur qui sera incrémenté à chaque rechargement de la page. Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test sera de la forme suivante : http://localhost:8080/inf5043-example-1/testLes correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par deux paramètres :le nom du .war qui va déterminer le nom de l'application web (webapp) juste après l'adresse du serveur d'application (dans l'exemple le war a pour nom inf5043-example-1.war)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Création des distributions JAR et EARCréation d'artefacts JAR et WAR à l'aide de Ant pour y stocker respectivement les Entity, les EJB (Stateless Session Bean et Stateful Session Bean) et les ressources de l'application.
Création des classes EntityCréation au minimum de deux classes Entity. Création du fichier persistence.xml avec définition de la persistence-unit. Création d'un EJB StatelessCréation d'un EJB Stateless qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.war Création d'un EJB StatefulCréation d'un EJB Stateful qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.warLa différence avec l'EJB Stateless viendra du fait que les méthodes de l'EJB Stateful se feront dans le cadre d'un contexte persistant. Création de la ControlServlet communiquant avec les EJB SessionRécupération d'une référence sur les EJB Session par JNDI de manière générique :Context jndiContext = new InitialContext();String refName = BeanInterface.class.getName();BeanInterface beanObject = (BeanInterface) jndiContext.lookup(refName);Exemple de code avec des noms de classes réels :Context jndiContext = new InitialContext();String refName = TicketDesk.class.getName();TicketDesk ticketDesk = (TicketDesk) jndiContext.lookup(refName); Structure de l'EJB JAR$ unzip -l dist/inf5043-example-1-ejb.jar META-INF/META-INF/MANIFEST.MForg/org/aful/org/aful/example1/org/aful/example1/ejb/org/aful/example1/ejb/TicketDesk.classorg/aful/example1/ejb/TicketDeskBean.classorg/aful/example1/ejb/UserAccountBoard.classorg/aful/example1/ejb/UserAccountBoardBean.classorg/aful/example1/entity/org/aful/example1/entity/Ticket.classorg/aful/example1/entity/UserAccount.classMETA-INF/persistence.xml Structure du EAR$ unzip -l dist/inf5043-example-1.ear META-INF/META-INF/MANIFEST.MFMETA-INF/application.xmlaful-example-1-ejb.jaraful-example-1.war Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test deviendra de la forme suivante : http://localhost:8080/project-name/test Ce qui change de la forme précédente qui était : http://localhost:8080/inf5043-example-1/testCeci vient du fait que maintenant les correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par les deux paramètres suivants :le context-root définit dans le fichier application.xml (dans l'exemple le contexte root vaut project-name)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Les correspondances entre les URL et les services déployés (Servlets, JSP) sont définies dans le fichier web.xml et le fichier application.xml. Génération des WebServicesGénération des Web services (en SOAP) pour les EJB Stateless Session à l'aide de l'annotation suivante :@WebMethodSeuls les Stateless Session Beans peuvent implémenter un Web service. Utilisation de JSFUtilisation de JSF pour la génération et la gestion des interactions des pages web. Précisions techniquesCette section décrit l'ensemble des précisions techniques utiles lors de l'utilisation de GlassFish et JBoss. Démarrage/arrêt /déploiement avec serveur d'application JEE Répertoires de déploiementGlassfish et JBoss n'ont pas la même structure d'arborescence, et leur répertoire de déploiement ne se trouve pas au même endroit :GlassFish : GLASSFISH_HOME/domains/domain1/autodeployJBoss : JBOSS_HOME/server/default/deployAussi il faut bien penser à modifier le build.xml lors d'un déploiement avec Ant, selon qu'on déploit sur GlassFish ou JBoss.Lorsque vous avez des erreurs de déploiement au niveau du serveur d'application, pensez bien à supprimer du répertoire de déploiement toutes les versions des JAR ou autres artefacts que vous avez pu déployer. L'idée est d'avoir une situation parfaitement propre avant de déployer quelque chose. Démarrage/arrêt/déploiement avec GlassFish$ cd GLASSFISH_HOME$ bin/asadmin start-domain domain1=> http://localhost:8080/Il est nécessaire de démarrer la base de données Derby embarquée si on souhaite l'utiliser comme c'est notre cas :$ bin/asadmin start-databaseArrêt des services :$ bin/asadmin stop-domain domain1$ bin/asadmin stop-database Permissions et droits d'accèsPour administrer GlassFish il peut être nécessaire de passer sous l'utilisateur glassfish :$ sudo su - glassfishDe plus, pour qu'un utilisateur puisse déployer des artefacts dans GlassFish il est nécessaire qu'il ait les droits nécessaires pour écrire dans le dossier autodeploy de GlassFish. Dans le cadre du TP, uniquement dans le cadre de tests et surtout pas en production, on pourra donc réaliser la manipulation suivante qui compromet la sécurité de l'application mais qui permet le déploiement par tous les utilisateurs :$ sudo su – glassfish
$ chmod a+rwx /opt/java-ee-6/glassfish/domains/domain1/autodeploy Démarrage de JBoss$ cd JBOSS_HOME$ bin/run.sh=> http://localhost:8080/ JNDI service de JBossLe fichier JBOSS_HOME/server/default/conf/jndi.properties doit bien comporter les propriétés suivantes :java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfacesjava.naming.provider.url=jnp://localhost:1099On peut vérifier que les EJB sont bien présents, et avec quel nom, au niveau du service de nommage JNDI à partir de la JMX Console :http://localhost:8080/ -> JMX Console -> service=JNDIView -> java.lang.String list() -> InvokeOn obtient alors une sortie du type de celle incluse dans le fichier jndiview-list.txt. Références JNDI des EJBLes références JNDI des EJB peuvent varier de JBoss à Glassfish.Attention le code suivant n'est pas portable :@Stateless(mappedName="fr.esiea_ouest.example1.ejb.TicketDesk") Sources de donnéesBien penser à changer la source de données spécifiées dans persistence.xml quand on passe de JBoss à GlassFish ou inversement. Vérifications LogsLorsqu'on déploie des artefacts (des JAR, des WAR, des EAR), les opérations effectuées sont listées en temps réel dans les logs de l'application. Les causes d'erreurs de non-déploiement (par exemple mauvaise configuration de la persistance cf. section plus loin) ou le fait que les composants ont bien été déployés sont détaillés.Glassfish et JBoss n'ont pas la structure d'arborescence, notamment les fichiers de log sont différents :GlassFish : GLASSFISH_HOME/domains/domain1/logs/server.logJBoss : JBOSS_HOME/server/default/log/server.log VérificateurJEE est fournie avec un outil de vérification des artefacts : verifier. On peut utiliser cet outil sur n'importe quel artefact préalablement à tout déploiement, ça permet d'aller un peu plus vite que l'attente d'un déploiement, mais surtout les résultats de l'analyse du vérificateur sont généralement un peu plus clairs lorsqu'ils sont isolés du reste des logs de l'application.$ JEE_HOME/bin/verifier example-ejb.jar$ JEE_HOME/bin/verifier example-webapp.war$ JEE_HOME/bin/verifier example-application.ear Vérifications dans GlassFishAvec Glassfish il est nécessaire de paramétrer un certain nombre de paramètre dans l'interface d'administration.http://localhost:4848/admin / javaadmin Visiter et vérifier la connexion à la base de données Resources> JDBC> JDBC Resources> jdbc/__defaultStatus : Enabled=> Save Vérifier les paramètres d'auto-déploiement Application Server -> Advanced :Reload : EnabledAuto Deploy : EnabledVerifier : EnabledPrecompile : Enabled=> Save Vider le contenu de la base de données DerbyAvant de supprimer le contenu de la base Derby, il faut s'assurer qu'elle n'est pas utilisée par l'application Glassfish. Une fois arrêtée on peut supprimer son contenu :$ rm -rf /media/cdrom/jee5/databases/*Les structures nécessaires au bon fonctionnement de la base seront créées à nouveau lors du prochain démarrage de la base Derby. Vérifier le contenu de la base de données DerbyAvant de se connecter à la base Derby, il faut s'assurer qu'elle n'est pas démarrée pour être utilisée avec l'application GlassFish. Une fois arrêtée on peut y accéder comme suit : $ export DERBY_HOME=/opt/SDK/javadb/tmp/jee5-databases$ bash /opt/SDK/javadb/bin/ijversion ij 10.2ij> help; Les commandes prises en charge sont les suivantes : PROTOCOL 'protocole JDBC' [ AS identificateur ]; -- définit un protocole par défaut ou indiqué DRIVER 'classe de pilote'; -- charge la classe indiquée CONNECT 'url de la base de données' [ PROTOCOL ProtocoleIndiqué ] [ AS NomDeConnexion ]; -- se connecte à l'URL de la base de données -- et peut affecter un identificateur SET CONNECTION NomDeConnexion; -- bascule vers la connexion indiquée SHOW CONNECTIONS; -- répertorie toutes les connexions AUTOCOMMIT [ ON | OFF ]; -- active ou désactive le mode de validation automatique pour la connexion DISCONNECT [ CURRENT | NomDeConnexion | ALL ]; -- interrompt la connexion en cours, la connexion indiquée ou toutes les connexions; -- la valeur par défaut est CURRENT SHOW SCHEMAS ; -- répertorie tous les schémas de la base de données actuelle SHOW [ TABLES | VIEWS | PROCEDURES | SYNONYMS ] { IN schéma }; ; -- répertorie les tables, les vues, les procédures ou les synonymesij> connect 'jdbc:derby:/opt/SDK/databases/sun-appserv-samples';ij> show tables;TABLE_SCHEM |TABLE_NAME |REMARKS------------------------------------------------------------------------SYS |SYSALIASES |SYS |SYSCHECKS |SYS |SYSCOLPERMS |SYS |SYSCOLUMNS |SYS |SYSCONGLOMERATES |SYS |SYSCONSTRAINTS |SYS |SYSDEPENDS |SYS |SYSFILES |SYS |SYSFOREIGNKEYS |SYS |SYSKEYS |SYS |SYSROUTINEPERMS |SYS |SYSSCHEMAS |SYS |SYSSTATEMENTS |SYS |SYSSTATISTICS |SYS |SYSTABLEPERMS |SYS |SYSTABLES |SYS |SYSTRIGGERS |SYS |SYSVIEWS |SYSIBM |SYSDUMMY1 |APP |SEQUENCE |APP |TICKET |APP |USERACCOUNTBEAN |22 lignes sélectionnéesij> exit;
Packages Java
Toutes les classes Java doivent avoir un nom de package spécifié. Ce nom doit refléter l'adresse Internet de la structure à laquelle l'auteur appartient.
Pour les étudiants de l'ESIEA Paris et de l'ESIEA Ouest à Laval les packages des classes Java doivent commencer respectivement par fr.esiea.inf5043. et fr.esiea_ouest.inf5043.
Exemple de code Java à insérer en début d'un fichier .java pour spécifier le package :
package fr.esiea_ouest.inf5043.ejb.sujet_a
On notera qu'on ne peut pas utiliser le tiret « - » dans un nom de package.
En-têtes des auteurs et des licences des fichiers source
Tous les fichiers sources (particulièrement tous les fichiers qui décrivent l'intelligence du programme, en pratique on néglige souvent les fichiers de configuration n'apportant pas de valeur ajoutée) doivent avoir une en-tête (les premières lignes du fichier) spécifiant les contributeurs du fichier ainsi que la ou les licences de distribution.
Pour du code Java et JavaScript l'en-tête sera de la forme suivante :
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* Contributor(s):
* M.-A. Darche <ma.darche@aful.org> (Original Author)
*
* ***** END LICENSE BLOCK ***** */
Pour du code XML l'en-tête sera de la forme suivante (attention de ne pas mettre l'en-tête des auteurs et des licences avant la déclaration XML) :
<?xml version='1.0' encoding='UTF-8' ?>
<!--
* **** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
*
* Contributor(s):
* M.-A. Darche <ma.darche@aful.org> (Original Author)
*
* ***** END LICENSE BLOCK *****
-->
Et on adaptera ainsi le bloc de licence en fonction de la syntaxe à utiliser pour les commentaires dans chaque type de langage de programmation, chaque type de configuration, etc.
Format du fichier de construction Ant à respecter
Chaque projet doit comporter un fichier de construction Ant : build.xml. Ce fichier build.xml est utilisé pour construire et déployer l'application en dehors de tout environnement graphique interactif.
Le fichier build.xml des étudiants devra impérativement comporter les propriétés suivantes pour être facilement portable et testable, notamment sur le système de l'enseignant :
<property file="build.properties" />
<property name="jee.home" location="XXXX" />
<property name="jee.lib" location="YYYY" />
Le fichier build.xml devra également avoir toutes les targets fonctionnelles suivantes :
prepare (crée les répertoires build et dist si ils n'existent pas)
clean (supprime les répertoires build et dist si ils existent)
war
war-deploy
ejb
ejb-deploy
ear
ear-deploy
build (effectue les tâches war, ejb, ear)
dist (génère le livrable à fournir au professeur à la fin du TP)
La target dist devra générer une archive avec un nom de fichier de la forme suivante :Année_promo-Ville-Nom_étudiant-Nom_sujet.(tar.gz|zip) Sources Java demandéesLes sources de l'application, devront comprendre au moins :une Servlet de test nommée TestServlet
deux classes de type Entity
un Stateless Session Bean
un Stateful Session Bean
une Servlet de service nommée ControlServlet
enchaînement de pages avec JSF
Étapes de la réalisation Développement du projet dans Eclipse Création d'un projet dans EclipseSi le projet existe déjà sur le système de fichiers on procédera comme suit :File -> New -> Java ProjectDécocher « Use default location »
et préciser l'emplacement dans « Location »Sur les anciennes versions d'Eclipse l'assistant de création de projet est un peu différent et on procédera comme suit :File -> New -> Java Project« Create project from existing source »Si le projet Eclipse a été généré à partir de Maven :File -> Import -> General -> Existing Projects into Workspace Définition des bibliothèques pour la compilationLa définition du CLASSPATH est utile pour le bon fonctionnement d'Eclipse, mais il faut définir quelles bibliothèques (library) utiliser pour la compilation (et la vérification au fil de l'eau) du projet.
Définition d'une User Library et ajout de la User Library dans le Build Path du projet :Window -> Preferences -> Java -> Build Path -> User Libraries -> NewJEE -> Add JARs Mise en place des traitements avec AntMise en place des traitements (compilation, déploiement, etc.) en définissant un fichier build.xml utilisé par Ant.PS : Ne pas utiliser les tâches optionnelles de Ant, car le plus souvent obsolètes et/ou non portables.Documentation : http://ant.apache.org/ Création d'une distribution WARCréation d'une archive WAR à l'aide de Ant pour y stocker des Servlets et des JSP.On fera bien attention de ne pas mettre de JAR contenant des EJB dans le WAR. Les seuls JAR autorisés dans le WAR sont des JAR de bibliothèques (par exemple des utilitaires, etc.). Le ou les JAR contenant des EJB doivent être placés dans un EAR.À noter que le tutoriel Java EE contient des exemples de code, notamment des exemples de fichiers web.xml.La spécification complète de Java Platform Enterprise Edition où on pourra trouver la syntaxe des fichiers de configuration XML comme web.xml, application.xml, persistence.xml :http://java.sun.com/javaee/technologies/ Structure du WAR$ unzip -l dist/inf5043-example-1.war META-INF/META-INF/MANIFEST.MFWEB-INF/WEB-INF/web.xmlWEB-INF/classes/WEB-INF/classes/fr/WEB-INF/classes/fr/esiea_ouest/WEB-INF/classes/fr/esiea_ouest/example1/WEB-INF/classes/fr/esiea_ouest/example1/server/WEB-INF/classes/fr/esiea_ouest/example1/server/CalculatorUiController.classWEB-INF/classes/fr/esiea_ouest/example1/server/ControlServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/EjbUtil.classWEB-INF/classes/fr/esiea_ouest/example1/server/TestServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/TicketUiController.classWEB-INF/faces-config.xmlindex.jspticket-create-servlet.jspticket-create.jspticket-creation-result.jspticket-list.jsptimer-create.jspuser-create.jspuser-list.jsp Création de la TestServlet et de JSPCréation et déploiement d'une Servlet et de JSP. On commencera par une Servlet de test (nommée TestServlet) héritant de la classe http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.htmlTestServlet devra juste afficher un message « Bonjour N » avec « N » étant un compteur qui sera incrémenté à chaque rechargement de la page. Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test sera de la forme suivante : http://localhost:8080/inf5043-example-1/testLes correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par deux paramètres :le nom du .war qui va déterminer le nom de l'application web (webapp) juste après l'adresse du serveur d'application (dans l'exemple le war a pour nom inf5043-example-1.war)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Création des distributions JAR et EARCréation d'artefacts JAR et WAR à l'aide de Ant pour y stocker respectivement les Entity, les EJB (Stateless Session Bean et Stateful Session Bean) et les ressources de l'application.
Création des classes EntityCréation au minimum de deux classes Entity. Création du fichier persistence.xml avec définition de la persistence-unit. Création d'un EJB StatelessCréation d'un EJB Stateless qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.war Création d'un EJB StatefulCréation d'un EJB Stateful qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.warLa différence avec l'EJB Stateless viendra du fait que les méthodes de l'EJB Stateful se feront dans le cadre d'un contexte persistant. Création de la ControlServlet communiquant avec les EJB SessionRécupération d'une référence sur les EJB Session par JNDI de manière générique :Context jndiContext = new InitialContext();String refName = BeanInterface.class.getName();BeanInterface beanObject = (BeanInterface) jndiContext.lookup(refName);Exemple de code avec des noms de classes réels :Context jndiContext = new InitialContext();String refName = TicketDesk.class.getName();TicketDesk ticketDesk = (TicketDesk) jndiContext.lookup(refName); Structure de l'EJB JAR$ unzip -l dist/inf5043-example-1-ejb.jar META-INF/META-INF/MANIFEST.MForg/org/aful/org/aful/example1/org/aful/example1/ejb/org/aful/example1/ejb/TicketDesk.classorg/aful/example1/ejb/TicketDeskBean.classorg/aful/example1/ejb/UserAccountBoard.classorg/aful/example1/ejb/UserAccountBoardBean.classorg/aful/example1/entity/org/aful/example1/entity/Ticket.classorg/aful/example1/entity/UserAccount.classMETA-INF/persistence.xml Structure du EAR$ unzip -l dist/inf5043-example-1.ear META-INF/META-INF/MANIFEST.MFMETA-INF/application.xmlaful-example-1-ejb.jaraful-example-1.war Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test deviendra de la forme suivante : http://localhost:8080/project-name/test Ce qui change de la forme précédente qui était : http://localhost:8080/inf5043-example-1/testCeci vient du fait que maintenant les correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par les deux paramètres suivants :le context-root définit dans le fichier application.xml (dans l'exemple le contexte root vaut project-name)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Les correspondances entre les URL et les services déployés (Servlets, JSP) sont définies dans le fichier web.xml et le fichier application.xml. Génération des WebServicesGénération des Web services (en SOAP) pour les EJB Stateless Session à l'aide de l'annotation suivante :@WebMethodSeuls les Stateless Session Beans peuvent implémenter un Web service. Utilisation de JSFUtilisation de JSF pour la génération et la gestion des interactions des pages web. Précisions techniquesCette section décrit l'ensemble des précisions techniques utiles lors de l'utilisation de GlassFish et JBoss. Démarrage/arrêt /déploiement avec serveur d'application JEE Répertoires de déploiementGlassfish et JBoss n'ont pas la même structure d'arborescence, et leur répertoire de déploiement ne se trouve pas au même endroit :GlassFish : GLASSFISH_HOME/domains/domain1/autodeployJBoss : JBOSS_HOME/server/default/deployAussi il faut bien penser à modifier le build.xml lors d'un déploiement avec Ant, selon qu'on déploit sur GlassFish ou JBoss.Lorsque vous avez des erreurs de déploiement au niveau du serveur d'application, pensez bien à supprimer du répertoire de déploiement toutes les versions des JAR ou autres artefacts que vous avez pu déployer. L'idée est d'avoir une situation parfaitement propre avant de déployer quelque chose. Démarrage/arrêt/déploiement avec GlassFish$ cd GLASSFISH_HOME$ bin/asadmin start-domain domain1=> http://localhost:8080/Il est nécessaire de démarrer la base de données Derby embarquée si on souhaite l'utiliser comme c'est notre cas :$ bin/asadmin start-databaseArrêt des services :$ bin/asadmin stop-domain domain1$ bin/asadmin stop-database Permissions et droits d'accèsPour administrer GlassFish il peut être nécessaire de passer sous l'utilisateur glassfish :$ sudo su - glassfishDe plus, pour qu'un utilisateur puisse déployer des artefacts dans GlassFish il est nécessaire qu'il ait les droits nécessaires pour écrire dans le dossier autodeploy de GlassFish. Dans le cadre du TP, uniquement dans le cadre de tests et surtout pas en production, on pourra donc réaliser la manipulation suivante qui compromet la sécurité de l'application mais qui permet le déploiement par tous les utilisateurs :$ sudo su – glassfish
$ chmod a+rwx /opt/java-ee-6/glassfish/domains/domain1/autodeploy Démarrage de JBoss$ cd JBOSS_HOME$ bin/run.sh=> http://localhost:8080/ JNDI service de JBossLe fichier JBOSS_HOME/server/default/conf/jndi.properties doit bien comporter les propriétés suivantes :java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfacesjava.naming.provider.url=jnp://localhost:1099On peut vérifier que les EJB sont bien présents, et avec quel nom, au niveau du service de nommage JNDI à partir de la JMX Console :http://localhost:8080/ -> JMX Console -> service=JNDIView -> java.lang.String list() -> InvokeOn obtient alors une sortie du type de celle incluse dans le fichier jndiview-list.txt. Références JNDI des EJBLes références JNDI des EJB peuvent varier de JBoss à Glassfish.Attention le code suivant n'est pas portable :@Stateless(mappedName="fr.esiea_ouest.example1.ejb.TicketDesk") Sources de donnéesBien penser à changer la source de données spécifiées dans persistence.xml quand on passe de JBoss à GlassFish ou inversement. Vérifications LogsLorsqu'on déploie des artefacts (des JAR, des WAR, des EAR), les opérations effectuées sont listées en temps réel dans les logs de l'application. Les causes d'erreurs de non-déploiement (par exemple mauvaise configuration de la persistance cf. section plus loin) ou le fait que les composants ont bien été déployés sont détaillés.Glassfish et JBoss n'ont pas la structure d'arborescence, notamment les fichiers de log sont différents :GlassFish : GLASSFISH_HOME/domains/domain1/logs/server.logJBoss : JBOSS_HOME/server/default/log/server.log VérificateurJEE est fournie avec un outil de vérification des artefacts : verifier. On peut utiliser cet outil sur n'importe quel artefact préalablement à tout déploiement, ça permet d'aller un peu plus vite que l'attente d'un déploiement, mais surtout les résultats de l'analyse du vérificateur sont généralement un peu plus clairs lorsqu'ils sont isolés du reste des logs de l'application.$ JEE_HOME/bin/verifier example-ejb.jar$ JEE_HOME/bin/verifier example-webapp.war$ JEE_HOME/bin/verifier example-application.ear Vérifications dans GlassFishAvec Glassfish il est nécessaire de paramétrer un certain nombre de paramètre dans l'interface d'administration.http://localhost:4848/admin / javaadmin Visiter et vérifier la connexion à la base de données Resources> JDBC> JDBC Resources> jdbc/__defaultStatus : Enabled=> Save Vérifier les paramètres d'auto-déploiement Application Server -> Advanced :Reload : EnabledAuto Deploy : EnabledVerifier : EnabledPrecompile : Enabled=> Save Vider le contenu de la base de données DerbyAvant de supprimer le contenu de la base Derby, il faut s'assurer qu'elle n'est pas utilisée par l'application Glassfish. Une fois arrêtée on peut supprimer son contenu :$ rm -rf /media/cdrom/jee5/databases/*Les structures nécessaires au bon fonctionnement de la base seront créées à nouveau lors du prochain démarrage de la base Derby. Vérifier le contenu de la base de données DerbyAvant de se connecter à la base Derby, il faut s'assurer qu'elle n'est pas démarrée pour être utilisée avec l'application GlassFish. Une fois arrêtée on peut y accéder comme suit : $ export DERBY_HOME=/opt/SDK/javadb/tmp/jee5-databases$ bash /opt/SDK/javadb/bin/ijversion ij 10.2ij> help; Les commandes prises en charge sont les suivantes : PROTOCOL 'protocole JDBC' [ AS identificateur ]; -- définit un protocole par défaut ou indiqué DRIVER 'classe de pilote'; -- charge la classe indiquée CONNECT 'url de la base de données' [ PROTOCOL ProtocoleIndiqué ] [ AS NomDeConnexion ]; -- se connecte à l'URL de la base de données -- et peut affecter un identificateur SET CONNECTION NomDeConnexion; -- bascule vers la connexion indiquée SHOW CONNECTIONS; -- répertorie toutes les connexions AUTOCOMMIT [ ON | OFF ]; -- active ou désactive le mode de validation automatique pour la connexion DISCONNECT [ CURRENT | NomDeConnexion | ALL ]; -- interrompt la connexion en cours, la connexion indiquée ou toutes les connexions; -- la valeur par défaut est CURRENT SHOW SCHEMAS ; -- répertorie tous les schémas de la base de données actuelle SHOW [ TABLES | VIEWS | PROCEDURES | SYNONYMS ] { IN schéma }; ; -- répertorie les tables, les vues, les procédures ou les synonymesij> connect 'jdbc:derby:/opt/SDK/databases/sun-appserv-samples';ij> show tables;TABLE_SCHEM |TABLE_NAME |REMARKS------------------------------------------------------------------------SYS |SYSALIASES |SYS |SYSCHECKS |SYS |SYSCOLPERMS |SYS |SYSCOLUMNS |SYS |SYSCONGLOMERATES |SYS |SYSCONSTRAINTS |SYS |SYSDEPENDS |SYS |SYSFILES |SYS |SYSFOREIGNKEYS |SYS |SYSKEYS |SYS |SYSROUTINEPERMS |SYS |SYSSCHEMAS |SYS |SYSSTATEMENTS |SYS |SYSSTATISTICS |SYS |SYSTABLEPERMS |SYS |SYSTABLES |SYS |SYSTRIGGERS |SYS |SYSVIEWS |SYSIBM |SYSDUMMY1 |APP |SEQUENCE |APP |TICKET |APP |USERACCOUNTBEAN |22 lignes sélectionnéesij> exit;
La target dist devra générer une archive avec un nom de fichier de la forme suivante :
Année_promo-Ville-Nom_étudiant-Nom_sujet.(tar.gz|zip)
Sources Java demandées
Les sources de l'application, devront comprendre au moins :
une Servlet de test nommée TestServlet
deux classes de type Entity
un Stateless Session Bean
un Stateful Session Bean
une Servlet de service nommée ControlServlet
enchaînement de pages avec JSF
Étapes de la réalisation Développement du projet dans Eclipse Création d'un projet dans EclipseSi le projet existe déjà sur le système de fichiers on procédera comme suit :File -> New -> Java ProjectDécocher « Use default location »
et préciser l'emplacement dans « Location »Sur les anciennes versions d'Eclipse l'assistant de création de projet est un peu différent et on procédera comme suit :File -> New -> Java Project« Create project from existing source »Si le projet Eclipse a été généré à partir de Maven :File -> Import -> General -> Existing Projects into Workspace Définition des bibliothèques pour la compilationLa définition du CLASSPATH est utile pour le bon fonctionnement d'Eclipse, mais il faut définir quelles bibliothèques (library) utiliser pour la compilation (et la vérification au fil de l'eau) du projet.
Définition d'une User Library et ajout de la User Library dans le Build Path du projet :Window -> Preferences -> Java -> Build Path -> User Libraries -> NewJEE -> Add JARs Mise en place des traitements avec AntMise en place des traitements (compilation, déploiement, etc.) en définissant un fichier build.xml utilisé par Ant.PS : Ne pas utiliser les tâches optionnelles de Ant, car le plus souvent obsolètes et/ou non portables.Documentation : http://ant.apache.org/ Création d'une distribution WARCréation d'une archive WAR à l'aide de Ant pour y stocker des Servlets et des JSP.On fera bien attention de ne pas mettre de JAR contenant des EJB dans le WAR. Les seuls JAR autorisés dans le WAR sont des JAR de bibliothèques (par exemple des utilitaires, etc.). Le ou les JAR contenant des EJB doivent être placés dans un EAR.À noter que le tutoriel Java EE contient des exemples de code, notamment des exemples de fichiers web.xml.La spécification complète de Java Platform Enterprise Edition où on pourra trouver la syntaxe des fichiers de configuration XML comme web.xml, application.xml, persistence.xml :http://java.sun.com/javaee/technologies/ Structure du WAR$ unzip -l dist/inf5043-example-1.war META-INF/META-INF/MANIFEST.MFWEB-INF/WEB-INF/web.xmlWEB-INF/classes/WEB-INF/classes/fr/WEB-INF/classes/fr/esiea_ouest/WEB-INF/classes/fr/esiea_ouest/example1/WEB-INF/classes/fr/esiea_ouest/example1/server/WEB-INF/classes/fr/esiea_ouest/example1/server/CalculatorUiController.classWEB-INF/classes/fr/esiea_ouest/example1/server/ControlServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/EjbUtil.classWEB-INF/classes/fr/esiea_ouest/example1/server/TestServlet.classWEB-INF/classes/fr/esiea_ouest/example1/server/TicketUiController.classWEB-INF/faces-config.xmlindex.jspticket-create-servlet.jspticket-create.jspticket-creation-result.jspticket-list.jsptimer-create.jspuser-create.jspuser-list.jsp Création de la TestServlet et de JSPCréation et déploiement d'une Servlet et de JSP. On commencera par une Servlet de test (nommée TestServlet) héritant de la classe http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.htmlTestServlet devra juste afficher un message « Bonjour N » avec « N » étant un compteur qui sera incrémenté à chaque rechargement de la page. Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test sera de la forme suivante : http://localhost:8080/inf5043-example-1/testLes correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par deux paramètres :le nom du .war qui va déterminer le nom de l'application web (webapp) juste après l'adresse du serveur d'application (dans l'exemple le war a pour nom inf5043-example-1.war)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Création des distributions JAR et EARCréation d'artefacts JAR et WAR à l'aide de Ant pour y stocker respectivement les Entity, les EJB (Stateless Session Bean et Stateful Session Bean) et les ressources de l'application.
Création des classes EntityCréation au minimum de deux classes Entity. Création du fichier persistence.xml avec définition de la persistence-unit. Création d'un EJB StatelessCréation d'un EJB Stateless qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.war Création d'un EJB StatefulCréation d'un EJB Stateful qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.warLa différence avec l'EJB Stateless viendra du fait que les méthodes de l'EJB Stateful se feront dans le cadre d'un contexte persistant. Création de la ControlServlet communiquant avec les EJB SessionRécupération d'une référence sur les EJB Session par JNDI de manière générique :Context jndiContext = new InitialContext();String refName = BeanInterface.class.getName();BeanInterface beanObject = (BeanInterface) jndiContext.lookup(refName);Exemple de code avec des noms de classes réels :Context jndiContext = new InitialContext();String refName = TicketDesk.class.getName();TicketDesk ticketDesk = (TicketDesk) jndiContext.lookup(refName); Structure de l'EJB JAR$ unzip -l dist/inf5043-example-1-ejb.jar META-INF/META-INF/MANIFEST.MForg/org/aful/org/aful/example1/org/aful/example1/ejb/org/aful/example1/ejb/TicketDesk.classorg/aful/example1/ejb/TicketDeskBean.classorg/aful/example1/ejb/UserAccountBoard.classorg/aful/example1/ejb/UserAccountBoardBean.classorg/aful/example1/entity/org/aful/example1/entity/Ticket.classorg/aful/example1/entity/UserAccount.classMETA-INF/persistence.xml Structure du EAR$ unzip -l dist/inf5043-example-1.ear META-INF/META-INF/MANIFEST.MFMETA-INF/application.xmlaful-example-1-ejb.jaraful-example-1.war Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test deviendra de la forme suivante : http://localhost:8080/project-name/test Ce qui change de la forme précédente qui était : http://localhost:8080/inf5043-example-1/testCeci vient du fait que maintenant les correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par les deux paramètres suivants :le context-root définit dans le fichier application.xml (dans l'exemple le contexte root vaut project-name)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Les correspondances entre les URL et les services déployés (Servlets, JSP) sont définies dans le fichier web.xml et le fichier application.xml. Génération des WebServicesGénération des Web services (en SOAP) pour les EJB Stateless Session à l'aide de l'annotation suivante :@WebMethodSeuls les Stateless Session Beans peuvent implémenter un Web service. Utilisation de JSFUtilisation de JSF pour la génération et la gestion des interactions des pages web. Précisions techniquesCette section décrit l'ensemble des précisions techniques utiles lors de l'utilisation de GlassFish et JBoss. Démarrage/arrêt /déploiement avec serveur d'application JEE Répertoires de déploiementGlassfish et JBoss n'ont pas la même structure d'arborescence, et leur répertoire de déploiement ne se trouve pas au même endroit :GlassFish : GLASSFISH_HOME/domains/domain1/autodeployJBoss : JBOSS_HOME/server/default/deployAussi il faut bien penser à modifier le build.xml lors d'un déploiement avec Ant, selon qu'on déploit sur GlassFish ou JBoss.Lorsque vous avez des erreurs de déploiement au niveau du serveur d'application, pensez bien à supprimer du répertoire de déploiement toutes les versions des JAR ou autres artefacts que vous avez pu déployer. L'idée est d'avoir une situation parfaitement propre avant de déployer quelque chose. Démarrage/arrêt/déploiement avec GlassFish$ cd GLASSFISH_HOME$ bin/asadmin start-domain domain1=> http://localhost:8080/Il est nécessaire de démarrer la base de données Derby embarquée si on souhaite l'utiliser comme c'est notre cas :$ bin/asadmin start-databaseArrêt des services :$ bin/asadmin stop-domain domain1$ bin/asadmin stop-database Permissions et droits d'accèsPour administrer GlassFish il peut être nécessaire de passer sous l'utilisateur glassfish :$ sudo su - glassfishDe plus, pour qu'un utilisateur puisse déployer des artefacts dans GlassFish il est nécessaire qu'il ait les droits nécessaires pour écrire dans le dossier autodeploy de GlassFish. Dans le cadre du TP, uniquement dans le cadre de tests et surtout pas en production, on pourra donc réaliser la manipulation suivante qui compromet la sécurité de l'application mais qui permet le déploiement par tous les utilisateurs :$ sudo su – glassfish
$ chmod a+rwx /opt/java-ee-6/glassfish/domains/domain1/autodeploy Démarrage de JBoss$ cd JBOSS_HOME$ bin/run.sh=> http://localhost:8080/ JNDI service de JBossLe fichier JBOSS_HOME/server/default/conf/jndi.properties doit bien comporter les propriétés suivantes :java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfacesjava.naming.provider.url=jnp://localhost:1099On peut vérifier que les EJB sont bien présents, et avec quel nom, au niveau du service de nommage JNDI à partir de la JMX Console :http://localhost:8080/ -> JMX Console -> service=JNDIView -> java.lang.String list() -> InvokeOn obtient alors une sortie du type de celle incluse dans le fichier jndiview-list.txt. Références JNDI des EJBLes références JNDI des EJB peuvent varier de JBoss à Glassfish.Attention le code suivant n'est pas portable :@Stateless(mappedName="fr.esiea_ouest.example1.ejb.TicketDesk") Sources de donnéesBien penser à changer la source de données spécifiées dans persistence.xml quand on passe de JBoss à GlassFish ou inversement. Vérifications LogsLorsqu'on déploie des artefacts (des JAR, des WAR, des EAR), les opérations effectuées sont listées en temps réel dans les logs de l'application. Les causes d'erreurs de non-déploiement (par exemple mauvaise configuration de la persistance cf. section plus loin) ou le fait que les composants ont bien été déployés sont détaillés.Glassfish et JBoss n'ont pas la structure d'arborescence, notamment les fichiers de log sont différents :GlassFish : GLASSFISH_HOME/domains/domain1/logs/server.logJBoss : JBOSS_HOME/server/default/log/server.log VérificateurJEE est fournie avec un outil de vérification des artefacts : verifier. On peut utiliser cet outil sur n'importe quel artefact préalablement à tout déploiement, ça permet d'aller un peu plus vite que l'attente d'un déploiement, mais surtout les résultats de l'analyse du vérificateur sont généralement un peu plus clairs lorsqu'ils sont isolés du reste des logs de l'application.$ JEE_HOME/bin/verifier example-ejb.jar$ JEE_HOME/bin/verifier example-webapp.war$ JEE_HOME/bin/verifier example-application.ear Vérifications dans GlassFishAvec Glassfish il est nécessaire de paramétrer un certain nombre de paramètre dans l'interface d'administration.http://localhost:4848/admin / javaadmin Visiter et vérifier la connexion à la base de données Resources> JDBC> JDBC Resources> jdbc/__defaultStatus : Enabled=> Save Vérifier les paramètres d'auto-déploiement Application Server -> Advanced :Reload : EnabledAuto Deploy : EnabledVerifier : EnabledPrecompile : Enabled=> Save Vider le contenu de la base de données DerbyAvant de supprimer le contenu de la base Derby, il faut s'assurer qu'elle n'est pas utilisée par l'application Glassfish. Une fois arrêtée on peut supprimer son contenu :$ rm -rf /media/cdrom/jee5/databases/*Les structures nécessaires au bon fonctionnement de la base seront créées à nouveau lors du prochain démarrage de la base Derby. Vérifier le contenu de la base de données DerbyAvant de se connecter à la base Derby, il faut s'assurer qu'elle n'est pas démarrée pour être utilisée avec l'application GlassFish. Une fois arrêtée on peut y accéder comme suit : $ export DERBY_HOME=/opt/SDK/javadb/tmp/jee5-databases$ bash /opt/SDK/javadb/bin/ijversion ij 10.2ij> help; Les commandes prises en charge sont les suivantes : PROTOCOL 'protocole JDBC' [ AS identificateur ]; -- définit un protocole par défaut ou indiqué DRIVER 'classe de pilote'; -- charge la classe indiquée CONNECT 'url de la base de données' [ PROTOCOL ProtocoleIndiqué ] [ AS NomDeConnexion ]; -- se connecte à l'URL de la base de données -- et peut affecter un identificateur SET CONNECTION NomDeConnexion; -- bascule vers la connexion indiquée SHOW CONNECTIONS; -- répertorie toutes les connexions AUTOCOMMIT [ ON | OFF ]; -- active ou désactive le mode de validation automatique pour la connexion DISCONNECT [ CURRENT | NomDeConnexion | ALL ]; -- interrompt la connexion en cours, la connexion indiquée ou toutes les connexions; -- la valeur par défaut est CURRENT SHOW SCHEMAS ; -- répertorie tous les schémas de la base de données actuelle SHOW [ TABLES | VIEWS | PROCEDURES | SYNONYMS ] { IN schéma }; ; -- répertorie les tables, les vues, les procédures ou les synonymesij> connect 'jdbc:derby:/opt/SDK/databases/sun-appserv-samples';ij> show tables;TABLE_SCHEM |TABLE_NAME |REMARKS------------------------------------------------------------------------SYS |SYSALIASES |SYS |SYSCHECKS |SYS |SYSCOLPERMS |SYS |SYSCOLUMNS |SYS |SYSCONGLOMERATES |SYS |SYSCONSTRAINTS |SYS |SYSDEPENDS |SYS |SYSFILES |SYS |SYSFOREIGNKEYS |SYS |SYSKEYS |SYS |SYSROUTINEPERMS |SYS |SYSSCHEMAS |SYS |SYSSTATEMENTS |SYS |SYSSTATISTICS |SYS |SYSTABLEPERMS |SYS |SYSTABLES |SYS |SYSTRIGGERS |SYS |SYSVIEWS |SYSIBM |SYSDUMMY1 |APP |SEQUENCE |APP |TICKET |APP |USERACCOUNTBEAN |22 lignes sélectionnéesij> exit;
Étapes de la réalisation
Développement du projet dans Eclipse
Création d'un projet dans Eclipse
Si le projet existe déjà sur le système de fichiers on procédera comme suit :
File -> New -> Java Project
Décocher « Use default location »
et préciser l'emplacement dans « Location »
Sur les anciennes versions d'Eclipse l'assistant de création de projet est un peu différent et on procédera comme suit :
File -> New -> Java Project
« Create project from existing source »
Si le projet Eclipse a été généré à partir de Maven :
File -> Import -> General -> Existing Projects into Workspace
Définition des bibliothèques pour la compilation
La définition du CLASSPATH est utile pour le bon fonctionnement d'Eclipse, mais il faut définir quelles bibliothèques (library) utiliser pour la compilation (et la vérification au fil de l'eau) du projet.
Définition d'une User Library et ajout de la User Library dans le Build Path du projet :
Window -> Preferences -> Java -> Build Path -> User Libraries -> New
JEE -> Add JARs
Mise en place des traitements avec Ant
Mise en place des traitements (compilation, déploiement, etc.) en définissant un fichier build.xml utilisé par Ant.
PS : Ne pas utiliser les tâches optionnelles de Ant, car le plus souvent obsolètes et/ou non portables.
Création d'une distribution WAR
Création d'une archive WAR à l'aide de Ant pour y stocker des Servlets et des JSP.
On fera bien attention de ne pas mettre de JAR contenant des EJB dans le WAR. Les seuls JAR autorisés dans le WAR sont des JAR de bibliothèques (par exemple des utilitaires, etc.). Le ou les JAR contenant des EJB doivent être placés dans un EAR.
À noter que le tutoriel Java EE contient des exemples de code, notamment des exemples de fichiers web.xml.
La spécification complète de Java Platform Enterprise Edition où on pourra trouver la syntaxe des fichiers de configuration XML comme web.xml, application.xml, persistence.xml :
Structure du WAR
$ unzip -l dist/inf5043-example-1.war
META-INF/
META-INF/MANIFEST.MF
WEB-INF/
WEB-INF/web.xml
WEB-INF/classes/
WEB-INF/classes/fr/
WEB-INF/classes/fr/esiea_ouest/
WEB-INF/classes/fr/esiea_ouest/example1/
WEB-INF/classes/fr/esiea_ouest/example1/server/
WEB-INF/classes/fr/esiea_ouest/example1/server/CalculatorUiController.class
WEB-INF/classes/fr/esiea_ouest/example1/server/ControlServlet.class
WEB-INF/classes/fr/esiea_ouest/example1/server/EjbUtil.class
WEB-INF/classes/fr/esiea_ouest/example1/server/TestServlet.class
WEB-INF/classes/fr/esiea_ouest/example1/server/TicketUiController.class
WEB-INF/faces-config.xml
index.jsp
ticket-create-servlet.jsp
ticket-create.jsp
ticket-creation-result.jsp
ticket-list.jsp
timer-create.jsp
user-create.jsp
user-list.jsp
Création de la TestServlet et de JSP
Création et déploiement d'une Servlet et de JSP. On commencera par une Servlet de test (nommée TestServlet) héritant de la classe
http://java.sun.com/javaee/5/docs/api/javax/servlet/http/HttpServlet.htmlTestServlet devra juste afficher un message « Bonjour N » avec « N » étant un compteur qui sera incrémenté à chaque rechargement de la page.
Correspondances des URL et des services (Servlets, JSP)
L'URL de la Servlet de test sera de la forme suivante :
http://localhost:8080/inf5043-example-1/testLes correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par deux paramètres :
le nom du .war qui va déterminer le nom de l'application web (webapp) juste après l'adresse du serveur d'application (dans l'exemple le war a pour nom inf5043-example-1.war)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Création des distributions JAR et EARCréation d'artefacts JAR et WAR à l'aide de Ant pour y stocker respectivement les Entity, les EJB (Stateless Session Bean et Stateful Session Bean) et les ressources de l'application.
Création des classes EntityCréation au minimum de deux classes Entity. Création du fichier persistence.xml avec définition de la persistence-unit. Création d'un EJB StatelessCréation d'un EJB Stateless qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.war Création d'un EJB StatefulCréation d'un EJB Stateful qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.warLa différence avec l'EJB Stateless viendra du fait que les méthodes de l'EJB Stateful se feront dans le cadre d'un contexte persistant. Création de la ControlServlet communiquant avec les EJB SessionRécupération d'une référence sur les EJB Session par JNDI de manière générique :Context jndiContext = new InitialContext();String refName = BeanInterface.class.getName();BeanInterface beanObject = (BeanInterface) jndiContext.lookup(refName);Exemple de code avec des noms de classes réels :Context jndiContext = new InitialContext();String refName = TicketDesk.class.getName();TicketDesk ticketDesk = (TicketDesk) jndiContext.lookup(refName); Structure de l'EJB JAR$ unzip -l dist/inf5043-example-1-ejb.jar META-INF/META-INF/MANIFEST.MForg/org/aful/org/aful/example1/org/aful/example1/ejb/org/aful/example1/ejb/TicketDesk.classorg/aful/example1/ejb/TicketDeskBean.classorg/aful/example1/ejb/UserAccountBoard.classorg/aful/example1/ejb/UserAccountBoardBean.classorg/aful/example1/entity/org/aful/example1/entity/Ticket.classorg/aful/example1/entity/UserAccount.classMETA-INF/persistence.xml Structure du EAR$ unzip -l dist/inf5043-example-1.ear META-INF/META-INF/MANIFEST.MFMETA-INF/application.xmlaful-example-1-ejb.jaraful-example-1.war Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test deviendra de la forme suivante : http://localhost:8080/project-name/test Ce qui change de la forme précédente qui était : http://localhost:8080/inf5043-example-1/testCeci vient du fait que maintenant les correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par les deux paramètres suivants :le context-root définit dans le fichier application.xml (dans l'exemple le contexte root vaut project-name)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Les correspondances entre les URL et les services déployés (Servlets, JSP) sont définies dans le fichier web.xml et le fichier application.xml. Génération des WebServicesGénération des Web services (en SOAP) pour les EJB Stateless Session à l'aide de l'annotation suivante :@WebMethodSeuls les Stateless Session Beans peuvent implémenter un Web service. Utilisation de JSFUtilisation de JSF pour la génération et la gestion des interactions des pages web. Précisions techniquesCette section décrit l'ensemble des précisions techniques utiles lors de l'utilisation de GlassFish et JBoss. Démarrage/arrêt /déploiement avec serveur d'application JEE Répertoires de déploiementGlassfish et JBoss n'ont pas la même structure d'arborescence, et leur répertoire de déploiement ne se trouve pas au même endroit :GlassFish : GLASSFISH_HOME/domains/domain1/autodeployJBoss : JBOSS_HOME/server/default/deployAussi il faut bien penser à modifier le build.xml lors d'un déploiement avec Ant, selon qu'on déploit sur GlassFish ou JBoss.Lorsque vous avez des erreurs de déploiement au niveau du serveur d'application, pensez bien à supprimer du répertoire de déploiement toutes les versions des JAR ou autres artefacts que vous avez pu déployer. L'idée est d'avoir une situation parfaitement propre avant de déployer quelque chose. Démarrage/arrêt/déploiement avec GlassFish$ cd GLASSFISH_HOME$ bin/asadmin start-domain domain1=> http://localhost:8080/Il est nécessaire de démarrer la base de données Derby embarquée si on souhaite l'utiliser comme c'est notre cas :$ bin/asadmin start-databaseArrêt des services :$ bin/asadmin stop-domain domain1$ bin/asadmin stop-database Permissions et droits d'accèsPour administrer GlassFish il peut être nécessaire de passer sous l'utilisateur glassfish :$ sudo su - glassfishDe plus, pour qu'un utilisateur puisse déployer des artefacts dans GlassFish il est nécessaire qu'il ait les droits nécessaires pour écrire dans le dossier autodeploy de GlassFish. Dans le cadre du TP, uniquement dans le cadre de tests et surtout pas en production, on pourra donc réaliser la manipulation suivante qui compromet la sécurité de l'application mais qui permet le déploiement par tous les utilisateurs :$ sudo su – glassfish
$ chmod a+rwx /opt/java-ee-6/glassfish/domains/domain1/autodeploy Démarrage de JBoss$ cd JBOSS_HOME$ bin/run.sh=> http://localhost:8080/ JNDI service de JBossLe fichier JBOSS_HOME/server/default/conf/jndi.properties doit bien comporter les propriétés suivantes :java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfacesjava.naming.provider.url=jnp://localhost:1099On peut vérifier que les EJB sont bien présents, et avec quel nom, au niveau du service de nommage JNDI à partir de la JMX Console :http://localhost:8080/ -> JMX Console -> service=JNDIView -> java.lang.String list() -> InvokeOn obtient alors une sortie du type de celle incluse dans le fichier jndiview-list.txt. Références JNDI des EJBLes références JNDI des EJB peuvent varier de JBoss à Glassfish.Attention le code suivant n'est pas portable :@Stateless(mappedName="fr.esiea_ouest.example1.ejb.TicketDesk") Sources de donnéesBien penser à changer la source de données spécifiées dans persistence.xml quand on passe de JBoss à GlassFish ou inversement. Vérifications LogsLorsqu'on déploie des artefacts (des JAR, des WAR, des EAR), les opérations effectuées sont listées en temps réel dans les logs de l'application. Les causes d'erreurs de non-déploiement (par exemple mauvaise configuration de la persistance cf. section plus loin) ou le fait que les composants ont bien été déployés sont détaillés.Glassfish et JBoss n'ont pas la structure d'arborescence, notamment les fichiers de log sont différents :GlassFish : GLASSFISH_HOME/domains/domain1/logs/server.logJBoss : JBOSS_HOME/server/default/log/server.log VérificateurJEE est fournie avec un outil de vérification des artefacts : verifier. On peut utiliser cet outil sur n'importe quel artefact préalablement à tout déploiement, ça permet d'aller un peu plus vite que l'attente d'un déploiement, mais surtout les résultats de l'analyse du vérificateur sont généralement un peu plus clairs lorsqu'ils sont isolés du reste des logs de l'application.$ JEE_HOME/bin/verifier example-ejb.jar$ JEE_HOME/bin/verifier example-webapp.war$ JEE_HOME/bin/verifier example-application.ear Vérifications dans GlassFishAvec Glassfish il est nécessaire de paramétrer un certain nombre de paramètre dans l'interface d'administration.http://localhost:4848/admin / javaadmin Visiter et vérifier la connexion à la base de données Resources> JDBC> JDBC Resources> jdbc/__defaultStatus : Enabled=> Save Vérifier les paramètres d'auto-déploiement Application Server -> Advanced :Reload : EnabledAuto Deploy : EnabledVerifier : EnabledPrecompile : Enabled=> Save Vider le contenu de la base de données DerbyAvant de supprimer le contenu de la base Derby, il faut s'assurer qu'elle n'est pas utilisée par l'application Glassfish. Une fois arrêtée on peut supprimer son contenu :$ rm -rf /media/cdrom/jee5/databases/*Les structures nécessaires au bon fonctionnement de la base seront créées à nouveau lors du prochain démarrage de la base Derby. Vérifier le contenu de la base de données DerbyAvant de se connecter à la base Derby, il faut s'assurer qu'elle n'est pas démarrée pour être utilisée avec l'application GlassFish. Une fois arrêtée on peut y accéder comme suit : $ export DERBY_HOME=/opt/SDK/javadb/tmp/jee5-databases$ bash /opt/SDK/javadb/bin/ijversion ij 10.2ij> help; Les commandes prises en charge sont les suivantes : PROTOCOL 'protocole JDBC' [ AS identificateur ]; -- définit un protocole par défaut ou indiqué DRIVER 'classe de pilote'; -- charge la classe indiquée CONNECT 'url de la base de données' [ PROTOCOL ProtocoleIndiqué ] [ AS NomDeConnexion ]; -- se connecte à l'URL de la base de données -- et peut affecter un identificateur SET CONNECTION NomDeConnexion; -- bascule vers la connexion indiquée SHOW CONNECTIONS; -- répertorie toutes les connexions AUTOCOMMIT [ ON | OFF ]; -- active ou désactive le mode de validation automatique pour la connexion DISCONNECT [ CURRENT | NomDeConnexion | ALL ]; -- interrompt la connexion en cours, la connexion indiquée ou toutes les connexions; -- la valeur par défaut est CURRENT SHOW SCHEMAS ; -- répertorie tous les schémas de la base de données actuelle SHOW [ TABLES | VIEWS | PROCEDURES | SYNONYMS ] { IN schéma }; ; -- répertorie les tables, les vues, les procédures ou les synonymesij> connect 'jdbc:derby:/opt/SDK/databases/sun-appserv-samples';ij> show tables;TABLE_SCHEM |TABLE_NAME |REMARKS------------------------------------------------------------------------SYS |SYSALIASES |SYS |SYSCHECKS |SYS |SYSCOLPERMS |SYS |SYSCOLUMNS |SYS |SYSCONGLOMERATES |SYS |SYSCONSTRAINTS |SYS |SYSDEPENDS |SYS |SYSFILES |SYS |SYSFOREIGNKEYS |SYS |SYSKEYS |SYS |SYSROUTINEPERMS |SYS |SYSSCHEMAS |SYS |SYSSTATEMENTS |SYS |SYSSTATISTICS |SYS |SYSTABLEPERMS |SYS |SYSTABLES |SYS |SYSTRIGGERS |SYS |SYSVIEWS |SYSIBM |SYSDUMMY1 |APP |SEQUENCE |APP |TICKET |APP |USERACCOUNTBEAN |22 lignes sélectionnéesij> exit;
Création des distributions JAR et EAR
Création d'artefacts JAR et WAR à l'aide de Ant pour y stocker respectivement les Entity, les EJB (Stateless Session Bean et Stateful Session Bean) et les ressources de l'application.
Création des classes EntityCréation au minimum de deux classes Entity. Création du fichier persistence.xml avec définition de la persistence-unit. Création d'un EJB StatelessCréation d'un EJB Stateless qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.war Création d'un EJB StatefulCréation d'un EJB Stateful qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :@PersistenceContext(unitName = "ejb1-example")private EntityManager emanager;emanager.persist(entityObject);etc.emanager.find(EntityObject.class, id);etc.example-1.warLa différence avec l'EJB Stateless viendra du fait que les méthodes de l'EJB Stateful se feront dans le cadre d'un contexte persistant. Création de la ControlServlet communiquant avec les EJB SessionRécupération d'une référence sur les EJB Session par JNDI de manière générique :Context jndiContext = new InitialContext();String refName = BeanInterface.class.getName();BeanInterface beanObject = (BeanInterface) jndiContext.lookup(refName);Exemple de code avec des noms de classes réels :Context jndiContext = new InitialContext();String refName = TicketDesk.class.getName();TicketDesk ticketDesk = (TicketDesk) jndiContext.lookup(refName); Structure de l'EJB JAR$ unzip -l dist/inf5043-example-1-ejb.jar META-INF/META-INF/MANIFEST.MForg/org/aful/org/aful/example1/org/aful/example1/ejb/org/aful/example1/ejb/TicketDesk.classorg/aful/example1/ejb/TicketDeskBean.classorg/aful/example1/ejb/UserAccountBoard.classorg/aful/example1/ejb/UserAccountBoardBean.classorg/aful/example1/entity/org/aful/example1/entity/Ticket.classorg/aful/example1/entity/UserAccount.classMETA-INF/persistence.xml Structure du EAR$ unzip -l dist/inf5043-example-1.ear META-INF/META-INF/MANIFEST.MFMETA-INF/application.xmlaful-example-1-ejb.jaraful-example-1.war Correspondances des URL et des services (Servlets, JSP)L'URL de la Servlet de test deviendra de la forme suivante : http://localhost:8080/project-name/test Ce qui change de la forme précédente qui était : http://localhost:8080/inf5043-example-1/testCeci vient du fait que maintenant les correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par les deux paramètres suivants :le context-root définit dans le fichier application.xml (dans l'exemple le contexte root vaut project-name)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Les correspondances entre les URL et les services déployés (Servlets, JSP) sont définies dans le fichier web.xml et le fichier application.xml. Génération des WebServicesGénération des Web services (en SOAP) pour les EJB Stateless Session à l'aide de l'annotation suivante :@WebMethodSeuls les Stateless Session Beans peuvent implémenter un Web service. Utilisation de JSFUtilisation de JSF pour la génération et la gestion des interactions des pages web. Précisions techniquesCette section décrit l'ensemble des précisions techniques utiles lors de l'utilisation de GlassFish et JBoss. Démarrage/arrêt /déploiement avec serveur d'application JEE Répertoires de déploiementGlassfish et JBoss n'ont pas la même structure d'arborescence, et leur répertoire de déploiement ne se trouve pas au même endroit :GlassFish : GLASSFISH_HOME/domains/domain1/autodeployJBoss : JBOSS_HOME/server/default/deployAussi il faut bien penser à modifier le build.xml lors d'un déploiement avec Ant, selon qu'on déploit sur GlassFish ou JBoss.Lorsque vous avez des erreurs de déploiement au niveau du serveur d'application, pensez bien à supprimer du répertoire de déploiement toutes les versions des JAR ou autres artefacts que vous avez pu déployer. L'idée est d'avoir une situation parfaitement propre avant de déployer quelque chose. Démarrage/arrêt/déploiement avec GlassFish$ cd GLASSFISH_HOME$ bin/asadmin start-domain domain1=> http://localhost:8080/Il est nécessaire de démarrer la base de données Derby embarquée si on souhaite l'utiliser comme c'est notre cas :$ bin/asadmin start-databaseArrêt des services :$ bin/asadmin stop-domain domain1$ bin/asadmin stop-database Permissions et droits d'accèsPour administrer GlassFish il peut être nécessaire de passer sous l'utilisateur glassfish :$ sudo su - glassfishDe plus, pour qu'un utilisateur puisse déployer des artefacts dans GlassFish il est nécessaire qu'il ait les droits nécessaires pour écrire dans le dossier autodeploy de GlassFish. Dans le cadre du TP, uniquement dans le cadre de tests et surtout pas en production, on pourra donc réaliser la manipulation suivante qui compromet la sécurité de l'application mais qui permet le déploiement par tous les utilisateurs :$ sudo su – glassfish
$ chmod a+rwx /opt/java-ee-6/glassfish/domains/domain1/autodeploy Démarrage de JBoss$ cd JBOSS_HOME$ bin/run.sh=> http://localhost:8080/ JNDI service de JBossLe fichier JBOSS_HOME/server/default/conf/jndi.properties doit bien comporter les propriétés suivantes :java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfacesjava.naming.provider.url=jnp://localhost:1099On peut vérifier que les EJB sont bien présents, et avec quel nom, au niveau du service de nommage JNDI à partir de la JMX Console :http://localhost:8080/ -> JMX Console -> service=JNDIView -> java.lang.String list() -> InvokeOn obtient alors une sortie du type de celle incluse dans le fichier jndiview-list.txt. Références JNDI des EJBLes références JNDI des EJB peuvent varier de JBoss à Glassfish.Attention le code suivant n'est pas portable :@Stateless(mappedName="fr.esiea_ouest.example1.ejb.TicketDesk") Sources de donnéesBien penser à changer la source de données spécifiées dans persistence.xml quand on passe de JBoss à GlassFish ou inversement. Vérifications LogsLorsqu'on déploie des artefacts (des JAR, des WAR, des EAR), les opérations effectuées sont listées en temps réel dans les logs de l'application. Les causes d'erreurs de non-déploiement (par exemple mauvaise configuration de la persistance cf. section plus loin) ou le fait que les composants ont bien été déployés sont détaillés.Glassfish et JBoss n'ont pas la structure d'arborescence, notamment les fichiers de log sont différents :GlassFish : GLASSFISH_HOME/domains/domain1/logs/server.logJBoss : JBOSS_HOME/server/default/log/server.log VérificateurJEE est fournie avec un outil de vérification des artefacts : verifier. On peut utiliser cet outil sur n'importe quel artefact préalablement à tout déploiement, ça permet d'aller un peu plus vite que l'attente d'un déploiement, mais surtout les résultats de l'analyse du vérificateur sont généralement un peu plus clairs lorsqu'ils sont isolés du reste des logs de l'application.$ JEE_HOME/bin/verifier example-ejb.jar$ JEE_HOME/bin/verifier example-webapp.war$ JEE_HOME/bin/verifier example-application.ear Vérifications dans GlassFishAvec Glassfish il est nécessaire de paramétrer un certain nombre de paramètre dans l'interface d'administration.http://localhost:4848/admin / javaadmin Visiter et vérifier la connexion à la base de données Resources> JDBC> JDBC Resources> jdbc/__defaultStatus : Enabled=> Save Vérifier les paramètres d'auto-déploiement Application Server -> Advanced :Reload : EnabledAuto Deploy : EnabledVerifier : EnabledPrecompile : Enabled=> Save Vider le contenu de la base de données DerbyAvant de supprimer le contenu de la base Derby, il faut s'assurer qu'elle n'est pas utilisée par l'application Glassfish. Une fois arrêtée on peut supprimer son contenu :$ rm -rf /media/cdrom/jee5/databases/*Les structures nécessaires au bon fonctionnement de la base seront créées à nouveau lors du prochain démarrage de la base Derby. Vérifier le contenu de la base de données DerbyAvant de se connecter à la base Derby, il faut s'assurer qu'elle n'est pas démarrée pour être utilisée avec l'application GlassFish. Une fois arrêtée on peut y accéder comme suit : $ export DERBY_HOME=/opt/SDK/javadb/tmp/jee5-databases$ bash /opt/SDK/javadb/bin/ijversion ij 10.2ij> help; Les commandes prises en charge sont les suivantes : PROTOCOL 'protocole JDBC' [ AS identificateur ]; -- définit un protocole par défaut ou indiqué DRIVER 'classe de pilote'; -- charge la classe indiquée CONNECT 'url de la base de données' [ PROTOCOL ProtocoleIndiqué ] [ AS NomDeConnexion ]; -- se connecte à l'URL de la base de données -- et peut affecter un identificateur SET CONNECTION NomDeConnexion; -- bascule vers la connexion indiquée SHOW CONNECTIONS; -- répertorie toutes les connexions AUTOCOMMIT [ ON | OFF ]; -- active ou désactive le mode de validation automatique pour la connexion DISCONNECT [ CURRENT | NomDeConnexion | ALL ]; -- interrompt la connexion en cours, la connexion indiquée ou toutes les connexions; -- la valeur par défaut est CURRENT SHOW SCHEMAS ; -- répertorie tous les schémas de la base de données actuelle SHOW [ TABLES | VIEWS | PROCEDURES | SYNONYMS ] { IN schéma }; ; -- répertorie les tables, les vues, les procédures ou les synonymesij> connect 'jdbc:derby:/opt/SDK/databases/sun-appserv-samples';ij> show tables;TABLE_SCHEM |TABLE_NAME |REMARKS------------------------------------------------------------------------SYS |SYSALIASES |SYS |SYSCHECKS |SYS |SYSCOLPERMS |SYS |SYSCOLUMNS |SYS |SYSCONGLOMERATES |SYS |SYSCONSTRAINTS |SYS |SYSDEPENDS |SYS |SYSFILES |SYS |SYSFOREIGNKEYS |SYS |SYSKEYS |SYS |SYSROUTINEPERMS |SYS |SYSSCHEMAS |SYS |SYSSTATEMENTS |SYS |SYSSTATISTICS |SYS |SYSTABLEPERMS |SYS |SYSTABLES |SYS |SYSTRIGGERS |SYS |SYSVIEWS |SYSIBM |SYSDUMMY1 |APP |SEQUENCE |APP |TICKET |APP |USERACCOUNTBEAN |22 lignes sélectionnéesij> exit;
Création des classes Entity
Création au minimum de deux classes Entity.
Création du fichier persistence.xml avec définition de la
persistence-unit.
Création d'un EJB Stateless
Création d'un EJB Stateless qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :
@PersistenceContext(unitName = "ejb1-example")
private EntityManager emanager;
emanager.persist(entityObject);
etc.
emanager.find(EntityObject.class, id);
etc.
example-1.war
Création d'un EJB Stateful
Création d'un EJB Stateful qui va créer, manipuler et requêter les Entities en passant par le biais d'un PersistenceContext et d'un EntityManager :
@PersistenceContext(unitName = "ejb1-example")
private EntityManager emanager;
emanager.persist(entityObject);
etc.
emanager.find(EntityObject.class, id);
etc.
example-1.war
La différence avec l'EJB Stateless viendra du fait que les méthodes de l'EJB Stateful se feront dans le cadre d'un contexte persistant.
Création de la ControlServlet communiquant avec les EJB Session
Récupération d'une référence sur les EJB Session par JNDI de manière générique :
Context jndiContext = new InitialContext();
String refName = BeanInterface.class.getName();
BeanInterface beanObject = (BeanInterface) jndiContext.lookup(refName);
Exemple de code avec des noms de classes réels :
Context jndiContext = new InitialContext();
String refName = TicketDesk.class.getName();
TicketDesk ticketDesk = (TicketDesk) jndiContext.lookup(refName);
Structure de l'EJB JAR
$ unzip -l dist/inf5043-example-1-ejb.jar
META-INF/
META-INF/MANIFEST.MF
org/
org/aful/
org/aful/example1/
org/aful/example1/ejb/
org/aful/example1/ejb/TicketDesk.class
org/aful/example1/ejb/TicketDeskBean.class
org/aful/example1/ejb/UserAccountBoard.class
org/aful/example1/ejb/UserAccountBoardBean.class
org/aful/example1/entity/
org/aful/example1/entity/Ticket.class
org/aful/example1/entity/UserAccount.class
META-INF/persistence.xml
Structure du EAR
$ unzip -l dist/inf5043-example-1.ear
META-INF/
META-INF/MANIFEST.MF
META-INF/application.xml
aful-example-1-ejb.jar
aful-example-1.war
Correspondances des URL et des services (Servlets, JSP)
L'URL de la Servlet de test deviendra de la forme suivante :
http://localhost:8080/project-name/test Ce qui change de la forme précédente qui était :
http://localhost:8080/inf5043-example-1/testCeci vient du fait que maintenant les correspondances entre les URL et les services déployés (Servlets, JSP) sont déterminées par les deux paramètres suivants :
le context-root définit dans le fichier application.xml (dans l'exemple le contexte root vaut project-name)
le fichier web.xml qui va établir les correspondances entre la partie suivant le nom de la webapp et les servlets (dans l'exemple /test fera la correspondance avec org.aful.example1.server.TestServlet)
Les correspondances entre les URL et les services déployés (Servlets, JSP) sont définies dans le fichier web.xml et le fichier application.xml. Génération des WebServicesGénération des Web services (en SOAP) pour les EJB Stateless Session à l'aide de l'annotation suivante :@WebMethodSeuls les Stateless Session Beans peuvent implémenter un Web service. Utilisation de JSFUtilisation de JSF pour la génération et la gestion des interactions des pages web. Précisions techniquesCette section décrit l'ensemble des précisions techniques utiles lors de l'utilisation de GlassFish et JBoss. Démarrage/arrêt /déploiement avec serveur d'application JEE Répertoires de déploiementGlassfish et JBoss n'ont pas la même structure d'arborescence, et leur répertoire de déploiement ne se trouve pas au même endroit :GlassFish : GLASSFISH_HOME/domains/domain1/autodeployJBoss : JBOSS_HOME/server/default/deployAussi il faut bien penser à modifier le build.xml lors d'un déploiement avec Ant, selon qu'on déploit sur GlassFish ou JBoss.Lorsque vous avez des erreurs de déploiement au niveau du serveur d'application, pensez bien à supprimer du répertoire de déploiement toutes les versions des JAR ou autres artefacts que vous avez pu déployer. L'idée est d'avoir une situation parfaitement propre avant de déployer quelque chose. Démarrage/arrêt/déploiement avec GlassFish$ cd GLASSFISH_HOME$ bin/asadmin start-domain domain1=> http://localhost:8080/Il est nécessaire de démarrer la base de données Derby embarquée si on souhaite l'utiliser comme c'est notre cas :$ bin/asadmin start-databaseArrêt des services :$ bin/asadmin stop-domain domain1$ bin/asadmin stop-database Permissions et droits d'accèsPour administrer GlassFish il peut être nécessaire de passer sous l'utilisateur glassfish :$ sudo su - glassfishDe plus, pour qu'un utilisateur puisse déployer des artefacts dans GlassFish il est nécessaire qu'il ait les droits nécessaires pour écrire dans le dossier autodeploy de GlassFish. Dans le cadre du TP, uniquement dans le cadre de tests et surtout pas en production, on pourra donc réaliser la manipulation suivante qui compromet la sécurité de l'application mais qui permet le déploiement par tous les utilisateurs :$ sudo su – glassfish
$ chmod a+rwx /opt/java-ee-6/glassfish/domains/domain1/autodeploy Démarrage de JBoss$ cd JBOSS_HOME$ bin/run.sh=> http://localhost:8080/ JNDI service de JBossLe fichier JBOSS_HOME/server/default/conf/jndi.properties doit bien comporter les propriétés suivantes :java.naming.factory.initial=org.jnp.interfaces.NamingContextFactoryjava.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfacesjava.naming.provider.url=jnp://localhost:1099On peut vérifier que les EJB sont bien présents, et avec quel nom, au niveau du service de nommage JNDI à partir de la JMX Console :http://localhost:8080/ -> JMX Console -> service=JNDIView -> java.lang.String list() -> InvokeOn obtient alors une sortie du type de celle incluse dans le fichier jndiview-list.txt. Références JNDI des EJBLes références JNDI des EJB peuvent varier de JBoss à Glassfish.Attention le code suivant n'est pas portable :@Stateless(mappedName="fr.esiea_ouest.example1.ejb.TicketDesk") Sources de donnéesBien penser à changer la source de données spécifiées dans persistence.xml quand on passe de JBoss à GlassFish ou inversement. Vérifications LogsLorsqu'on déploie des artefacts (des JAR, des WAR, des EAR), les opérations effectuées sont listées en temps réel dans les logs de l'application. Les causes d'erreurs de non-déploiement (par exemple mauvaise configuration de la persistance cf. section plus loin) ou le fait que les composants ont bien été déployés sont détaillés.Glassfish et JBoss n'ont pas la structure d'arborescence, notamment les fichiers de log sont différents :GlassFish : GLASSFISH_HOME/domains/domain1/logs/server.logJBoss : JBOSS_HOME/server/default/log/server.log VérificateurJEE est fournie avec un outil de vérification des artefacts : verifier. On peut utiliser cet outil sur n'importe quel artefact préalablement à tout déploiement, ça permet d'aller un peu plus vite que l'attente d'un déploiement, mais surtout les résultats de l'analyse du vérificateur sont généralement un peu plus clairs lorsqu'ils sont isolés du reste des logs de l'application.$ JEE_HOME/bin/verifier example-ejb.jar$ JEE_HOME/bin/verifier example-webapp.war$ JEE_HOME/bin/verifier example-application.ear Vérifications dans GlassFishAvec Glassfish il est nécessaire de paramétrer un certain nombre de paramètre dans l'interface d'administration.http://localhost:4848/admin / javaadmin Visiter et vérifier la connexion à la base de données Resources> JDBC> JDBC Resources> jdbc/__defaultStatus : Enabled=> Save Vérifier les paramètres d'auto-déploiement Application Server -> Advanced :Reload : EnabledAuto Deploy : EnabledVerifier : EnabledPrecompile : Enabled=> Save Vider le contenu de la base de données DerbyAvant de supprimer le contenu de la base Derby, il faut s'assurer qu'elle n'est pas utilisée par l'application Glassfish. Une fois arrêtée on peut supprimer son contenu :$ rm -rf /media/cdrom/jee5/databases/*Les structures nécessaires au bon fonctionnement de la base seront créées à nouveau lors du prochain démarrage de la base Derby. Vérifier le contenu de la base de données DerbyAvant de se connecter à la base Derby, il faut s'assurer qu'elle n'est pas démarrée pour être utilisée avec l'application GlassFish. Une fois arrêtée on peut y accéder comme suit : $ export DERBY_HOME=/opt/SDK/javadb/tmp/jee5-databases$ bash /opt/SDK/javadb/bin/ijversion ij 10.2ij> help; Les commandes prises en charge sont les suivantes : PROTOCOL 'protocole JDBC' [ AS identificateur ]; -- définit un protocole par défaut ou indiqué DRIVER 'classe de pilote'; -- charge la classe indiquée CONNECT 'url de la base de données' [ PROTOCOL ProtocoleIndiqué ] [ AS NomDeConnexion ]; -- se connecte à l'URL de la base de données -- et peut affecter un identificateur SET CONNECTION NomDeConnexion; -- bascule vers la connexion indiquée SHOW CONNECTIONS; -- répertorie toutes les connexions AUTOCOMMIT [ ON | OFF ]; -- active ou désactive le mode de validation automatique pour la connexion DISCONNECT [ CURRENT | NomDeConnexion | ALL ]; -- interrompt la connexion en cours, la connexion indiquée ou toutes les connexions; -- la valeur par défaut est CURRENT SHOW SCHEMAS ; -- répertorie tous les schémas de la base de données actuelle SHOW [ TABLES | VIEWS | PROCEDURES | SYNONYMS ] { IN schéma }; ; -- répertorie les tables, les vues, les procédures ou les synonymesij> connect 'jdbc:derby:/opt/SDK/databases/sun-appserv-samples';ij> show tables;TABLE_SCHEM |TABLE_NAME |REMARKS------------------------------------------------------------------------SYS |SYSALIASES |SYS |SYSCHECKS |SYS |SYSCOLPERMS |SYS |SYSCOLUMNS |SYS |SYSCONGLOMERATES |SYS |SYSCONSTRAINTS |SYS |SYSDEPENDS |SYS |SYSFILES |SYS |SYSFOREIGNKEYS |SYS |SYSKEYS |SYS |SYSROUTINEPERMS |SYS |SYSSCHEMAS |SYS |SYSSTATEMENTS |SYS |SYSSTATISTICS |SYS |SYSTABLEPERMS |SYS |SYSTABLES |SYS |SYSTRIGGERS |SYS |SYSVIEWS |SYSIBM |SYSDUMMY1 |APP |SEQUENCE |APP |TICKET |APP |USERACCOUNTBEAN |22 lignes sélectionnéesij> exit;
Les correspondances entre les URL et les services déployés (Servlets, JSP) sont définies dans le fichier web.xml et le fichier application.xml.
Génération des WebServices
Génération des Web services (en SOAP) pour les EJB Stateless Session à l'aide de l'annotation suivante :
@WebMethod
Seuls les Stateless Session Beans peuvent implémenter un Web service.
Utilisation de JSF
Utilisation de JSF pour la génération et la gestion des interactions des pages web.
Précisions techniques
Cette section décrit l'ensemble des précisions techniques utiles lors de l'utilisation de GlassFish et JBoss.
Démarrage/arrêt /déploiement avec serveur d'application JEE
Répertoires de déploiement
Glassfish et JBoss n'ont pas la même structure d'arborescence, et leur répertoire de déploiement ne se trouve pas au même endroit :
GlassFish : GLASSFISH_HOME/domains/domain1/autodeploy
JBoss : JBOSS_HOME/server/default/deploy
Aussi il faut bien penser à modifier le build.xml lors d'un déploiement avec Ant, selon qu'on déploit sur GlassFish ou JBoss.
Lorsque vous avez des erreurs de déploiement au niveau du serveur d'application, pensez bien à supprimer du répertoire de déploiement toutes les versions des JAR ou autres artefacts que vous avez pu déployer. L'idée est d'avoir une situation parfaitement propre avant de déployer quelque chose.
Démarrage/arrêt/déploiement avec GlassFish
$ cd GLASSFISH_HOME
$ bin/asadmin start-domain domain1
Il est nécessaire de démarrer la base de données Derby embarquée si on souhaite l'utiliser comme c'est notre cas :
$ bin/asadmin start-database
Arrêt des services :
$ bin/asadmin stop-domain domain1
$ bin/asadmin stop-database
Permissions et droits d'accès
Pour administrer GlassFish il peut être nécessaire de passer sous l'utilisateur glassfish :
$ sudo su - glassfish
De plus, pour qu'un utilisateur puisse déployer des artefacts dans GlassFish il est nécessaire qu'il ait les droits nécessaires pour écrire dans le dossier autodeploy de GlassFish. Dans le cadre du TP, uniquement dans le cadre de tests et surtout pas en production, on pourra donc réaliser la manipulation suivante qui compromet la sécurité de l'application mais qui permet le déploiement par tous les utilisateurs :
$ sudo su – glassfish
$ chmod a+rwx /opt/java-ee-6/glassfish/domains/domain1/autodeploy
Démarrage de JBoss
$ cd JBOSS_HOME
$ bin/run.sh
JNDI service de JBoss
Le fichier JBOSS_HOME/server/default/conf/jndi.properties doit bien comporter les propriétés suivantes :
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces
java.naming.provider.url=jnp://localhost:1099
On peut vérifier que les EJB sont bien présents, et avec quel nom, au niveau du service de nommage JNDI à partir de la JMX Console :
http://localhost:8080/ -> JMX Console -> service=JNDIView -> java.lang.String list() -> Invoke
On obtient alors une sortie du type de celle incluse dans le fichier jndiview-list.txt.
Références JNDI des EJB
Les références JNDI des EJB peuvent varier de JBoss à Glassfish.
Attention le code suivant n'est pas portable :
@Stateless(mappedName="fr.esiea_ouest.example1.ejb.TicketDesk")
Sources de données
Bien penser à changer la source de données spécifiées dans persistence.xml quand on passe de JBoss à GlassFish ou inversement.
Vérifications
Logs
Lorsqu'on déploie des artefacts (des JAR, des WAR, des EAR), les opérations effectuées sont listées en temps réel dans les logs de l'application. Les causes d'erreurs de non-déploiement (par exemple mauvaise configuration de la persistance cf. section plus loin) ou le fait que les composants ont bien été déployés sont détaillés.
Glassfish et JBoss n'ont pas la structure d'arborescence, notamment les fichiers de log sont différents :
GlassFish : GLASSFISH_HOME/domains/domain1/logs/server.log
JBoss : JBOSS_HOME/server/default/log/server.log
Vérificateur
JEE est fournie avec un outil de vérification des artefacts : verifier. On peut utiliser cet outil sur n'importe quel artefact préalablement à tout déploiement, ça permet d'aller un peu plus vite que l'attente d'un déploiement, mais surtout les résultats de l'analyse du vérificateur sont généralement un peu plus clairs lorsqu'ils sont isolés du reste des logs de l'application.
$ JEE_HOME/bin/verifier example-ejb.jar
$ JEE_HOME/bin/verifier example-webapp.war
$ JEE_HOME/bin/verifier example-application.ear
Vérifications dans GlassFish
Avec Glassfish il est nécessaire de paramétrer un certain nombre de paramètre dans l'interface d'administration.
admin / javaadmin
Visiter et vérifier la connexion à la base de données
Resources>
JDBC>
JDBC Resources> jdbc/__default
Status : Enabled
=> Save
Vérifier les paramètres d'auto-déploiement
Application Server -> Advanced :
Reload : Enabled
Auto Deploy : Enabled
Verifier : Enabled
Precompile : Enabled
=> Save
Vider le contenu de la base de données Derby
Avant de supprimer le contenu de la base Derby, il faut s'assurer qu'elle n'est pas utilisée par l'application Glassfish. Une fois arrêtée on peut supprimer son contenu :
$ rm -rf /media/cdrom/jee5/databases/*
Les structures nécessaires au bon fonctionnement de la base seront créées à nouveau lors du prochain démarrage de la base Derby.
Vérifier le contenu de la base de données Derby
Avant de se connecter à la base Derby, il faut s'assurer qu'elle n'est pas démarrée pour être utilisée avec l'application GlassFish. Une fois arrêtée on peut y accéder comme suit :
$ export DERBY_HOME=/opt/SDK/javadb
/tmp/jee5-databases$ bash /opt/SDK/javadb/bin/ij
version ij 10.2
ij> help;
Les commandes prises en charge sont les suivantes :
PROTOCOL 'protocole JDBC' [ AS identificateur ];
-- définit un protocole par défaut ou indiqué
DRIVER 'classe de pilote'; -- charge la classe indiquée
CONNECT 'url de la base de données' [ PROTOCOL ProtocoleIndiqué ] [ AS NomDeConnexion ];
-- se connecte à l'URL de la base de données
-- et peut affecter un identificateur
SET CONNECTION NomDeConnexion; -- bascule vers la connexion indiquée
SHOW CONNECTIONS; -- répertorie toutes les connexions
AUTOCOMMIT [ ON | OFF ]; -- active ou désactive le mode de validation automatique pour la connexion
DISCONNECT [ CURRENT | NomDeConnexion | ALL ];
-- interrompt la connexion en cours, la connexion indiquée ou toutes les connexions;
-- la valeur par défaut est CURRENT
SHOW SCHEMAS ; -- répertorie tous les schémas de la base de données actuelle
SHOW [ TABLES | VIEWS | PROCEDURES | SYNONYMS ] { IN schéma };
; -- répertorie les tables, les vues, les procédures ou les synonymes
ij> connect 'jdbc:derby:/opt/SDK/databases/sun-appserv-samples';
ij> show tables;
TABLE_SCHEM |TABLE_NAME |REMARKS
------------------------------------------------------------------------
SYS |SYSALIASES |
SYS |SYSCHECKS |
SYS |SYSCOLPERMS |
SYS |SYSCOLUMNS |
SYS |SYSCONGLOMERATES |
SYS |SYSCONSTRAINTS |
SYS |SYSDEPENDS |
SYS |SYSFILES |
SYS |SYSFOREIGNKEYS |
SYS |SYSKEYS |
SYS |SYSROUTINEPERMS |
SYS |SYSSCHEMAS |
SYS |SYSSTATEMENTS |
SYS |SYSSTATISTICS |
SYS |SYSTABLEPERMS |
SYS |SYSTABLES |
SYS |SYSTRIGGERS |
SYS |SYSVIEWS |
SYSIBM |SYSDUMMY1 |
APP |SEQUENCE |
APP |TICKET |
APP |USERACCOUNTBEAN |
22 lignes sélectionnées
ij> exit;