Vous êtes sur la page 1sur 211

Serialisation

 La sérialisation est un procédé introduit dans le JDK version 1.1 qui permet de
rendre un objet persistant. Cet objet est mis sous une forme sous laquelle il pourra
être reconstitué à l'identique. Ainsi il pourra être stocké sur un disque dur ou
transmis au travers d'un réseau pour le créer dans une autre JVM. C'est le procédé
qui est utilisé par RMI. La sérialisation est aussi utilisée par les beans pour
sauvegarder leurs états.
 Au travers de ce mécanisme, Java fourni une façon facile, transparente et standard
de réaliser cette opération : ceci permet de facilement mettre en place un
mécanisme de persistance. Il est de ce fait inutile de créer un format particulier
pour sauvegarder et relire un objet. Le format utilisé est indépendant du système
d'exploitation. Ainsi, un objet sérialisé sur un système peut être réutilisé par un
autre système pour récréer l'objet.
 L'ajout d'un attribut à l'objet est automatiquement pris en compte lors de la
sérialisation. Attention toutefois, la déserialisation de l'objet doit se faire avec la
classe qui a été utilisée pour la sérialisation.
 La sérialisation peut s'appliquer facilement à tous les objets.
Cliquez sur l'icône pour ajouter une image

Introduction aux JFC/Swing


Qu’est ce que les JFC?
 JFC  Java Foundation Classes
 5 parties :
 Java 1.1 Abstract Window Toolkit (AWT)
 Java2D API
 ***Swing***
 Native Drag and Drop, et Copy and Paste
 API pour l'Accessibilité (aveugle, ...)
Qu’est-ce que Swing?
 Abstract Window Toolkit (AWT) V2
 100% Pure Java
 Nécessite le JDK 1.1.2 ou supérieur
 Fait parti des JFC
 Composants
 Nouveaux composants de haut niveau
 Look & Feel modulable
Philosophie Swing

 Une directive de conception fondamentale est


«rendre les choses simples faciles, et les choses
difficiles possibles»
 Ensemble plus Riche de Composants
 Remplace l’AWT
 Ajoute des composants plus complexes
 Composants Swing sont basés sur Java
 Si des problèmes, les même problèmes partout
 100% Pure Java
 Java 1.1.2+ nécessaire
 Uniquement le modèle d'événements de Java 1.1
Les Particularités de Swing

 Inclut avec les API Java 2 (JDK 1.2)


 Utilisable dans les Environnements Java 1.1
 javax.swing.*
 Ne peut être dans la hiérarchie java.* et être
téléchargé par des browsers JDK 1.1
Deux Vues des Swing

 Alternative aux composants AWT Java 1.1


 modèle d’événements 1.0 NON supporté
 Quelques nouveaux composants.
 Interface Model/View/Controller
 Séparer les données des vues écrans et des interactions
 Plus de travail nécessaire
Les classes Swing
L’ensemble des composants Swing
 Exemple de programme basé sur les Swing
De l’AWT aux SWING

 Pour la plupart des composants, ajouter J avant le


nom
 Button  JButton, Applet  JApplet, …
 Modèle d'événements Java 1.1
 Les containers Swing intègrent le double-buffer
 Evite le scintillement des composants Swing
Le Look and Feel
 Swing propose plusieurs aspects et utilisation de
l’interface graphique : Look and Feel (L&F).
 Le Look and Feel de Java est appelé Metal ou Java
L&F : c’est le L&F par défaut. On peut aussi avoir
les L&F Motif, Windows et Macintosh (contrôlé
par des droits) et même se créer son propre L&F.
Le Look and Feel
 On peut connaître les divers L&F utilisables sur
une machine à l’aide de la méthode statique
UIManager.getInstalledLookAndFeels(); qui
retourne un tableau de
UIManager.LookAndFeelInfo
Le Look and Feel

Les différents L&F de la plate-forme Windows


Le Look and Feel

 Personnaliser l ’aspect des composants


graphiques :
 indépendant des plate-formes : style Metal
 dépendant du système :windows, ...
Le Look and Feel
Le Look and Feel

 Utiliser le look d ’affichage Metal


try {
UIManager.setLookAndFeel (
"javax.swing.plaf.metal.MetalLookAndFeel");
} catch (java.lang.ClassNotFoundException e)
{ // Ne peut changer le look and feel
}
 Ou

try {
UIManager.setLookAndFeel (
UIManager.getCrossPlatformLookAndFeelClassName());
} catch (java.lang.ClassNotFoundException e)
{ // Ne peut changer le look and feel
}
Le Look and Feel

 Utiliser le look d ’affichage du système

try {
UIManager.setLookAndFeel (
UIManager.getSystemLookAndFeelClassName());
} catch (java.lang.ClassNotFoundException e)
{ // Ne peut changer le look and feel
}
Swing vs. AWT 1.1
class MyActionListener implements ActionListener {
public void actionPerformed (ActionEvent e) {
System.out.println (e.getActionCommand());
}
}
...
ActionListener al = new MyActionListener();
Button b1 = new Button ("Hello");
b1.addActionListener (al);
add (b1, BorderLayout.NORTH);

JButton b2 = new JButton ("World");


b2.addActionListener (al);
add (b2, BorderLayout.SOUTH);
Le modèle MVC
 Swing utilise fondamentalement une architecture
d’interface homme-machine inspiré de Smalltalk :
l’architecture Model-View-Controller.
 Cette architecture est composée de trois parties :
 le modèle qui est la partie décrivant les données à
afficher
 la vue qui est la représentation graphique de ces
données
 le contrôleur qui est la partie qui traite des interactions
du composant avec l’utilisateur.
Le modèle MVC
Intérêts de l’architecture MVC
 meilleure modularité
 possibilité d’associer plusieurs vues distinctes à un
même modèle (histogramme, courbes, camembert,
valeur flottante, ...)
 possibilité de changer l’implémentation d’un
modèle (optimisation, réorganisation, ...) sans rien
changer aux vues et aux contrôleurs.
Vue des paquetages Swing

 La collection Swing est constitué de 17


paquetages
 javax.swing
 le paquetage Swing racine définit les
composants, les adapters, les modèles par
défaut des composants, et les interfaces pour
tous les modèles et les containers.
Vue des paquetages Swing
 javax.swing.border
 Le paquetage border déclare l ’interface Border et ses
classes, afin de définir les styles d ’affichage
spécifiques aux bords des composants.
 javax.swing.colorchooser
 Le paquetage colorchooser contient les classes pour
choisir la couleur du composant.
Vue des paquetages Swing
 javax.swing.event
 Le paquetage event est pour les types d ’événements et
les listeners spécifiques des composants Swing. En
plus des types java.awt.event, les composants Swing
peuvent générer leurs propres types d ’événements.
 javax.swing.filechooser
 le paquetage filechooser contient les classes pour la
sélection de fichiers.
Vue des paquetages Swing
 javax.swing.plaf.*
 Le paquetage look-and-feel (Pluggable Look And Feel)
contient les classes (delegates) de l ’Interface
Utilisateur (UI) qui implémentent les aspects des
composants Swing. javax.swing.table
 Le paquetage table définit les interfaces et les classes
pour les tableaux.
Vue des paquetages Swing
 javax.swing.text
 Le paquetage text contient les classes pour le
framework des documents Swing.
 javax.swing.text.html.*
 Le paquetage text.html contient les classes pour
l ’analyse et l ’affichage de l ’HTML version 3.2.
Vue des paquetages Swing

 javax.swing.text.rtf
 Le paquetage text.rtf définit les classes pour le
rendu de documents basic Rich Text Format
(RTF).
 javax.swing.tree
 Le paquetage tree contient les interfaces et les
classes qui supportent l ’affichage sous forme
d ’arbres (explorateur Window).
Vue des paquetages Swing

 javax.swing.undo
 Le paquetage undo permet le support des
classes pour implémenter les capacités du
undo/redo dans une GUI.
 javax.accessibility
 Le paquetage JFC Accessibility est inclu avec
les classes Swing, pour le support d ’outils
d ’aide aux personnes handicapées.
Hiérarchie Swing
Hiérarchie Swing
Composants de haut niveau

 Toutes les sous-classes de Window, non de


JComponent
 Non portables, ils ont des composants peer
 Composants ajoutés au panel de contenu
 interface RootPaneContainer - délégué au container
Utilisation du RootPaneContainer
 Ne pas ajouter de composants directement dans les
containers de haut niveau :
 aFrame.add (new Button (“Help”));
 Ajouter au panel de contenu:“content pane”
 aJFrame.getContentPane().add (…);
 possède un Layout manager - par défaut: BorderLayout
 JDialog, JFrame, JWindow, JApplet, JInternalFrame
Exemple de JFrame
public class FrameTester {
public static void main (String args[]) {
JFrame f = new JFrame ("JFrame Example");
Container c = f.getContentPane();
c.setLayout (new FlowLayout());
for (int i = 0; i < 5; i++) {
c.add (new JButton ("No"));
c.add (new Button ("Batter"));
}
c.add (new JLabel ("Swing"));
f.setSize (300, 200);
f.show();
}
}
 Une directive de conception fondamentale est «
rendre les choses simples faciles, et les choses
difficiles possibles ».
multithreading
PLAN
 Introduction
 Définition
 Raison d’être
 Création de Thread
 Par implémentation
 Par héritage
 Gestion de Thread
 Méthodes de gestion
 Diagrammes d’état
Qu’est-ce qu’un Thread?
 Un ordinateur qui exécute un programme :
 Possède un CPU
 Stocke le programme à exécuter

 Possède une mémoire manipulée par le programme

 Multitasking géré par l’OS

 Un thread (« file ») a ces mêmes capacités


 A accès au CPU
 Gère un processus

 A accès à la mémoire, qu’il partage avec d’autres files

 Multithreading géré par la JVM


Definition
 Une thread (appelée aussi processus léger ou activité)
est une suite d'instructions à l'intérieur d'un process.
 Les programmes qui utilisent plusieurs threads sont
dits multithreadés.
 Les threads peuvent être créés comme instance d'une
classe dérivée de la classe Thread. Elles sont lancées
par la méthode start(), qui demande à l'ordonanceur de
thread de lancer la méthode run() de la thread. Cette
méthode run() doit être implantée dans le programme.
Notion de threads
Un processus multi-threads

Un processus avec
un seul thread Thread 1 Thread 2 Thread 3

Il faut voir une processus comme le code correspondant au programme.


Le thread est l'entité qui exécute le code.
Toute application comporte au moins un thread appelé
« thread pincipal ».
Pourquoi le multithreading?
 Un programme moderne est composé de
 Une interface graphique
 Quelques composantes pouvant agir de manière autonome

 Sans multithreading
 Les composantes ne pourraient agir que lorsque l’interface est
suspendue

 Plus généralement, le multithreading


 Permet de réaliser plusieurs processus indépendants en parallèle
 Permet de gérer les files d’attente
 Permet au besoin de synchroniser les différents processus entre eux
