Ce tutorial est une introduction aux APIs, outils et services du Java 2 Enterprise Edition Software Developer Kit (SDK). Vous pouvez obtenir gratuitement le J2EE SDK (http://java.sun.com/j2ee/download.html) et l'utiliser pour des démonstrations, le prototypage d'applications et lanimation de formations, et vérifier la portabilité de vos applications J2EE.
Pour servir ce propos, le J2EE SDK est livré avec les outils de développement et déploiement de J2EE, un serveur web, la base de donnée Cloudscape, un serveur d'application Java, le support de XML, les APIs J2EE et le Java Plug-In. Le Java Plug-In vous permet de lancer des applets dans les navigateurs qui supportent une version précédente du Java Runtime Environment (JRE).
Cette leçon vous introduit à la programmation d'applications J2EE, et au J2EE SDK en vous montrant comment écrire une application multitiers client-léger simple qui consiste en une page HTML, une servlet et un bean de session.
Application multitiers client léger
Le J2EE SDK est une implémentation opérationnelle non-commerciale de la plate-forme J2EE et de ses spécifications, distribuée gratuitement par Sun Microsystems pour la démonstration, le prototypage et la formation. Il est livré avec le serveur d'application J2EE, un serveur web, une base de données, les APIs J2EE et une large gamme d'outils de développement et de déploiement. Vous deviendrez familier avec ces fonctionnalités et outils `à mesure que vous effectuerez ce tutorial.
L'exemple d'application multi-tiers client-léger de cette leçon reçoit les données de l'utilisateur au travers d'un formulaire HTML qui invoque une servlet. La servlet utilise les APIs Java Naming and Directory Interface (JNDI) pour chercher un bean de session qui effectuera un calcul pour la servlet. Dès qu'elle reçoit les résultats du calcul, la servlet renvoie la valeur calculée `à l'utilisateur final dans une page HTML.
Cet exemple est une application client léger car la servlet n'exécute aucune logique applicative. Le calcul est effectué par un bean de session exécuté sur le serveur d'application J2EE. Ainsi, le client est léger car il n'effectue pas de traitements, c'est le bean de session qui les fait.
Les applications multitiers peuvent être composées de 3 ou 4 tiers. Comme le présente la Figure 1, l'exemple multitiers de ce tutorial a 4 tiers. Les architectures 3 tiers 'étendent le modèle d'architecture client-serveur standard en plaçant un serveur d'application multi-threadé entre une application cliente non-web et une base de données. Les architectures 4 tiers 'étendent le modèle 3 tiers en remplaçant l'application cliente par un navigateur Web et des pages HTML crées `à l'aide de technologies comme les serlvets,JSPs,...
Durant cette leçon nous utiliserons seulement 3 des 4 tiers, la leçon 2 'étend cet exemple pour accéder `à une base de donnée comme 4eme tiers. Les leçons suivantes adaptent cet exemple pour utiliser les technologies Java Server Pages et Extensible Markup Language (XML).
Pour faire les exemples du tutorial vous avez besoin de télécharger et installer le kit de développement Java 2 Enterprise Edition (http://java.sun.com/j2ee/download.html) et le kit de développement Java 2 Standard Edition(http://java.sun.com/index.html).
Les instructions de ce tutorial supposent que J2EE et J2SE sont tous deux installés dans un répertoire J2EE de l'utilisateur.
Note: A chaque fois que lmaitre est utilisé dans un nom de chemin, changez le par votre propre nom d'utilisateur.
/net/home/lmaitre/J2EE/j2sdkee1.3
/net/home/lmaitre/J2EE/j2sdk1.3.1
\net\home\lmaitre\J2EE\j2sdkee1.3
\net\home\lmaitre\J2EE\j2sdk1.3.1
Le téléchargement contient le serveur d'application J2EE, la base de donnée Cloudscape, un serveur web utilisant secure socket layer (SSL) aussi connu sous le nom de HTTPS, des outils de développement et de déploiement, et les APIs Java pour l'Entreprise. Pour utiliser ces fonctionnalités, régler vos variables d'environnement PATH et CLASSPATH comme d'écrit ci-dessous.
Le réglage de la variable d'environnement PATH rend les outils de développement et de déploiement accessibles de n'importe quel endroit de votre système. Assurez-vous d'avoir placé ces réglages du chemin avant tout autre chemin que vous pourriez avoir fait pour une installation plus ancienne du JDK.
PATH=${PATH}:/net/home/lmaitre/J2EE/j2sdkee1.3/bin
PATH=${PATH}:/net/home/lmaitre/J2EE/j2sdk1.3.1/bin
PATH=%PATH%;\net\home\lmaitre\J2EE\j2sdkee1.3\bin
PATH=%PATH%;\net\home\lmaitre\J2EE\j2sdk1.3.1\bin
Le réglage de la variable d'environnement CLASSPATH dit aux outils de développement et déploiement Java 2 où trouver les différentes libraires de classes qu'ils utilisent.
CLASSPATH=${CLASSPATH}:/net/home/lmaitre/J2EE/j2sdkee1.3/lib/j2ee.jar
CLASSPATH=%CLASSPATH%;\net\home\lmaitre\J2EE\j2sdkee1.3\lib\j2ee.jar
Les programmeurs d'application J2EE 'écrivent des composants d'application J2EE. Un composant J2EE est une unité de code logiciel fonctionnelle et autonome qui est assemblé dans une application J2EE et interfacé avec d'autres composants applicatifs. Les spécifications J2EE définissent les composants d'application suivants :
Dans cette leçon, nous créons une application J2EE et deux composants J2EE : une servlet et un bean de session. La servlet est incorporée avec ses fichiers HTMLs dans un fichier Web Archive (WAR), et l'interface et les classes du bean de session sont incorporés dans un fichier Java Archive (JAR). Les fichiers WAR et JAR sont ajoutés `à une application J2EE et incorporés dans un fichier Enterprise Archive (EAR) pour la vérification et le déploiement en environnement de production.
Alors que vous allez faire toutes ces 'étapes dans cette leçon, vous allez exercer différentes fonctions. Ecrire la servlet et le code du bean de session est une tâche de programmeur, tandis que la création de l'application et l'ajout de composants J2EE à l'application est une tâche d'intégrateur. En réalité, ces fonctions pourront être effectuées par différentes personnes dans différentes compagnies.
La page HTML pour cette leçon est appelée bonus.html. Son code HTML est après l'illustration 2, qui montre `à quoi la page HTML ressemble lorsqu'elle est affichée `à l'utilisateur. Le fichier bonus.html a deux champs de saisie où l'utilisateur peut saisir son numéro de sécurité sociale et un multiplicateur. Quand l'utilisateur clique sur le bouton Submit, BonusServlet reçoit les données de l'utilisateur final, cherche le bean de session, et transmet les données de l'utilisateur au bean de session. Le bean de session calcul un bonus et renvoie la valeur du bonus à la servlet. La servlet retourne alors une autre page HTML qui contient la valeur du bonus pour que l'utilisateur la voie.
L'illustration 3 présente les flux de données entre le navigateur et le bean de session. Le bean de session est exécuté sur le serveur d'application J2EE.
Le plus intéressant dans le code HTML du formulaire est l'alias utilisé pour invoquer BonusServlet. Quand l'utilisateur clique sur le bouton d'envoi (Submit) du formulaire HTML, BonusServlet est invoquée car elle est mappée sous le nom BonusAlias durant la phase d'assemblage de l'application d'écrite dans Assemblage de l'application J2EE (page ??)
Cet exemple suppose que bonus.html est dans le répertoire /home/nome_user/J2EE/ClientCode sous Unix. Ici comme par la suite, les utilisateurs Windows peuvent inverser le signe divisé (/) pour obtenir le nom de chemin correct sur leur plate-forme (\).
<HTML> <BODY> <BLOCKQUOTE> <H3>Bonus Calculation</H3> <FORM METHOD="GET" ACTION="BonusAlias"> <P>Enter social security Number:</P> <P><INPUT TYPE="TEXT" NAME="SOCSEC"></INPUT></P> <P>Enter Multiplier:</P> <P><INPUT TYPE="TEXT" NAME="MULTIPLIER"></INPUT></P> <P><INPUT TYPE="SUBMIT" VALUE="Submit"><INPUT TYPE="RESET"></P> </FORM> </BLOCKQUOTE> </BODY> </HTML>
Cet exemple suppose que le fichier BonusServlet.java est dans le répertoire /home/nome_user/J2EE/ClientCode on Unix. A l'exécution, le code de la servlet fait les actions suivantes :
Les sections suivantes d'écrivent les différentes parties du code source de la servlet. La servlet est présentée dans son intégralité dans la section Code source de la servlet.
Le code de la servlet commence par des directives d'importation des paquetages suivants :
La méthode BonusServlet.init cherche l'interface home du bean de session et en crée une instance. La méthode utilise le nom JNDI spécifié durant l'assemblage des composants (calcs) pour obtenir une référence de l'interface home par son nom. La ligne suivante passe la référence et la classe d'interface home à la méthode PortableRemoteObject.narrow pour s'assurer que la référence peut être convertie en type CalcHome.
InitialContext ctx = new InitialContext();
Object objref = ctx.lookup("calcs");
homecalc = (CalcHome)PortableRemoteObject.narrow(obj ref, CalcHome.class);
La liste des paramètres de la méthode doGet contient des objets request et response. Le navigateur envoie une requête à la servlet et la servlet renvoie une réponse au navigateur. L'implémentation de cette méthode accède aux informations de l'objet request pour trouver qui a émis la requête, quelles données de formulaires contient la requête, et quelles entêtes HTTP ont été émises, et utilise l'objet réponse pour créer une page HTML de réponse à la requête du navigateur.
La méthode doGet déclenche une IOException sil y a un problème
d'entrée ou de sortie quand elle traite la requête, et une
ServletException si la requête ne peut pas être traitée. Pour calculer
la valeur du bonus, la méthode doGet crée une interface home et
appelle sa méthode calcBonus.
public void doGet (HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
String socsec = null;
int multiplier = 0;
double calc = 0.0;
PrintWriter out;
response.setContentType("text/html");
String title = "EJB Example";
out = response.getWriter();
out.println("<HTML><HEAD><TITLE>)
out.println(title);
out.println("</TITLE></HEAD><BODY>");
try{
//Retrieve Bonus and Social Security Information
String strMult = request.getParameter("MULTIPLIER");
Integer integerMult = new Integer(strMult);
multiplier = integerMult.intValue();
socsec = request.getParameter("SOCSEC");
//Calculate bonus
double bonus = 100.00;
theCalculation = homecalc.create();
calc = theCalculation.calcBonus(
multiplier, bonus);
}catch(Exception CreateException){
CreateException.printStackTrace();
}
//Display Data
out.println("<H1>Bonus Calculation</H1>");
out.println("<P>Soc Sec: " + socsec + "<P>");
out.println("<P>Multiplier: " +
multiplier + "<P>");
out.println("<P>Bonus Amount: " + calc + "<P>");
out.println("</BODY></HTML>");
out.close();
}
Voici le code source complet.
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import javax.naming.*;
import javax.rmi.PortableRemoteObject;
import Beans.*;
public class BonusServlet extends HttpServlet {
CalcHome homecalc;
public void init(ServletConfig config)
throws ServletException{
//Look up home interface
try{
InitialContext ctx = new InitialContext();
Object objref = ctx.lookup("calcs");
homecalc = (CalcHome)PortableRemoteObject.narrow(objref, CalcHome.class);
} catch (Exception NamingException) {
NamingException.printStackTrace();
}
}
public void doGet (HttpServletRequest request,HttpServletResponse response)
throws ServletException, IOException {
String socsec = null;
int multiplier = 0;
double calc = 0.0;
PrintWriter out;
response.setContentType("text/html");
String title = "EJB Example";
out = response.getWriter();
out.println("<HTML><HEAD><TITLE>");
out.println(title);
out.println("</TITLE></HEAD><BODY>");
try{
Calc theCalculation;
//Get Multiplier and Social Security Information
String strMult = request.getParameter("MULTIPLIER");
Integer integerMult = new Integer(strMult);
multiplier = integerMult.intValue();
socsec = request.getParameter("SOCSEC");
//Calculate bonus
double bonus = 100.00;
theCalculation = homecalc.create();
calc = theCalculation.calcBonus(multiplier, bonus);
} catch(Exception CreateException){
CreateException.printStackTrace();
}
//Display Data
out.println("<H1>Bonus Calculation</H1>");
out.println("<P>Soc Sec: " + socsec + "<P>");
out.println("<P>Multiplier: " + multiplier + "<P>");
out.println("<P>Bonus Amount: " + calc + "<P>");
out.println("</BODY></HTML>");
out.close();
}
public void destroy() {
System.out.println("Destroy");
}
}
Un bean de session représente une conversation passagère avec un client. Si le serveur ou le client plante, le bean de session et ses données sont perdues. Par comparaison, les beans d'entité sont persistants et représentent les données d'une base de données. Si le serveur ou le client plante, les services sous-jacents garantissent que les données du beans d'entité sont sauvegardées.
Comme le bean effectue un simple calcul à la demande de Bonus Servlet, et que le calcul peut être recommencé en cas de plantage, il est judicieux d'utiliser un bean de session pour cet exemple.
L'illustration 4 montre comment les composants applicatifs servlet et bean de session fonctionnent comme une application J2EE complète une fois qu'ils sont assemblés et d'éployés. Le container, représenté par une boîte ombrée, est l'interface entre le bean de session et les fonctionnalités bas niveau et spécifiques `à la plate-forme sur lesquels le bean de session s'appuie. Le container est crée durant le déploiement.
Illustration 4 - Composants de l'application
Les sections suivantes présentent le code source du bean de session. Cet exemple suppose que les fichiers CalcBean.jav, Calc.java et CalcHome.java sont situés dans le répertoire /net/home/lmaitre/J2EE/Beans sous Unix. La directive package Beans au début de l'interface CalcBean et des fichiers de classe porte le même nom que le nom du répertoire où ces fichiers sont stockés. Quand ces fichiers seront compilés, ils seront compilés à partir du répertoire Beans sus - mentionné et le nom du paquetage Beans (ou répertoire) sera préfixé avec un signe divisé (/) à l'interface et aux fichiers en cours de compilation. Voir Compilation du bean de session.
NOTE : Bien que cet exemple montre comment 'écrire un bean de session d'exemple, il est aussi possible d'acheter des beans auprès d'un prestataire et de les assembler dans une application J2EE.
BonusServlet ne fonctionne pas directement avec le bean de session, mais crée une instance de son interface home. L'interface home 'étend l'interface EJBHome et a une méthode create pour créer le bean de session dans son conteneur. CreateException est déclenchée si une erreur de transmission intervient durant l'exécution d'une procédure distante.
package Beans;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBHome;
public interface CalcHome extends EJBHome {
Calc create() throws CreateException, RemoteException;
}
Quand l'interface home est crée, le serveur d'application J2EE crée l'interface distante et le bean de session. L'interface distante étend EJBObject et déclare la méthode calcBonus pour calculer la valeur du bonus. Cette méthode peut déclencher une javax.rmi.RemoteException, et est implémentée dans la classe CalcBean.
package Beans;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
public interface Calc extends EJBObject {
public double calcBonus(int multiplier, double bonus)
throws RemoteException;
}
La classe du bean de session implémente l'interface SessionBean et fournit le comportement de la méthode calcBonus. Les méthodes setSessionContext et ejbCreate sont appelées dans cet ordre par le conteneur après que BonusServlet ai appelé la méthode create de CalcHome.
Les méthodes vides sont celles de l'interface SessionBean. Ces méthodes sont appelées par le conteneur de bean. Vous n'avez pas à fournir de comportement pour ces méthodes à moins que vous n'ayez besoin de fonctionnalités additionnelles quand le bean est, par exemple, crée ou enlevé du conteneur.
package Beans;
import java.rmi.RemoteException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
public class CalcBean implements SessionBean {
public double calcBonus(int multiplier, double bonus) {
double calc = (multiplier*bonus);
return calc;
}
//Ces methodes peuvent etre redefinies par le bean
public void ejbCreate() { }
public void setSessionContext(SessionContext ctx) { }
public void ejbRemove() { }
public void ejbActivate() { }
public void ejbPassivate() { }
public void ejbLoad() { }
public void ejbStore() { }
}
Pour s'épargner du temps de saisie, le plus facile pour compiler le bean de session et la servlet est de créer un script (sous Unix) ou un fichier batch (sous Windows).
Compilation du bean de session
#!/bin/sh
cd /net/home/lmaitre/J2EE
J2EE_HOME=/net/home/lmaitre/J2EE/j2sdkee1.3
CPATH=.:$J2EE_HOME/lib/j2ee.jar
javac -d . -classpath "$CPATH" Beans/CalcBean.java Beans/CalcHome.java Beans/Calc.java
cd \net\home\lmaitre\J2EE
set J2EE_HOME=\net\home\lmaitre\J2EE\j2sdkee1.3
set CPATH=.;%J2EE_HOME%\lib\j2ee.jar
javac -d . -classpath %CPATH% Beans/CalcBean.java Beans/CalcHome.java Beans/Calc.java
#!/bin/sh
cd /home//J2EE/ClientCode
J2EE_HOME=/net/home/lmaitre/J2EE/j2sdkee1.3
CPATH=.:$J2EE_HOME/lib/j2ee.jar:/net/home/lmaitre/J2EE
javac -d . -classpath "$CPATH" BonusServlet.java
cd \net\home\lmaitre\J2EE\ClientCode
set J2EE_HOME=\net\home\lmaitre\J2EE\j2sdkee1.3
set CPATH=.;%J2EE_HOME%\lib\j2ee.jar;\net\home\lmaitre\J2EE
javac -d . -classpath %CPATH% BonusServlet.java
Vous avez besoin de démarrer le serveur d'application J2EE pour déployer et exécuter l'exemple. La commande pour démarrer le serveur se trouve dans le répertoire bin sous votre installation de J2EE. Si vous avez réglé votre PATH pour lire le répertoire bin, allez dans le répertoire J2EE (ainsi ce que vous taperez correspondra exactement à ce que vous lisez) et tapez :
j2ee -verbose
NOTE : Parfois le serveur J2EE ne démarrera pas si Outlook est lancé.
Si cela ne marche pas, tapez ce qui suit à partir du répertoire J2EE :
j2sdkee1.2.1/bin/j2ee -verbose
j2sdkee1.2.1\bin\j2ee -verbose
L'option verbose affiche des messages d'information à la ligne de commande pendant le démarrage du serveur. Quand vous voyez apparaître J2EE server startup complete, vous pouvez lancer l'outil de déploiement. Pour l'instant, vous pouvez ignorer les autres messages qui défilent à l'écran.
Pour assembler et d'éployer une application J2EE, vous devez lancer l'outil de déploiement. Si vous avez réglé votre chemin pour lire le répertoire bin, allez dans le répertoire J2EE (ainsi ce que vous taperez correspondra exactement `à ce que vous lisez) et tapez :
deploy tool
Si cela ne marche pas, tapez ce qui suit à partir du répertoire J2EE :
j2sdkee1.2.1/bin/deploytool
j2sdkee1.2.1\bin\deploytool
NOTE : Si une erreur d'accès mémoire survient lors du lancement de deploytool, ajoutez une variable d'environnement appelée JAVA_FONTS et faites-là pointer sur C:\<répertoire de fontes>. Par exemple c:\winnt\fonts. De même, si une NullPointerException venant de BasicFileChooserUI survient en démarrant deploytool, assurez-vous de ne pas avoir démarrer le logiciel à partir du répertoire racine (ex. C:\). Si vous l'exécutez de n'importe où ailleurs, comme par exemple le répertoire bin de votre installation j2sdkee1.3, vous ne rencontrerez pas ce problème.
L'outil de déploiement présenté dans l'illustration 5 comporte 2 fenêtres principales. La fenêtre de gauche affiche la File Tree View qui présente les applications J2EE et leurs composants. La Servers Tree View indique que le serveur est exécuté sur la machine locale et quelles applications sont installées sur le serveur. La fenêtre Inspecting à droite affiche des informations sur l'application ou le composant sélectionné. Au cours des étapes pour assembler l'application J2EE d'exemple, vous verrez apparaître des informations dans la fenêtre Inspecting et les File et Server Tree views.
Illustration 5 Deployment Tool
Note : Sur la droite de la fenêtre Inspecting se trouve un bouton Undeploy grisé. Après le déploiement de l'application, vous verrez l'application listée dans la fenêtre Inspecting. Vous pourrez alors cliquer sur Undeploy pour désinstaller l'application, effectuer vos changements, et redéployer l'application sans avoir à arrêter et redémarrer le serveur d'application.
L'assemblage d'une application J2EE implique la création d'une nouvelle application, et l'ajout de composants `à l'application. Voici un résumé des étapes de l'assemblage, qui sont exposées en détail par la suite.
Les composants J2EE sont assemblés dans un fichier d'application J2EE Enterprise Archive Bean (EAR).
Le nom BonusApp est maintenant listé dans la fenêtre Local Application, et la fenêtre Inspector `à droite affiche le nom, l'emplacement et des informations sur le contenu de BonusApp. Les meta-informations affichées dans la fenêtre de contenu décrivent le fichier JAR et l'application J2EE, et fournissent des informations sur l'exécution de l'application.
Les enterprise beans (d'entité et de session) sont livrés dans des fichiers Java Archive (JAR).
Note importante : La boîte de dialogue « Add Contents to JAR » doit ressembler `à celle de l'illustration 6. Les classes « Enterprise Bean JAR » doivent être affichées dans le répertoire Beans et le nom du répertoire préfixé aux noms des classes.
Illustration 6 : Sélection des fichiers de classes du bean de session
Vérifier que le fichier JAR a bien été ajouté à l'application J2EE :
Les composants web (servlets, ou Java Server Pages) sont livrées dans des fichiers Web Archives (WAR).
Note: Assurez-vous d'ajouter bonus.html avant d'ajouter BonusServlet.class.
Illustration 7 Ajout de BonusServlet.class
Illustration 8 Ajout de bonus.html
Dans le panneau « Content », vous pouvez voir que le fichier WAR contient un fichier XML avec des informations sur la structure et les attributs de l'application, le fichier bonus.html, et le fichier de la classe BonusServlet. Le format des fichiers WAR précise que toutes les classes servlets doivent ^être stockés sous WEB-INF/classes. Cependant, lorsque le fichier WAR est déployé, la classe BonusServlet est placée dans un contexte racine situé sous public_html. Cet emplacement est une convention sur les serveurs compatibles Servlet 2.2.
Pour changer le nom ou la description :
Avant de pouvoir déployer l'application BonusApp et ses composants, vous devez choisir quel nom JNDI BonusServlet utilisera pour contacter le bean de session CalcBean et choisir le contexte racine où seront déployés les composants web.
Figure 9 Arborescence de répertoire du contexte racine
Avant de déployer l'application, c'est une bonne idée d'utiliser le verifier. Le verifier va examiner les composants de l'application à la recherche d'erreurs telles que des méthodes manquantes dans les enterprise bean, erreurs que le compilateur ne repère pas.
Note : Ne pas cocher la case Return Client Jar Box. La seule fois où vous aurez besoin de cocher cette case sera lorsque vous d'éploierez des applications autonomes comme programme client. Cet exemple utilise une servlet et une page HTML, c'est pourquoi la case n'est pas cochée. Cocher cette case entraîne la création d'un fichier JAR avec toutes les informations nécessaires au déploiement d'une application autonome (stand-alone).
Le serveur web écoute le port 8000 par défaut. Pour ouvrir la page bonus.html, taper l'URL http://localhost:8000/BonusRoot/bonus.html, qui est l'emplacement où l'outil de déploiement a copié le fichier HTML.
Note : Si vous avez besoin d'utiliser un autre port car votre port 8000 est utilisé par quelque chose d'autre, modifier le fichier web.properties qui se trouve dans le répertoire ~/J2EE/j2sdk1.3/config et redémarrer le serveur J2EE.
Résultat du calcul
Numéro de Sécu : 777777777
Multiplicateur : 25
Bonus : 2500.0
Le menu « Tools » comporte deux options particulièrement intéressantes : « Update Application Files » et « Update and redeploy Application ». Ces options permettent de modifier le code source et de redéployer l'application facilement. Faites simplement vos modifications, recompilez le code, et choisissez l'une de ces options de menu.
La version originale de ce tutorial (en anglais) est disponible sur le site de Sun ainsi que de nombreux autres exercices. Java est une marque déposée de Sun Microsystems.