Exemple
class DeuxThreadAsynchrones {
public static void main(String args[ ]) {
new UneThread("la thread 1").start();
new UneThread("la seconde thread").start();
}
}
class UneThread extends Thread {
public UneThread(String str) {
super(str);
}
public void run() {
for (int i=0; i<10; i++) {
System.out.println(i+" "+getName());
try {sleep((int)(Math.random()*10));}
catch (InterruptedException e){}
}
System.out.println(getName()+" est finie");
}
}
Création de Thread
 Par implémentation de l’interface Runnable
 Usage
 public void MaClasse implements Runnable
 Avantages et inconvénients
 Meilleur sur le plan orienté objet
 La classe peut hériter d’une autre classe
 Consistance
 Par héritage de la classe Thread elle-même
 Usage
 public void MaClasse extends Thread
 Avantages et inconvénients
 Code simple (l’objet est un Thread lui-même)
 La classe ne peut plus hériter d’une autre classe
Quelle solution choisir ?
 Sous-classer Thread
 Lorsqu’on désire paralléliser une classe qui n’hérite pas déjà
d’une autre classe
 Implémenter Runnable
 Lorsque la super classe est imposée (exemple : une applet
que l’on désire paralléliser),
 Ou lorsqu’un partage de contexte est requis par un nombre
quelconque de threads
 En général, le démarrage du ou des threads associés à
l’objet est effectué par l’objet lui-même
(new Thread(this)).start();
Création de Thread
public class MaFile implements Runnable {
public void run(){
byte[] buffer=new byte[512];
int i=0;
while(true){
if(i++%10==0)System.out.println(""+i+" est divisible par 10");
if (i>101) break;
}
}
}
public class LanceFile {
public static void main(String[]arg){
Thread t=new Thread(new MaFile());
t.start(); Le constructeur de la classe Thread
} attend un objet Runnable
}
en argument
Création de Thread
public class MyThread extends Thread {
public void run(){
byte[] buffer=new byte[512];
int i=0;
while(true){
if(i++%10==0) System.out.println(""+i+" est divisible par 10");
if(i>101) break;
}
}
}

public class LaunchThread{


public static void main(String[]arg){
MyThread t=new MyThread(); Grâce à l’héritage, un objet de type
t.start(); MyThread est lui-même Runnable,
} on peut donc appeler un constructeur
} sans argument
Gestion des Thread
 t.start()
Appeler cette méthode place le thread dans l’état “runnable”
 Eligible par le CPU
 t.yield() throws InterruptedException
La VM arrête la file active et la place dans un ensemble de files activables.
(runnable state)
La VM prend une file activable et la place dans l’état actif (running state)
 t.sleep(int millis) throws InterruptedException
La VM bloque la file pour un temps spécifié (état « d’attente »)
 t.join() throws InterruptedException
Met la file en attente jusqu’au moment où la file t est terminée
(a fini sa méthode run()). Le thread appelant redevient alors activable.
Gestion des Thread
 Thread.yield() throws InterruptedException
La VM arrête la file active et la place dans un ensemble de files activables.
(runnable state)
La VM prend une file activable et la place dans l’état actif (running state)
 t.sleep(int millis) throws InterruptedException
La VM bloque la file pour un temps spécifié (état « d’ attente »)
 t.join() throws InterruptedException
Met la file en attente jusqu’au moment où la file t est terminé (a fini sa
méthode run()). Le thread appelant redevient alors activable.
 t.currentThread() throws InterruptedException
Donne le thread actuellement en cours d'exécution
Autre opérations d'un thread

 Pour arrêter un thread on utilise l'opération « stop » :


public final void stop();

 Pour connaître la priorité d'un thread, on emploi la méthode


« getPriority » :
public final int getPriority();

 De plus, pour fixer la priorité d'un thread, on utilise « setPriority » :


public final void setPriority(int newPriority);
Gestion des Thread
Diagrammes d’état

Object.notify()
t.sleep()
Object.notifyAll()
En attente
début fin
Object.wait()
Fin du sleep()

t.yield()

t.start()

Activable Active
Scheduler Fin de run()
Ensemble de files éligibles Une des files éligibles, pas
nécessairement celle avec la plus
grande priorité.
Comment récupérer le thread courant ?

 Lorsqu'une méthode est exécutée, elle peut l'être par plusieurs


threads.

 Pour connaître le thread courant, elle peut utiliser l'opération


« currentThread » :

public static Thread currentThread();

 A partir de la référence vers le thread récupéré, on peut appliquer


toutes les opérations traditionnelles aux threads.
L'opération « currentThread » peut être également
utilisée pour récupérer le thread principal.
Exemple
// utilisation de threads
import java.io.*;
import java.util.*;
public class thread2{
public static void main(String[] arg) {
// init thread courant
Thread main=Thread.currentThread();
// on donne un nom au thread courant
main.setName("myMainThread");
// début de main
System.out.println("début du thread " +main.getName());
// création de threads d'exécution
Thread[] tâches=new Thread[5];
for(int i=0;i<tâches.length;i++){
// on crée le thread i
Exemple
tâches[i]=new Thread() {
public void run() {
affiche();
}
};//déf tâches[i]
// on fixe le nom du thread
tâches[i].setName(""+i);
// on lance l'exécution du thread i
tâches[i].start();
}//for
// fin de main
System.out.println("fin du thread " +main.getName());
}//Main
public static void affiche() {
// on récupère l'heure
Calendar calendrier=Calendar.getInstance();
String H=calendrier.get(Calendar.HOUR_OF_DAY)+":"
+calendrier.get(Calendar.MINUTE)+":"
+calendrier.get(Calendar.SECOND);
// affichage début d'exécution
System.out.println("Début d'exécution de la méthode affiche dans le Thread " +
Thread.currentThread().getName()+ " : " + H);
Exemple

// mise en sommeil pendant 1 s


try{
Thread.sleep(1000);
}catch (Exception ex){}
// on récupère l'heure
calendrier=Calendar.getInstance();
H=calendrier.get(Calendar.HOUR_OF_DAY)+":"
+calendrier.get(Calendar.MINUTE)+":"
+calendrier.get(Calendar.SECOND);
// affichage fin d'exécution
System.out.println("Fin d'exécution de la méthode affiche dans le Thread "
+Thread.currentThread().getName()+ " : " + H);
}// affiche
}//classe
Priorités
 Principes
 Java offre la possibilité de fixer les priorités des dif-férents threads d’un
processus.
 Niveaux de priorités absolus (gestion simplifiée).
 Seuls les threads à l’état actif s’exécutent et peu-vent partager le CPU.
 Le partage de temps entre threads d’une même priorité dépend de l’OS.
 Les threads actifs de plus hautes priorité se parta-gent le CPU (si l’OS le
permet).
 Méthodes
 void setPriority(int) modifie la priorité du receveur. Le paramètre appartient à
l’intévalle [MIN_PRIORITY, MAX_PRIORITY]. Dans le cas contraire
IllegalArgumentException est levée.
 int getPriority() permet de connaître la priorité d’un thread.
 Le niveau de priorité “normal” est donné par la constante NORM_PRIORITY.
Accès concurrents

 Que se passe t'il si plusieurs threads accèdent à la même méthode ou à la même


ressource au même instant ?
 Comportement imprévisible selon les applications
 problématique des accès concurrents

 Pour qu'une méthode ne soit pas utilisée par plus d'un thread à la fois, il faut la
spécifier « synchronized » :

synchronized type_de_retour nom_methode ( liste des paramètres )

Un même thread pourra tout de même appeler


récursivement cette opération.
Les verrous
 Un verrou ( en anglais « mutex » ) est un concept qui lorsqu'il est activé
empêche les threads qui n'ont pas activés le verrou d'utiliser le code
verrouillé.

 Tant que le verrou n'est pas levé, seul un thread peut être actif dans le code
verrouillé.

 Chaque objet java peut servir de verrou.

 Comment créer une zone verrouillée ?


 On applique « synchronized » sur un objet.
Synchronisation
 Certains accès simultanés à une ressource peuvent être
gênants.
 Gérer les concurrences d’accés à une méthode
 Cela se fait en déclarant la méthode synchronized
public synchronized void maMethode() {
...
}

 Lorsqu’un thread exécute cette méthode sur un objet, un


autre thread ne peut pas l’exécuter pour le même objet.
 En revanche, il peut exécuter cette méthode pour un autre
objet.
 Contrôler l’accés à un objet
 Déclarer l’objet synchronized
public void maMethode() {
...
synchronized(objet) {
objet.methode();
}
...
}

 L’accès à l’objet passé en paramètre de synchronized(Object obj)


est réservé à un thread et un seul.
 Pour éviter une dégradation des performances il faut que les
sections critiques soient courtes et utilisées à bon escient.
Thread en tâche de fond (démon)
 Il existe une catégorie de threads qualifiés de
démons : leur exécution peut se poursuivre même
après l‘arrêt de l'application qui les a lancés.
 Le thread doit d'abord être créé comme thread
standard puis transformé en demon par un appel à
la méthode setDaemon() avec le paramètre true.
Cet appel se fait avant le lancement du thread,
sinon une exception de type
IllegalThreadStateException est levée.
Groupes de threads
 Il est possible de regrouper des threads selon différents
critères. Il suffit de créer un objet de la classe ThreadGroup
et de lui affecter les différents threads. Un objet
ThreadGroup peut contenir des threads mais aussi d'autres
objets de type ThreadGroup.
 Groupe de threads par défaut : main
 Constructeurs:
 ThreadGroup(String nom) création d'un groupe avec attribution
d'un nom
 ThreadGroup(ThreadGoup groupe_parent, String nom) création
d'un groupe à l'intérieur du groupe spécifié avec l'attribution d'un
nom
Groupes de threads
Exemple :
package com.moi.test;
public class LanceurDeThreads {
public static void main(String[] args) {
ThreadGroup tg = new ThreadGroup("groupe");
Thread t1 = new Thread(tg,new MonThread3(), "numero 1");
Thread t2 = new Thread(tg,new MonThread3(), "numero 2");
}
}

 L'un des avantages de la classe ThreadGroup est de


permettre d'effectuer une action sur tous les threads
d'un même groupe.
Exercice
Producteur-consommateur : un exemple
Un producteur est une thread qui dépose des jetons numérotés dans
un chapeau qui ne peut contenir qu'un seul jeton. Un
consommateur prend ce jeton qui doit être présent dans le
chapeau. Donc :
- le producteur doit s'arrêter de déposer des jetons lorsqu'il y en a
déjà un et doit être informer qu'un jeton a été retiré.
- le consommateur ne peut pas prendre de jeton s'il n'y en a pas
(arrêt du consommateur) et doit être informé lorqu'un jeton a été
déposé.
L'objet le plus à même pour avertir le producteur et le
consommateur est le chapeau lui même.
Exercice
Avec ce même programme, il peut y avoir plusieurs
producteurs et plusieurs consommateur (repérés par
des numéros) mais toujours un seul chapeau ayant un
emplacement pour un seul jeton.
Comme la notification est faite par un get() d'un
consommateur ou un put() d'un producteur, on doit
vérifier si c'est un producteur ou un consommateur
qui a levé l'arrêt ce qui est fait dans le test et qui doit
être refait à chaque déblocage du wait() d'où la
nécessité d'une boucle while et non d'un test if.
JDBC
Le problème de l’accès aux données sans JDBC

 Java est un excellent candidat pour le


développement d’applications de bases de données:
 robuste et sécurisé
 facile à comprendre
 automatiquement téléchargeable par le réseau
 mais avant JDBC, il était difficile d’accéder à des
bases de données SQL depuis Java :
 obligé d’utiliser des API natives comme ODBC
Objectifs de JDBC

 Permettre aux programmeurs Java d’écrire un code


indépendant de la base de données et du moyen de
connectivité utilisé
 Réalisé par l’API JDBC :
 une interface uniforme permettant un accès homogène
aux SGBD
 simple à mettre en œuvre
 indépendant de la SGBD cible
 supportant les fonctionnalités de base du langage SQL
Avantages
Liés a Java :
 portabilité sur de nombreux O.S. et sur de

nombreuses SGBDR (Oracle, Informix, Sybase, ..)


 uniformité du langage de description des

applications, des applets et des accès aux bases de


données
 liberté totale vis a vis des constructeurs
Qu’est ce que JDBC ?
 Java DataBase Connectivity (Core API 1.1)
 API Java adaptée à la connexion avec les bases de
données relationnelles (SGBDR)
 Fournit un ensemble de classes et d’interfaces
permettant l’utilisation sur le réseau d’un ou
plusieurs SGBDR à partir d’un programme Java.
L'architecture JDBC standard
 Tout programme comporte 3 composants :
 Le code de l'application (ou de l'applet)
 Les requêtes doivent être au standard JDBC
 Le JDBC Driver Manager
 Fourni par SUN
 Lien entre l'application et les pilotes (ou drivers) JDBC
 Le driver JDBC
 Fourni par le fournisseur de la base ou autre
 Adapté à la BD
 Convertit les requêtes JDBC en requêtes propres à la base
Architecture JDBC
Les types de pilotes JDBC
 4 types de drivers (taxonomie de JavaSoft) :
 Type I : JDBC-ODBC bridge driver
 Type II : Native-API, partly-Java driver
 Type III : Net-protocol, all-Java driver
 Type IV : Native-protocol, all-Java driver
 Tous les drivers :
 ttp://www.javasoft.com/products/jdbc/drivers.html
Les types de pilotes JDBC
 Il existe quatre types de pilote JDBC :
 Type 1 ( JDBC-ODBC bridge ) : le pont JDBC-ODBC qui s'utilise
avec ODBC et un pilote ODBC spécifique pour la base à accéder.
Cette solution fonctionne très bien sous Windows. C'est la solution
idéale pour des développements avec exécution sous Windows d'une
application locale. Cette solution « simple » pour le développement
possède plusieurs
 inconvénients :
 la multiplication du nombre de couches rend complexe l'architecture (bien
que transparent pour le développeur) et détériore un peu les performances
 lors du deploiement, ODBC et son pilote doivent être installé sur tous les
postes ou l'application va fonctionner.
 la partie native (ODBC et son pilote) rend l'application moins portable et
dépendant d'une plateforme. ¨
Les types de pilotes JDBC
 Type 2 : un driver écrit en java qui appelle l'API native de la base de
données Ce type de driver convertit les ordres JDBC pour appeler
directement les API de la base de données via un pilote natif sur le client. Ce
type de driver nécessite aussi l'utilisation de code natif sur le client.
 Type 3 : un driver écrit en Java utilisant le protocole natif de la base de
données
 Ce type de driver utilise un protocole réseau propriétaire spécifique à une
base de données. Un serveur dédié reçoit les messages par ce protocole et
dialogue directement avec la base de données. Ce type de driver peut être
facilement utilisé par une applet mais dans ce cas le serveur intermédiaire
doit obligatoirement être installé sur la machine contenant le serveur web.
 Type 4 : un driver Java natif
 Ce type de driver, écrit en java, appelle directement le SGBD par le réseau.
Ils sont fournis par l'éditeur de la base de données.
Types de drivers et applets
 Une application Java peut travailler avec tous les
types de drivers
 Pour une applet (untrusted) :
 type I ou II : impossible
 une applet ne peut pas charger à distance du code natif (non
Java) sur son poste d’exécution
 type III : possible
 si le serveur middleware se situe au même endroit que le
serveur Web (car communication par sockets avec l’applet)
 type IV : possible
 si le SGBDR installé au même endroit que le serveur Web
Modèles de connexion en Java

 2-tiers : 2 entités interviennent


1. une application Java ou une applet
2. le SGBDR

 Modèle 3-tiers : 3 entités interviennent


1. une application Java ou une applet
2. un serveur middleware installé sur le réseau
3. le SGBDR
Enregistrer une base de données dans
ODBC sous Windows 9x ou XP
Enregistrer une base de données dans ODBC
sous Windows 9x ou XP
L’API JDBC
Est fournie par le package java(x).sql
 permet de formuler et gérer les requêtes aux bases

de données relationnelles
 supporte le standard « SQL-3 Entry Level »

 bientôt le niveau supérieur : ANSI SQL-4


 Classes/interfaces définissant les objets nécessaires:
 à la connexion à une base éloignée
 et à la création et exécution de requêtes SQL
L’API JDBC
 Disponible en plusieurs versions
 JDBC 1 :
 Livrée avec JDK 1.1
 Tout se trouve dans le package java.sql
 JDBC 2 :
 2 packages
 J2SE contient java.sql (SDK 1.2+)
 J2EE contient javax.sql
 JDBC 3 :
 Avec J2SE, SDK 1.4+
 Le cours est basé sur JDBC2
Les classes de l'API JDBC

 Les classes de java.sql :


 Statement
 CallableStatement, PreparedStatement
 DatabaseMetaData, ResultSetMetaData
 ResultSet,
 Connection
 Driver
 De javax.sql :
 RowSet
 Datasource
LES CLASSES DE L'API JDBC
 Toutes les classes de JDBC sont dans le package
java.sql
Classe Role

DriverManager charge et configure le driver de la base de


données.
Connection réalise la connexion et l'authentification à la
base de données.
Statement ( et PreparedStatement ) contient la requête SQL et la transmet à la
base de données.
ResultSet permet de parcourir les informations
retournées par la base de données
dans le cas d'une sélection de données
Modèle 2-tiers
 Principe :
 l’application (ou l’applet) cliente utilise JDBC pour parler
directement avec le SGBD qui gère la base de données
 Avantages :
 simple à mettre en œuvre
 bon choix pour des applications clientes peu évoluées, à livrer
rapidement et n’exigeant que peu de maintenance
 Inconvénients :
 dépendance forte entre le client et la structure du SGBDR
 g modification du client si l’environnement serveur change
 tendance à avoir des clients « graisseux »
 tout le traitement est du côté client
Architecture 2-tiers
Modèle 3-tiers
 Principes :
 le serveur middleware est l’interlocuteur direct du code Java client;
c’est lui qui échange des données avec le SGBDR
 pas forcemment écrit en Java
 si c’est le cas : utilise souvent JDBC pour accéder au SGBDR
 Avantages:
 le middleware peut ajouter un niveau de sécurité
 plusieurs supports pour les échanges avec le client :
 sockets, RMI Java, CORBA, …
 applets : le SGBDR peut se trouver sur une autre machine:
 mais serveur Web et middleware au même endroit
 facilite l’utilisation de clients « légers »
Modèle 3-tiers
Scénarios d’utilisation
 Scénario 1 :
 architecture 2-tiers avec une application Java
Scénarios d’utilisation
 Scénario 2 :
 architecture 2-tiers avec une applet Java
 Scénario 3 :
 architecture 3-tiers et applet/application Java
La connexion à une base de données

1. Chargement d’un pilote JDBC


2. Définition de l’URL de connexion
3. Etablissement de la connexion
4. Création d’une instruction
5. Exécution de la requête
6. Traitement des résultats
7. Fermeture de la connexion
Chargement d’un pilote JDBC
 Pour se connecter à une base de données via ODBC, il faut
tout d'abord charger le pilote JDBC-ODBC qui fait le lien
entre les deux.
 L’utilisation de la méthode Class.forName() peut lever une
exception de type ClassNotFoundException, il convient donc
de placer le chargement du pilote dans un bloc sécurisé.
Exemple :
Try {
Class.forName(« oracle.jdbc.driver.OracleDriver ») ;
}
catch(ClassNotFoundException e) {
System.err.println(« Erreur de chargement du driver : + e) ;
}
Définition de l’URL de
connexion.
 Afin de localiser votre serveur ou votre base de
données, il est indispensable de spécifier une
adresse sous forme d’URL de type « jdbc: ».
 pour une connexion à une base de données en
utilisant un driver JDBC, l’URL se compose
comme suit: jdbc:<sous-protocole>:<nom-BD>?
param=valeur, ...
Exemple:
String url=« jdbc:odbc:Mabase »;
Etablissement de la connexion
 La classe DriverManager dispose d’une méthode statique
permettant d’obtenir une connexion à l’URL, la méthode
getConnection() qui retourne un objet de type Connexion.
Cette méthode peut, si la connexion échoue ou si aucun pilote
ne prend en charge l’URL spécifiée, une exception de type
SQLException.
Exemple :
Import java.sql.* ;

try {
Connection con = DriverManager.getConnection(url,userId,password) ;
}
catch(SQLException sqle) {
System.err.println(« Erreur lors de la connexion : » + sqle) ;
}
Création d’une instruction.
 Afin d’accéder ou de modifier les informations contenues
dans la base de données, il convient d’utiliser un objet de
type Statement.
 Une instance de cet objet est retournée par la méthode
Connexion.createStatement() comme ceci :
Statement statement = con.createStatement() ;
 3 types de Statement :
 Statement : requêtes statiques simples
 PreparedStatement : requêtes dynamiques pré-compilées (avec
paramètres d’entrée/sortie)
 CallableStatement : procédures stockées
Exécution d’une requête
 Pour une requête de type interrogation (SELECT),
la méthode à utiliser de la classe Statement est
exécuteQuery(). retourne un ResultSet (tuples
résultants) Exemple :
String query = "SELECT * FROM Employés";
ResultSet resultset = statement.executeQuery(query);
 Pour des traitements de mise à jour, il faut utiliser
la méthode executeUpdate(). retournent un entier
(nombre de tuples traités)
Exemple :
String query = "DELETE FROM Employés WHERE Région =
‘WA’";
int result = statement.executeUpdate(query) ;
Traitement du résultat
 Le résultat d'une requête d'intérrogation est renvoyé dans un
objet de la classe ResultSet par la méthode executeQuery().
 En ce qui concerne la numérotation des colonnes, elle ne
commence pas à 0 comme pour les tableaux JAVA, mais à 1.
 lors de l’exécution de la requête, l’objet ResultSet ne semble
pas positionné sur le premier enregistrement mais avant, dans
une zone que l’on nomme le GAP.
 L’objet ResultSet dispose aussi d’un certain nombre de
méthodes permettant de naviguer d’un enregistrement à un
autre. while(resultset.next()) {
System.out.println(resultset.getString(1)) ;
}
la classe ResultSet
Les principales méthodes pour obtenir des données sont :
Méthode Role

getInt(int) retourne le contenu de la colonne dont le numéro est passé en paramètre sous forme
d'entier.
getInt(String) retourne le contenu de la colonne dont le nom est passé en paramètre sous forme
d'entier.
getFloat(int) retourne le contenu de la colonne dont le numéro est passé en paramètre sous forme
de nombre flottant.
getFloat(String)

getDate(int) retourne le contenu de la colonne dont le numéro est passé en paramètre sous forme
de date.
getDate(String)

next() se déplace sur le prochain enregistrement : retourne false si la fin est atteinte

Close() ferme le ResultSet

getMetaData() retourne un objet ResultSetMetaData associé au ResultSet.


JDBC 2.0
 La version 2.0 de l'API JDBC a été intégrée au JDK 1.2. Cette nouvelle
version apporte plusieurs fonctionnalités très intéréssantes dont les
principales sont :
 support du parcours dans les deux sens des résultats ·
 support de la mise à jour des résultats ·
 possibilité de faire des mises à jour de masse (Batch Updates) ·
 prise en compte des champs définis par SQL-3 dont BLOB et CLOB ·
 L'API JDBC 2.0 est séparée en deux parties :
 la partie principale (core API) contient les classes et interfaces nécessaires à
l'utilisation de bases de données : elles sont regroupées dans le package java.sql·
 la seconde partie est une extension utilisée dans J2EE qui permet de gérer les
transactions distribuées, les pools de connection, la connection avec un objet
DataSource ... Les classes et interfaces sont regroupées dans le package
javax.sql·
JDBC 2.0
 Méthode Rôle
 boolean isBeforeFirst() renvoie un booleen qui indique si la position courante du
curseur se trouve avant la première ligne
 boolean isAfterLast() renvoie un booleen qui indique si la position courante du
curseur se trouve après la dernière ligne
 boolean isFirst() renvoie un booleen qui indique si le curseur est positionné sur la première
ligne
 boolean isLast() renvoie un booleen qui indique si le curseur est positionné sur la dernière
ligne
 boolean first() déplace le curseur sur la première ligne
 boolean last() déplace le curseur sur la dernière ligne
 boolean absolute() déplace le curseur sur la ligne dont le numéro est fournie en
paramètre à partir du début si il est positif et à partir de la fin si il est négatif. 1
déplace sur la première ligne, -1 sur la dernière, -2 sur l'avant dernière ...
 boolean relative(int) déplace le curseur du nombre de lignes fourni en paramètre
par rapport à la position courante du curseur. Le paramètre doit être négatif pour se
déplacer vers le début et positif pur se déplacer vers la fin. Avant l'appel de
cette méthode, il faut obligatoirement que le curseur soit positionné sur une ligne.
 boolean previous() déplace le curseur sur la ligne précédente. Le booleen
indique si la première occurrence est dépassée.
JDBC 2.0
 void afterLast() déplace le curseur après la
dernière ligne
 void beforeFirst() déplace le curseur avant la
première ligne
 int getRow() renvoie le numéro de la
ligne courante
JDBC 2.0
 Méthode Rôle
 updateXXX(String, XXX) permet de mettre à jour la colonne dont le
nom est fourni en paramètre. Le type Java de cette colonne est XXX
 updateXXX(int, XXX) permet de mettre à jour la colonne dont
l'index est fourni en paramètre. Le type Java de cette colonne est
XXX
 updateRow() permet d'actualiser les modifications
réalisées avec des appels à updateXXX()
 boolean rowsUpdated() indique si la ligne courante a été modifiée
 deleteRow() supprime la ligne courante
 rowDeleted() indique si la ligne courante est supprimée
 moveToInsertRow() permet de créer une nouvelle ligne dans
l'ensemble de résultat
 inserRow() permet de valider la création de la ligne
Fermeture de la connexion
 Pour terminer proprement un traitement, il faut
fermer les différents espaces ouverts
 sinon le garbage collector s’en occupera mais moins
efficace
 Chaque objet possède une méthode close() :
 resultset.close();
 statement.close();
 connection.close();
PreparedStatement
 Lors de l'envoi d'une requête pour exécution 4 étapes doivent être
faites :
 analyse de la requête
 compilation de la requête
 optimisation de la requête
 exécution de la requête
et ceci même si cette requête est la même que la précédente !! Or les 3
premières étapes ont déjà été effectuées dans ce cas.
 Les bases de données définissent la notion de requête préparée,

requête où les 3 premières étapes ne sont effectuées qu'une seule fois.


 modéliser cette notion: l'interface PreparedStatement

 interface dérive de l'interface Statement.


PreparedStatement
 on ne peut pas avec un Statement construire des
requêtes paramétrées. Il faut pour cela utiliser un
PreparedStatement.
Syntaxe:
PreparedStatement pSmt = conX.prepareStatement("SELECT * FROM
Livres" );
ResultSet rs = pSmt.executeQuery();
Exemple :
PreparedStatement pSmt = conX.prepareStatement("SELECT
nom FROM Personnes WHERE age > ? AND adresse = ?" );
pSmt .setInt(1, 22);
pSmt .setString(2, "Turin");
ResultSet rs = pSmt.executeQuery();//smt.hgfjf fausse
setType(numéroDeLArgument, valeur)
CallableStatement
 L'interface CallableStatement définit les méthodes
pour un objet qui va permettre d'appeler une
procédure stockée.
 Cette interface hérite de l'interface
PreparedStatement.
 Un objet qui implémente l'interface
CallableStatement est obtenu en utilisant la
méthode prepareCall() d'un objet de type
Connection.
Exécution
 On lance l'éxécution d'une procédure stockée à l'aide de
la syntaxe :
 {call nom_procedure_stockees} : cette forme la plus
simple permet l'appel d'une procédure stockée sans
paramètre ni valeur de retour
 {call nom_procedure_stockees(?, ?, ...)} : cette forme
permet l'appel d'une procédure stockée avec des
paramètres·
 {? = call nom_procedure_stockees(?, ?, ...)} : cette forme
permet l'appel d'une procédure stockée avec des
paramètre et une valeur de retour·
Exécution
 Pour exécuter la requête, l'interface
PreparedStatement propose deux méthodes :
 executeQuery() : cette méthode permet d'exécuter une
requête de type interrogation et renvoie un objet de
type ResultSet qui contient les données issues de
l'exécution de la requête·
 executeUpdate() : cette méthode permet d'exécuter une
requête de type mise à jour et renvoie un entier qui
contient le nombre d'occurrences impactées par la mise
à jour·
Accès aux méta-données
 La méthode getMetaData () permet d’obtenir des
informations sur les types de données du ResultSet
 elle renvoie des ResultSetMetaData
 on peut connaître entre autres :
 le nombre de colonne : getColumnCount()
 le nom d’une colonne : getColumnName(int col)
 le nom de la table : getTableName(int col)
 si un NULL SQL peut être stocké dans une colonne :
isNullable()
ResultSetMetaData

ResultSet rs = stmt.executeQuery("SELECT * FROM emp");


ResultSetMetaData rsmd = rs.getMetatData();

int nbColonnes = rsmd.getColumnCount();


for(int i = 1; i <= nbColonnes; i++) {
// colonnes numerotées à partir de 1 (et non 0)
String nomCol = rsmd.getColumnName(i);
}
DatabaseMetaData
 Pour récupérer des informations sur la base de données
 elle-même, utiliser la méthode getMetaData() de l’objet
Connection
 dépend du SGBD avec lequel on travaille
 elle renvoie des DatabaseMetaData
 on peut connaître entre autres :
 getDriverVersion(), getDriverName(),
 getDatabaseProductName(), getDatabaseProductVersion()
 les tables de la base : getTables()
 le nom de l ’utilisateur : getUserName()
Le composant RowSet
 A démarré avec JDBC 2
 Interfacé vers un containeur pour tabuler les données
 Souvent associé avec un ResultSet
 Peut être n'importe quelle donnée, tableau, fichier à
plat, etc.
 Étend l'interface de ResultSet
 Contient un ensemble complet de propriétés
 Supporte les interactions basées sur les évènements
Le composant RowSet (2)
 Il a la possibilité de se remplir lui-même avec des
données
 Définition de l'emplacement de la base de données
dans une propriété principale
 Peut aussi être rempli à partir d'un ResultSet existant
RowSetReader et RowSetWriter
 Chaque classe qui implémente une RowSet dispose
d'une lecture et d'une écriture associées :
 La lecture extrait les données à partir de la source de
données pour remplir le RowSet : appliquer l'interface
RowsetReader
 L'écriture extrait les données du RowSet et les envoie
dans la source de données : appliquer RowSetWriter
Types de RowSet
Les types définis par les fournisseurs :
 CachedRowSet :

 Déconnecte le RowSet qui stocke ces données dans la mémoire


 Ne convient pas à des données volumineuses
 Idéal pour les client java légers ou les PDA
 JDBCRowSet :
 Sert de fin emballage autour du ResultSet
 Utilise un driver JDBC
 WebRowSet :
 Connecte le RowSet qui utilise le protocole HTTP
 Permet une interaction avec les servlets à partir du client léger à la
manière d'un tableau
Connexion/déconnexion du RowSet

 Les RowSet peuvent être utilisés de la même manière


que les ResultSet standards
 Peuvent être reliés à une source de données en
permanence
 Peuvent aussi être déconnectés de la source de
données
 Se comportent comme source de données pour le client
(données cachées)
 Peuvent être séralisés et transmis à travers le réseau
 Utile pour les clients légers (PDAs, les périphériques non
connectés)
Cliquez sur l'icône pour ajouter une image

Les Servlets
INTRODUCTION
 Une servlet est un programme qui s'exécute côté
serveur en tant qu'extension du serveur.
 La technique des CGI en Java, MAIS
 Sans créer de processus + toute la puissance de Java
(accès aux divers domaines de l'informatique : BD,
multimédia, réseau, objets distribués, composants, etc.)
 + indépendance de la plate-forme et du serveur
 Servlets
 Scripts serveur écrit en Java
 Servlets de Base : FileServlet, CGIServlet, …
 HttpServlet
 Exécution dans un espace isolé (Web Application)
 Spécification : Sun (sous partie de J2EE)
 Implémentation de référence : Apache Group (Jakarta
Tomcat)
 Différence avec les CGI et les LD (NSAPI, ISAPI)
 performance sur les passages des paramêtres (vs CGI)
 sûreté de fonctionnement (NSAPI, ISAPI)
Moteurs de servlets
 Pour exécuter des servlets, il faut un moteur de
servlets dans le serveur Web.
 Ces moteurs sont des plug-in pour des serveurs Web
existants
 ou bien des serveurs Web aux mêmes
 Plug-in : deux candidats : Jrun (www.allaire.com),
tomcat (jakarta.apache.org)
Programmation des servlets
 Utilise deux paquetages :
 javax.servlet : paquetage générique
 javax.servlet.http : paquetage pour
 serveurs Web
 Ces paquetages ne sont pas dans J2SE 1.3
 Sont des paquetages supplémentaires.
 Il sont aussi intégrés dans J2EE voir à
http://java.sun.com/j2ee/
Exemple de Servlet
Hello World !
import java. io.*;
import javax. servlet.*;
import javax. servlet. http.*;
public class HelloServlet extends HttpServlet {
public void doGet( HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
res. setContentType(" text html"); //Set the Content- Type header
PrintWriter out = res. getWriter(); // Get the output
String pname = req. getParameter(" name"); //Get a parameter
if( pname== null) pname=" World !";
out. println("< HTM >");
out. println("< HEAD>< TIT E> Hello, " + pname + "< TIT E>< HEAD>");
out. println("< BODY>");
out. println(" Hello, " + pname);
out. println("< BODY>< HTM >");
out. close();//pas flash?
}
public void doPost( HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException { doGet( req, res); }
}
L'API servlet
 L'API servlet regroupe un ensemble de classes dans
deux packages :
 javax.servlet : contient les classes pour développer des
serlvets génériques indépendantes d'un protocole.
 javax.servlet.http : contient les classes pour développer
des servlets qui reposent sur le protocole http utilisé
par les serveurs web.
L'API servlet
L'API servlet

javax.servlet Nom Role


RequestDispatcher Définition d'un objet qui permet le renvoi d'une
requête vers une autre ressource du serveur (une
autre servlet, une JSP ...)
Servlet Définition de base d'une servlet
ServletContext Définition d'un objet pour obtenir des
informations sur le contexte d'execution de la
servlet
Les
interfaces
ServletConfig Définition d'un objet pour configurer la servlet
ServletRequest Définition d'un objet contenant la requête du
client
ServletResponse Définition d'un objet qui contient la reponse
renvoyée par la servlet
SingleThreadMode Permet de définir une servlet qui ne répondra qu'à
l une seule requête à la fois
L'API servlet

javax.servlet Nom Role


GenericServlet Classe définissant une servlet indépendante de
tout protocole
ServletInputStream Flux permet la lecture des donnes de la requête
Les classes cliente
ServletOutPutStream Flux permettant l'envoie de la reponse de la
servlet

SevletException Exception générale en cas de problème durant


Les l'exécution de la servlet
exceptions UnavailableExceptio Exception levée si la servlet n'est pas
n disponible
L'API servlet
javax.servlet. Nom Role
http
HttpServletRequest Hérite de ServletRequest : définit un objet
contenant une requête selon le protocole http
HttpServletRespons Hérite de ServletResponse : définit un objet
Les interfaces e contenant la reponse de la servlet selon le
protocole http
HttpSession Définit un objet qui représente une session

Cookie Classe représentant un cookie (ensemble de


données sauvegardées par le brower sur le poste
client)
Les classes
HttpServlet Hérite de GenericServlet : classe définissant une
servlet utilisant le protocole http
HttpUtils Classe proposant des méthodes statiques utiles
pour le développement de servlet http
L'interface Servlet
 Cette interface définit 5 méthodes qui permettent au conteneur web
de dialoguer avec la servlet:
 void service (ServletRequest req,ServletResponse res)
 void init(ServletConfig conf)
 ServletConfig getServletConfig()
 void destroy()
 String getServletInfo()

 Les méthodes init(), service() et destroy() assurent le cycle


de vie de la servlet en étant respectivement appelées lors de
la création de la servlet, lors de son appel pour le traitement
d'une requête et lors de sa destruction.
La requête et la réponse
 L'interface ServletRequest définit plusieurs méthodes qui permettent
d'obtenir des données sur la requête du client :
 ServletInputStream getInputStream()
//Permet d'obtenir un flux pour les données de la requête
 BufferedReader getReader()
//Idem
 L'interface ServletResponse définit plusieurs méthodes qui permettent
de fournir la réponse faite par la servlet suite à ces traitements :
 SetContentType //Permet de préciser le type MIME de la réponse
 ServletOutputStream getOutputStream() // Permet d'obtenir un flux
pour envoyer la réponse
 PrintWriter getWriter() //Permet d'obtenir un flux pour
envoyer la réponse
Gestion des servlets
Les états d'une servlet

les états d'une applet. Le passage d'un état à un autre est automatique fait par le
conteneur de servlets.
 Une servlet doit implémenter l'interface
javax.servlet.http

Elle doit comporter l’une des deux méthodes :


 doGet() pour les requêtes http de type GET
 doPost() pour les requêtes http de type POST
Récupération de paramètres
public void doGet(HttpServletRequest req,
HttpServletResponse rep)
throws ServletException, IOException{

Enumeration liste = req.getParameterNames();


String [] valeurs = req.getParameterValues();
String val1 = req.getParameter(''param1'');
Exemple : annuaire Mastere
<HTML>
<HEAD><TITLE> ANNUAIRE Mastere </TITLE></HEAD>
<BODY BGCOLOR="#FFFFFF"<CENTER>
<CENTER><H1>ANNUAIRE DU DESS TIIR </H1></CENTER>
<HR><CENTER>
<H2>Recherche de coordonnées </H2></CENTER>
<P> Tapez le début du nom de la personne recherchée:
<P><FORM METHOD=POST
ACTION=http://localhost:8080/examples/servlets/annuaire
method=post>
<INPUT TYPE=TEXT NAME="nom" SIZE=20 MAXLENGTH=30 VALUE="">
<P><INPUT TYPE=SUBMIT NAME="go" VALUE="RECHERCHER">
<INPUT TYPE=RESET NAME="reset" VALUE="ANNULER">
</FORM>
</BODY></HTML>
Annuaire Mastere(Servlet)
import java.io.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class Annuaire extends HttpServlet{
public void doPost( HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException{
res.setContType("text/html");
PrintWriter out=res.getWriter();
out.println("<HEAD><TITLE>Réponse annuaire </TITLE></HEAD><BODY>");
out.println("<HR>");
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver").newInstance();
String url ="jdbc:odbc:mabase";
java.sql.Connection c=DriverManager.getConnection(url,"","");
Annuaire Mastere(Servlet)-Suite-
java.sql.Statement st = c.createStatement();
java.sql.ResultSet rs =
st.executeQuery("Select * from matable where nom like '"
+req.getParameter("nom"+"*'"));
rs.next();
out.println(rs.getString("prenom")+" "+rs.getString("nom") );
}
catch (SQLException e){
out.println("Cette personne n'existe pas");
}
out.println("<P><A href = annuaire.html> Retour</A>"</P>);
out.println("</BODY>");
out.close();
}
public String getServletInfo(){
return "Servlet Annuaire";
}
Les cookies
 Ajout de cookies à l ’entête de la réponse
 void HttpServletResponse. addCookie( Cookie
cookie)
 Le cookie peut être un cookie récupéré dans la requête
 Et modifié avant d’être ajouté à la réponse
Sessions : javax. servlet. http. HttpSession

Garder la mémoire des informations d'une page à l'autre :


 Utiliser les cookies (sécurité!)
 Syntaxe CGI : paramètres dans l'URL
 Champs ``HIDDEN'' de formulaires
<INPUT TYPE=''HIDDEN'' NAME=''PARAM1''VALUE=''VAL1''>
 Objet HttpSession
HttpSession session=request.getSession(true);
Classe objet = (Classe) session.getValue(''param1'');
Méthodes : getValue(), putValue(), removeValue()
HttpSession session = req.getSession(true);
If (session.isNew()){
session.putValue('‘toto'', new int[] {0});
}
Int[] toto = (int[]) session.getValue('‘toto'');
Le suivi de session
 Le serveur maintient une session de 2 manières :
 Cookie (Name: SESSIONID Value: To1010mC8601021835741167At)
 les cookies peuvent être désactivés sur le navigateur
 Réécriture des URLs
 Ouverture/récupération d ’une session
javax. servlet. http. HttpSession session = req. getSession( false);
// la session est récupérée ou null si elle n ’existait pas déjà
javax. servlet. http. HttpSession session = req. getSession( true);
//la session est récupérée ou ouverte si elle n ’existait pas déjà
 Invalidation d ’une session

javax. servlet. http. HttpSession session = req. getSession( false);


session. invalidate(); la session est invalidée ( i. e. fermée)
Information sur la session
javax. servlet. http. HttpSession session = req. getSession( false);
 L ’identifiant
String sessionid= session. getId(); // par exemple: To1010mC8601021835741167At
 La date de création
long datecreation= session. getCreationTime(); // nb de ms depu s 1/ 1/ 1970: 00: 00
 La date du dernier accès
long datelastaccess= session. get astAccessedTime();
 Exemple
HttpSession session = req. getSession( true);
if( session. get astAccessedTime() - session. getCreationTime() > 5* 60* 1000 ) {
session. invalidate();
}
Information sur la session
javax. servlet. http. HttpSession session = req. getSession( false);
 Méthode de suivi de session

boolean HttpServletRequest. isRequestedSessionIdFromCookie()


// test si le suivi de session utilise un cookie
boolean HttpServletRequest. isRequestedSessionIdFromUR ()
// test si le suivi de session utilise la réécriture d ’UR
 Réécriture des URL (cas isRequestedSessionIdFromURL )

 les URL générées doivent être encodées pour intégrer le suivi de session
String HttpServletResponse. encodeRedirectUR (String url)
String HttpServletResponse. encodeUR (String url)
 Exemple
res. sendRedirect( res. encodeRedirectUR (" servlet login");
Liaison d ’objets à une session
 javax. servlet. http. HttpSession session = req.
getSession( true);
 Ajout/remplacement d ’une valeur
void HttpSession. setAttribute( String name, Object value)
 Suppression d ’une valeur
void HttpSession. removeAttribute( String name)
 Récupération des valeurs/d ’une valeur

String[] HttpSession. getAttributeNames()


Object HttpSession. getAttribute( String name)
Exemple de liaison d ’objets
 import mycybermarket. Cart; …
 public void doGet( HttpServletRequest req, HttpServletResponse res) … {
 Cart cart;
 HttpSession session = req. getSession( true);
 if(( cart=( Cart) session. getAttribute(" CART"))!= null) {
 cart= CartFactory. create(); // new rt( ... ); ou = c rtHome. cre te();
 session. setAttribute("CART", cart);
 } ...
 ...
 if( action. equals(" exit") {
 cart. releaseProducts();
 session. removeAttribute(" CART");
 }
 ...
Observateurs sur la session
 Motivations
 réagir face à des événements intervenants dans la/les sessions

 4 interfaces Listeners
HttpSessionActivationListener
la session peut être passivée puis réactivée
HttpSessionListener
changement sur la liste des sessions actives de l'application Web.
HttpSessionAttributeListener
changement sur les attributs d’une des sessions de l’application
Web.
HttpSessionBindingListener
un objet peut être notifié de sa liaison rupture à un session
Observateurs sur la session
 HttpSessionActivationListener
 la session peut être passivée puis réactivée
void sessionDidActivate( HttpSessionEvent se)
void sessionWillPassivate( HttpSessionEvent se)
 HttpSessionListener
 changement sur la liste des sessions actives de l'application Web.
void sessionCreated( HttpSessionEvent se)
Void sessionDestroyed( HttpSessionEvent se) invalidation
 HttpSessionAttributeListener
 attribute lists of sessions within this web application.
void attributeAdded( HttpSessionBindingEvent se)
void attributeRemoved( HttpSessionBindingEvent se)
void attributeReplaced( HttpSessionBindingEvent se)
 HttpSessionBindingListener
 un objet peut être notifié de sa liaison rupture à un session
void valueBound( HttpSessionBindingEvent event)
void valueUnbound( HttpSessionBindingEvent event)
Observateur de liaison
 Motivations
 faire réagir les objets liés aux liaisons et « déliaisons »
 fermer des fichiers, des connexions, valider des transactions, ...
 API
interface HttpSessionBinding istener
public void valueBound( HttpSessionBindingEvent event)
public void valueUnbound( HttpSessionBindingEvent event)
class HttpSessionBindingEvent extends EventObject
public Session getSession() la session concernée
public String getName() le nom de la liaison
 Principe
 l ’objet lié doit implanté HttpSessionBinding istener
 valueBound () est invoqué quand l ’objet est lié ( putValue ())
 valueUnbound () est invoqué quand la session est invalidé ou expire ou quand l ’objet est
délié ( setAttribute ()/ removeAttribute ()).
Exemple de Observateur de
Liaison
class CartBinding istener implements HttpSessionBindingListener {
rt c rt= null;
public CartBinding istener( ... ) { this. cart = new Cart( ... ); }
public void valueBound( HttpSessionBindingEvent event) {}
public void valueUnbound( HttpSessionBindingEvent event) {
cart. releaseProducts();}
public void doGet( HttpServletRequest req, HttpServletResponse res) {
CartBinding istener cart;
HttpSession session = req. getSession( true);
CartBinding istener cart=( Cart) session. getValue(" CART");
if( cart== null) { cart= new CartBinding istener( ... );
session. setAttribute(" CART", cart); // v lueBound est invoqué sur l ’objet lié
}…
session. removeAttribute (" CART"); // v lueUnbound est invoqué sur l ’objet lié
Partage d ’objets entre servlets
 Motivation
 partager une information commune entre servlets, ...
 Plusieurs
 S1 : utilisez les Properties de java. lang. System
 S2 : classe commune avec des membres statiques
 S3 : utilisez le contexte de l’application
Partage d ’objets entre servlets
 Solution 1 : utilise les Properties de java. lang. System
String java. lang. System. getProperty( String key)
String java. lang. System. setProperty( String key, String value)
 Remarque : les Properties sont partagées par toutes les WebApps du
serveur J2EE
 Solution 2 : classe commune avec des membres statiques
 l ’initialisation des membres statiques XXX peut se faire au moment du
premier accès par une des servlets
Remarque pour une meilleure programmation

 les membres statiques sont privés et sont accédés par des méthodes
statiques setXXX() et getXXX()
 la classe n ’est accessible que par les servlets du même package et chargée
par le même ClassLoader (un par WebApp)
Partage d ’objets entre servlets
 Solution 3 : utiliser les <env- entry> du contexte JNDI de l’application
 Paires typées (name, value, classname) appartenant au contexte de l’application
Web
<env- entry>
<env- entry- name> defaultCurrency< env- entry- name>
<env- entry- value> EUR< env- entry- value>
<env- entry- type> java. lang. String< env- entry- type>
< env- entry>
<env- entry>
<env- entry- name> default anguage< env- entry- name>
<env- entry- value> 33< env- entry- value>
<env- entry- type> java. lang. Integer< env- entry- type>
< env- entry>
Partage d ’objets entre servlets
 Récupération des <env- entry> via JNDI
Context ctx = new InitialContext();
Object value = ctx. lookup(" java: comp env defaultCurrency");
out. println(" Default currency value : " + value);
Context envCtx = ( Context) ctx. lookup(" java: comp env ");
NamingEnumeration enum = ctx. list(" java: comp env ");
while (enum. hasMoreElements()) {
out. print(" Binding : "+ ( enum. nextElement(). toString());
}
NamingEnumeration enumbinding = envCtx. listBindings(" java: comp env
");
while (enumbinding. hasMoreElements()) {
out. print(" Binding : "+( enumbinding. nextElement(). toString());
Authentification
 Authentification
 • Système :

HttpServletRequest. getAuthType(), HttpServletRequest. getRemoteUser()


 HTTP - BASIC ou DIGEST challenge

WWW-Authenticate
 SSL 3.0 authentifie le client
 Custom
 utilise des servlets vérifiant l’identité de l ’utilisateur avec des moyens
externes au serveur (annuaire LDAP, BD, GSM, …)
 Autres
java. security. Principal HttpServletRequest. getUserPrincipal()
//identité de l ’utilisateur dans le schéma général sécurité de java
boolean HttpServletRequest. isUserInRole( String role)
//test si l ’utilisateur appartient à un role (i. e. classe d ’utilisateur)
Request Dispatch
 Redirige la traitement de la requête vers une autre
servlet ou JSP
 Utilisé pour le MVC
 Exemple
public class ForwardServlet extends HttpServlet {
public void doGet (HttpServletRequest request,
HttpServletResponse response) {
//Set the attribute and forward to hello. jsp
request. setAttribute (" action", " hello");
ServletContext context= getServletConfig(). getServletContext().
context. getRequestDispatcher(" hello. jsp"). forward( request,
response);
}
}
Java Server Pages (JSP)
Principe
 Server Side Script
 Insertion de SSS (syntaxe Java) dans les pages HTML
 Avantage par rapport aux servlets
 Ecriture moins verbeuse Orientée Web Designer
 Insérable par des outils auteurs dans le code de pages HTML
 Extensible grâce aux JSTL
 Spécification
 JSR-52
 JSR-152 JavaServer Pages 2.0 Specification
 Implémentations
 J2EESDK et Jakarta JASPER/TomCat
JSP vs Active Server Pages (ASP)
 ASP est une technologie comparable à JSP développé par
Microsoft. Cependant, deux avantages sont dégagés par
JSP. Premièrement, les parties dynamiques sont
développées en JAVA et non en VisualBasic ou d’autres
langages spécifiques à Microsoft donc plus performantes
et faciles à utiliser. Deuxièmement, JSP est compatible
avec d’autres systèmes d’exploitation et serveurs web
développés par d’autres compagnies que Microsoft.
JSP vs JavaScript
 JavaScript peut générer dynamiquement du HTML sur le
côté client. Cette une fonctionnalité très utile mais elle gère
les situations où les informations se trouvent sur le côté
client seulement. De plus, le fait que les programmes
JavaScript s’exécutent sur le côté client, ils ne peuvent
accéder aux ressources situées sur le côté serveur comme
une base de données, un catalogue d’information, etc.
Insertion des scripts
 Directives
<%@page import="java.util.*" %>
<%@taglib prefix="c" uri="WEB-INF/tld/core.tld" %>
 Éléments de script
 Scriplets <% code java %>
 Déclarations <%! Déclarations %>
 Expressions <%= expression %>
 TagLib
<jsp:forward page="forward.jsp" />
<jsp:include page="result.jsp" />
<c:if test="${applicationScope:booklist == null}" >
<c:import url="/books.xml" var="xml" />
<x:parse xml="${xml}" var="booklist" scope="application" />
</c:if>
Exemple
<HTML >
<HEAD>< TITLE> Hello< TITLE>< HEAD>
<BODY>
<H1> Salut
<%
String pname; //déclaration de variable
pname = request. getParameter(" name"); // request : objet implicite
if ( pname== null) { out. println(" World"); } else {
%>
Mr <%= pname%>
<% } // fin du else %>
< H1>
< BODY>< HTML >
Exemple de traitement d ’un formulaire

<%@ method = " doPost" %>


<HTM >
<HEAD>< TITLE> Hello< TITLE>< HEAD>
<BODY>
<H1> Hello
<%
String pname; //déclaration de variable
pname = request. getParameter(" name"); //request : objet implicite
if ( pname== null) { out. println(" World"); } else {
%>
Mr <%= pname%>
<% } // fin du else %>
< H1>
< BODY>< HTML >
JSP : Exemple avec une session
JSP listant un « caddie » virtuel
<html>
<jsp: useBean id=" cart" scope=" session" class=" mycybermarket. MyCart" >
<jsp: setProperty name=" cart" property="*" >
<%
cart. processRequest( request);
%>
<br> You have the following items in your cart:
<ol>
<% String[] items = cart. getItems();
for ( int i= 0; i< items. length; i++) { %>
<li> <%= items[ i] %>
<% } %>
< ol>< hr>
<%@ include file =" catalog. html" %>
< html>
JSP : Exemple avec une session
Classe de « caddie » utilisé par la JSP
Génération des JSP
 Compilation des JSP en classes Java
 génération et compilation d ’une classe étendant
HttpJspBase à la première invocation.
 Au runtime
 la servlet JspServlet invoque le compilateur Jasper
puis charge et exécute la méthode _jspService de la
classe HttpJspBase générée
 Avant déploiement
 Les JSP peuvent être aussi générées avant le
déploiement (tâche <jspc>)
Architecture
Action jsp:forward
 Cette action vous permet de rediriger une requête
vers une autre page.
 Syntaxe:
<jsp:forward page="{relativeURL | <%= expression %>}" />
ou
<jsp:forward page="{relativeURL | <%= expression %>}" >
<jsp:param name="parameterName"
value="{ parameterValue | <%= expression %>}" /> +
</jsp:forward>
Action jsp:include
 Comme vu précédemment, l’action include vous permet d’insérer
un fichier pendant que le servlet est généré à partir du fichier JSP.

<jsp:include page="relative URL" flush="true" />

 Contrairement à la directive include qui insère les fichiers au


moment où le fichier JSP est compilé sur le serveur et transformé
en servlet, l’action include insère les fichiers seulement
lorsqu’une requête est placée sur la page demandée. Ceci en
coûte une légère perte en performance mais gagne en flexibilité.
Session JSP
 GetName.html SaveName.jsp
<% String name =
<HTML> request.getParameter( "username" );
<BODY> session.setAttribute( "theName", name ); %>
<FORM METHOD=POST
ACTION="SaveName.jsp"> NextPage.jsp
What's your name? <INPUT <HTML>
TYPE=TEXT NAME=username <BODY> Hello, <%=
session.getAttribute( "theName" ) %>
SIZE=20> <P> </BODY>
<INPUT TYPE=SUBMIT> </HTML>
</FORM>
</BODY>
</HTML>
<jsp:useBean>
 Le tag <jsp:useBean>
 Le tag <jsp:useBean> permet de localiser une instance ou d'instancier un
bean pour l'utiliser dans la JSP. Ce tag ne permet pas de traiter
directement des EJB.
<jsp:useBean>
 La syntaxe est la suivante :
<jsp:useBean
id="beanInstanceName"
scope="page|request|session|application"
{ class="package.class" | •L'attribut id permet de donner un nom à la
type="package.class" |
variable qui va contenir la référence sur le
bean.
class="package.class" type="package.class" |
beanName="{package.class | <%= expression %>}" type="package.class"
}
•L'attribut class permet d'indiquer la classe du bean.
{ /> |
•L'attribut type permet de préciser le type de la variable qui va
> ... contenir la référence du bean. La valeur indiquée doit
</jsp:useBean> obligatoirement être une super classe du bean ou une interface
} implémentée par le bean (directement ou par héritage)
•L'attribut beanName permet d'instancier le bean grâce à la
méthode instanciate() de la classe Beans.
<jsp:useBean>
 L'attribut scope permet de définir la portée durant laquelle le
bean est défini et utilisable. La valeur de cette attribut
détermine la manière dont le tag localise ou instancie le bean.
Les valeurs possibles sont :
Valeur Rôle
page Le bean est utilisable dans toute la page JSP ainsi que dans les fichiers statiques
inclus. C'est la valeur par défaut.
request le bean est accessible durant la durée de vie de la requête. La méthode
getAttribute() de l'objet request permet d'obtenir une référence sur le bean.
session le bean est utilisable par toutes les JSP qui appartiennent à la même session que la
JSP qui a instanciée le bean. Le bean est utilisable tout au long de la session par
toutes les pages qui y participent. La JSP qui créé le bean doit avoir l'attribut
session = « true » dans sa directive page.
application le bean est utilisable par toutes les JSP qui appartiennent à la même application
que la JSP qui a instanciée le bean. Le bean n'est instancié que lors du
rechargement de l'application.
Exemple
Personne.java
TestBean.jsp
package test;
<html> public class Personne {
<HEAD> private String nom;
<TITLE>Essai d'instanciation d'un bean dans une private String prenom;
JSP</TITLE> public Personne() {
</HEAD> this.nom = "nom par defaut";
<body> this.prenom = "prenom par defaut";
}
<p>Test d'utilisation d'un Bean dans une JSP </p>
public void setNom (String nom) {
<jsp:useBean id="personne" scope="request" this.nom = nom;
class="test.Personne" /> }
<p>nom initial = <%=personne.getNom() %></p> public String getNom() {
<% return (this.nom);
personne.setNom("mon nom"); }
%> public void setPrenom (String prenom) {
this.prenom = prenom;
<p>nom mise à jour = <%= personne.getNom()
}
%></p> public String getPrenom () {
</body> return (this.prenom);
</html> }
}
Formulaire d'échange avec une BD
<HTML><HEAD><Title> Essai de connexion </title></HEAD>
<BODY bgcolor="#FFFFFF">
<%@ page import="java.sql.*" errorPage="erreur.jsp" %>

<%!
Connection con=null;
public void JspInit(){
String url="jdbc:odbc:musiciens";
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
con=DriverManager.getConnection(url,"","");
}
catch (Exception e){
System.err.println(e.getMessage());
}
}
public void jspDestroy(){
try{con.close();}
catch (SQLException e)
{System.err.println(e.getMessage());}
}
%>
Formulaire d'échange avec une BD

<% String pnom = request.getParameter("nom"); <br>


String nom = ""; String prenom = ""; <%="nom "+nom + " " %> <
String adresse =""; String ville = ""; %="Ville "+ville %>
String requete = ""; <br>
try{ <%
Statement stmt = con.createStatement(); stmt.close();
requete="select * from personnes where nom }
="+pnom; catch(SQLException ex){
ResultSet rs =stmt.executeQuery(requete);
if (rs.next()) { System.err.println("SQLExceptio
nom = rs.getString("NOM"); n : "+
prenom = rs.getString("PRENOM"); ex.getMessage());
adresse = rs.getString("ADRESSE"); }
ville = rs.getString("VILLE"); %>
}%>
Formulaire d'échange avec une BD
<form action= saisie.jsp method="post">
<input type="text" name="pnom"> Entrez un nom
<input type="submit" value="valider">
</form>
</body>
</HTML>

Remarque : les méthodes jspInit et jspDestroy


doivent être redéfinies en surcharge de façon à
éviter l'ouverture et la fermeture systématique de la
base lors du traitement de chaque requête.
Définition
 Selon la spécification des Javabeans, une Bean est un
composant logiciel réutilisable pouvant être manipulé
visuellement dans un outil de construction ( builder
tool ).
 Les EJB et les beans n'ont en commun que d'être des
composants. Les java beans sont des composants qui
peuvent être utilisés dans toutes les circonstances. Les
EJB doivent obligatoirement s'exécuter dans un
environnement serveur dédié.
 Les EJB s'exécutent dans un environnement particulier :
le serveur d'EJB.
 La technologie Enterprise JavaBeans (EJB) est une
architecture de composants logiciels côté serveur
pour la plateforme J2EE.
 Composant logiciel. Un composant logiciel est une unité
de composition dotée d’interfaces spécifiées. Un
composant logiciel peut être déployé indépendamment
et être sujet à une composition par une tierce entité.
 Le point clé des technologies basées composant est la
réutilisabilité, le composant doit être capable de
s’autodécrire et de se déployer indépendamment des
autres parties de l’application.
 Les EJB s'exécutent dans un environnement particulier : le
serveur d'EJB.
 Le serveur d'EJB fournit un ensemble de fonctionnalités utilisées
par un ou plusieurs conteneurs d'EJB qui constituent le serveur
d'EJB.
Serveur
EJBConteneur
d’EJB
EJ EJ
B B
Client Browser Base de
ou application données
Conteneur d’EJB
EJ EJ
EJ
B B
B
Conteneur d'EJB
 Le conteneur d'EJB propose un certain nombre de
services qui assurent la gestion :
 du cycle de vie du bean ·
 de l'accès au bean ·
 de la sécurité d'accès ·
 des accès concurrents ·
 des transactions ·
Développement d'un EJB
 Le cycle de développement d'un EJB comprend :
 la création des interfaces et des classes du bean.
 le packaging du bean sous forme de fichier archive jar.
 le déploiement du bean dans un serveur d'EJB.
 le test du bean.
Création d'un bean
 La création d'un bean nécessite la création d'au
minimum deux interfaces et une classe pour
respecter les spécifications de Sun :
 la classe du bean,
 l'interface remote
 l'interface home
L'interface remote
 L'interface remote permet de définir l'ensemble des
services fournis par le bean. Cette interface étend
l'interface javax.ejb.EJBObject.
 Dans la version 2.0 des EJB, l'API propose une
interface supplémentaire, EJBLocalObject, pour
définir les services fournis par le bean qui peuvent
être appellés en local par d'autres beans.
L'interface remote
 L'interface javax.ejb.EJBObject définit plusieurs méthodes qui seront donc
présentes dans tous les EJB :
 EJBHome getEJBHome() throws java.rmi.RemoteException : renvoie une
référence sur l'objet Home ·
 Handle getHandle() throws java.rmi.RemoteException : renvoie un objet
permettant de sérialiser le bean ·
 Object getPrimaryKey() throws java.rmi.RemoteException : renvoie une
référence sur l'objet qui encapsule laclé primaire d'un bean entité·
 boolean isIdentical(EJBObject) throws java.rmi.RemoteException : renvoie un
boolean qui précise si le bean est identique à l'instance du bean fourni en
paramètre. Pour un bean session sans état, cette méthode renvoie toujours true.
Pour un bean entité, la méthode renvoie true si la clé primaire des deux beans est
identique.
 void remove() throws java.rmi.RemoteException, javax.ejb.RemoveException :
cette méthode demande la destruction du bean. Pour un bean entité, elle provoque
la suppression des données coorespondantes dans la base de données.
L'interface home
 L'interface home permet de définir l'ensemble des services qui vont
permettre la gestion du cycle de vie du bean. Cette interface étend
l'interface EJBHome.
 La création d'une instance d'un bean se fait grâce à une ou plusieurs
surcharges de la méthode create(). Chacune de ces méthodes renvoie une
instance d'un objet du type de l'interface remote.
 L'interface javax.ejb.EJBHome définit plusieurs méthodes :
 EJBMetaData getEJBMetaData() throws java.rmi.RemoteException
 HomeHandle getHomeHandle() throws java.rmi.RemoteException // renvoie un
objet qui permet de sérialiser l'objet implémentant l'interface EJBHome
 void remove(Handle) throws java.rmi.RemoteException,
javax.ejb.RemoveException // supprime le bean
 void remove(Object) throws java.rmi.RemoteException,
javax.ejb.RemoveException // supprime le bean entité dont l'objet encapsulant la
clé primaire est fourni en paramètre
La classe du bean
 La classe du bean contient l'implémentation des
traitements du bean. Cette classe implémente les
méthodes déclarées dans les interfaces home et
remote. Les méthodes définissant celle de
l'interface home sont obligatoirement préfixées par
"ejb".
Les différents types d’EJB
 Il existe trois sortes d’EJB, chacun ayant une fonction
bien précise. Leur utilisation impose une bonne
conception et une certaine modularité dans l’application.
 Session Beans. Les beans sessions encapsulent le coeur des
traitement, on parle aussi de composants “métiers”
 Message Driven Beans. Les MDB permettent de recevoir des
messages de manière asynchrone (méthode onMessage() de
l’interface MessageListener). Ils invoquent ensuite des
méthodes sur les beans sessions. (seulement dans EJB2.0)
 Entity Beans. Les beans entit´es permettent de gérer la
persistance et la consultation des données de manière
transparente.
Les EJB session
 Modélisent un traitement (business process)
 Correspondent à des verbes, à des actions
 Ex : gestion de compte bancaire, affichage de
catalogue de produit, vérifieur de données bancaires,
gestionnaire de prix…
 Les actions impliquent des calculs, des accès à une
base de données, consulter un service externe (appel
téléphonique, etc.)
Les EJB session
 Un EJB session est un EJB de service dont la durée
de vie correspond à un échange avec un client. Ils
contiennent les règles métiers de l'application. Il
existe deux types d'EJB session :
 sans état (stateless)
 avec état (statefull)
EJB session stateless
 Ce type de bean propose des services sous la forme
de méthodes. Il ne peut pas conserver de données
entre deux appels de méthodes. Les données
provenant du client nécessaires aux traitements
d'une méthode doivent obligatoirement être
fournies en paramètre de la méthode.
Exemple stateless
package com.moi.ejb;
import java.rmi.RemoteException;
import javax.ejb.EJBException;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
public class MonPremierEJBBean implements SessionBean {
public String message() {
return "Bonjour";
}
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void ejbRemove() {
}
public void setSessionContext(SessionContext arg0) throws EJBException,
RemoteException {
}
public void ejbCreate() {
}
}
Les EJB session Statefull
 Ce type de bean fourni aussi un ensemble de traitements
via ces méthodes mais il a la possibilité de conserver des
données entre les différents appels de méthodes d'un même
client. Une instance particulière est donc dédiée à chaque
client qui sollicite ces services et ce tout au long du
dialogue entre les deux entités.
 Les données conservées par le bean sont stockées dans les
variables d'instances du bean. Les données sont donc
conservées en mémoire.
 Généralement, les méthodes proposées par le bean
permettent de consulter et mettre à jour ces données.
Les EJB entité
 Modélisent des données
 Correspondent à des noms
 Ce sont des objets java qui cachent des données d'une base de
données
 Ce sont des objets persistants
 Ex : un Bean Personne, un Bean compte bancaire, un Bean
produit, un Bean commande.
 Serveurs pour des Beans Session le plus souvent
 Servent de proxy entre la logique métier et les base de données
 Mapping base de donnée relationnelle/Objet facilité par EJB2.0
Les EJB entité
 Les EJB entité permettent de représenter et de gérer des données
enregistrées dans une base de données. Ils implémentent
l'interface EntityBean.
 Les beans entité assurent la persistance des données en
représentant tout au partie d'une table ou d'une vue. Il existe
deux types de bean entité :
 persistance gérée par le conteneur (CMP : Container Managed
Persistence)
 persistance gérée par le bean (BMP : Bean Managed Persistence)
 Plusieurs clients peuvent accéder simultanément à un
même EJB entity. La gestion des transactions et des accès
concurrents est assurée par le conteneur.
Entity Beans
 Les Entity Beans servent à manipuler de manière
transparente des données.
 On a généralement un type d’Entity Bean par table
d’une base de données relationnelle.
 A un moumment donné, une instance d’Entity Bean
correspond à un enregistrement de cette table.
 Il suffit alors de manipuler le bean entité pour
manipuler les données sous-jacentes.
Message Driven Beans
 Nouveau dans EJB 2.0,
 Similaire aux Session bean : représentent des
verbes ou des actions,
 On les invoque en leur envoyant des messages,
 Ex : message pour déclencher des transactions
boursières, des autorisations d'achat par CB,
 Souvent clients d'autres beans…
Message Driven Beans
 La communication avec les Entity Beans ou avec les Session
Beans se fait par invocation de méthode à distance (mode
synchrone).
 Les Message Driven Beans permettent au contraire d’utiliser
des envois de messages pour la communication (mode
asynchrone). Les messages peuvent par ailleurs encapsuler,
ou d´eclencher des appels de méthodes sur des sessions et/ou
des entity beans, ce qui permet de les manipuler de maniére
asynchrone et de gérer des files d’attentes.
 Tout MDB implémente l’interface
javax.jms.MessageListener, qui posséde une méthode
onMessage(Message)
Ecriture d'un premier Bean
 Ordre typique des opérations
1. Ecrire les fichiers .java qui composent le bean,
2. Ecrire le descripteur du bean,
3. Compiler les .java de l'étape 1,
4. Créer un .jar contenant les .class et le descripteur,
5. Deployer le .jar (via outil ou simple copie),
6. Vérifier que le serveur fonctionne et a bien déployé le
bean, sinon, vérifier la config,
7. Ecrire, compiler, exécuter un client de test du bean.
L'interface distante
package examples;
/**
* This is the HelloBean remote interface.*
* This interface is what clients operate on when
* they interact with EJB objects. The container
* vendor will implement this interface; the
* implemented object is the EJB object, which
* delegates invocations to the actual bean.
*/
public interface Hello extends javax.ejb.EJBObject {
/**
* The one method - hello - returns a greeting to the client.
*/
public String hello() throws java.rmi.RemoteException;
}
L'interface locale
package examples;
/**
* This is the HelloBean local interface.
*
* This interface is what local clients operate
* on when they interact with EJB local objects.
* The container vendor will implement this
* interface; the implemented object is the
* EJB local object, which delegates invocations
* to the actual bean.
*/
public interface HelloLocal extends javax.ejb.EJBLocalObject {
/**
* The one method - hello - returns a greeting to the client.
*/
public String hello();
}
L'interface Home
package examples;
/**
* This is the home interface for HelloBean. This interface
* is implemented by the EJB Server's tools - the
* implemented object is called the Home Object, and serves
* as a factory for EJB Objects.
*
* One create() method is in this Home Interface, which
* corresponds to the ejbCreate() method in HelloBean.
*/
public interface HelloHome extends javax.ejb.EJBHome {
/*
* This method creates the EJB Object.
*
* @return The newly created EJB Object.
*/
Hello create() throws java.rmi.RemoteException,
javax.ejb.CreateException;
}
L'interface Home locale
package examples;
/**
* This is the local home interface for HelloBean.
* This interface is implemented by the EJB Server's
* tools - the implemented object is called the
* local home object, and serves as a factory for
* EJB local objects.
*/
public interface HelloLocalHome extends javax.ejb.EJBLocalHome {
/*
* This method creates the EJB Object.
*
* @return The newly created EJB Object.
*/
HelloLocal create() throws javax.ejb.CreateException;
}
La classe du bean
package examples; public void
/** setSessionContext(javax.ejb.SessionC
* Demonstration stateless session bean. ontext ctx) {
*/ this.ctx = ctx;
public class HelloBean implements javax.ejb.SessionBean
{
}
private SessionContext ctx; //
// // Business methods
// EJB-required methods //
// public String hello() {
public void ejbCreate() { System.out.println("hello()");
System.out.println("ejbCreate()"); return "Hello, World!";
}
}
public void ejbRemove() {
System.out.println("ejbRemove()"); }
}
public void ejbActivate() {
System.out.println("ejbActivate()");
}
public void ejbPassivate() {
System.out.println("ejbPassivate()");
}
La classe du bean
 ejbCreate() correspond au create() de l'interface
Home
 Une seule méthode métier : hello()
 On la retrouve dans les interfaces distante et
locales.
 ejbActivate() et ejbPassivate() n'ont pas d'utilité
dans le cas de session bean stateless.
 Elles sont vides.
 …
Les EJBContexts : le lien avec le container

 Sert à encapsuler le domaine dans lequel évolue le


bean dans un objet.
 setSessionContext() appelé par le container.
 Un contexte par type de Bean
 SessionContext, EntityContext, MesageDrivenContext
 Méthodes correspondantes setSessionContext(),
setEntityContext(), setMessageDrivenBeanContext()
Les EJBContexts : le lien avec le container

public interface javax.ejb.EJBContext { * These are transaction methods


/* */
* Call these from within your bean to public boolean getRollbackOnly();
access public void setRollbackOnly();
* your own home object or local home public javax.transaction.UserTransaction
object. getUserTransaction();
* /*
* You can use them to create, destroy, or * These are security methods -
* find EJB objects and EJB local objects */
* of your own bean class type. public boolean
*/ isCallerInRole(java.lang.String);
public javax.ejb.EJBHome public java.security.Principal
getEJBHome(); getCallerPrincipal();
public javax.ejb.EJBLocalHome }
getEJBLocalHome();
Le descripteur de déploiement
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise
JavaBeans 2.0//EN" "http://java.sun.com/j2ee/dtds/ejb-jar_2_0.dtd">
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>Hello</ejb-name>
<home>examples.HelloHome</home>
<remote>examples.Hello</remote>
<local-home>examples.HelloLocalHome</local-home>
<local>examples.HelloLocal</local>
<ejb-class>examples.HelloBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
Le fichier .jar de l'EJB
 Il faut mettre tous les fichiers compilés + descripteurs
dans un .jar
 Depuis un IDE ou à la main
jar cf HelloWorld.jar *
 Contenu de HelloWorld.jar
META-INF/MANIFEST.MF
META-INF/ejb-jar.xml
examples/HelloBean.class
examples/HelloLocalHome.class
examples/HelloHome.class
examples/HelloLocal.class
examples/Hello.class
Déployer le bean

 Cette étape varie selon le container


 Simple copie avec JBoss,
 A l'aide d'un outil de déploiement spécifique (BAS…)
 Lors du déploiement
 Vérification du fichier.jar,
 Le container génère les EJBObjects et EJBHome,
 Le container génère les stubs et skeletons pour les appelsRMI-
IIOP.
 Vérifier le déploiement
 Le serveur doit vous avertir qu'il a bien chargé le bean.
Écriture d'un client
 Deux types de clients
1. Clients JAVA RMI-IIOP : ils utilisent JNDI pour localiser
les objets et Java Transaction API pour contrôler les
transactions.
2. Clients CORBA : par exemple écrits en C++… Ils utilisent
COS Naming Service et Object Transaction Service (OTS)
pour les transactions…
 Quel que soit le client
1. Localiser (lookup) un objet Home,
2. Utiliser cet objet Home pour créer (create) un EJBObject,
3. Appeler les méthodes de l'EJBObject,
4. Supprimer (remove) l'EJBObject.
Client : le code
package examples;
import javax.naming.Context;
import javax.naming.InitialContext;
import java.util.Properties;
/**
* This class is an example of client code which invokes
* methods on a simple stateless session bean.
*/
public class HelloClient {
public static void main(String[] args) throws Exception {
/* Setup properties for JNDI initialization.
* These properties will be read-in from
* the command-line. */
Properties props = System.getProperties();
/* Obtain the JNDI initial context .
* The initial context is a starting point for
* connecting to a JNDI tree. We choose our JNDI
* driver, the network location of the server, etc
* by passing in the environment properties. */
Context ctx = new InitialContext(props);
Client : le code
/* Get a reference to the home object - the
* factory for Hello EJB Objects */
Object obj = ctx.lookup("HelloHome");
/* Home objects are RMI-IIOP objects, and so
* they must be cast into RMI-IIOP objects
* using a special RMI-IIOP cast.
* See Appendix X for more details on this. */
HelloHome home = (HelloHome) javax.rmi.PortableRemoteObject.narrow(obj,
HelloHome.class);
/* Use the factory to create the Hello EJB Object */
Hello hello = home.create();
/* Call the hello() method on the EJB object. The
* EJB object will delegate the call to the bean,
* receive the result, and return it to us.
* We then print the result to the screen. */
System.out.println(hello.hello());
/* Done with EJB Object, so remove it.
* The container will destroy the EJB object. */
hello.remove();
}
}

Vous aimerez peut-être aussi