27/02/22 © Robert Godin. Tous droits réser vés.
1
15 Développement d'application de
base de données en Java
Patron d'architecture en couche (layer)
Couche présentation
Couche contrôle (coordonnateur d'application)
Couche domaine d'application (ou métier)
Couche de services.
– persistance
– transaction
– communication
– sécurité
– etc.
27/02/22 © Robert Godin. Tous droits réser vés.
3
15.1 Application Java/JDBC client-serveur
R é s e a u
L o g i c i e l i n t e r m é d i a i r e
P i l o t e d e t é l é c o m m u n i c a t i o n
P r o g r a m m e d 'a p p l i c a t i o n
L o g i c i e l i n t e r m é d i a i r e
P i l o t e d e t é l é c o m m u n i c a t i o n
S G B D
C l i e n t S e r v e u r
B D
P r o g r a m m e d 'a p p l i c a t i o n : - p r é s e n t a t i o n
- c o n t r ô l e
- d o m a i n e d 'a p p l i c a t i o n
S G B D
- p e r s i s t e n c e
- p a r t i e d u d o m a i n e d 'a p p l i c a t i o n ?
C l i e n t S e r v e u r
Cas d ’utilisation EnregistrerPrêts
Commis au prêt Système
1. Le commis invoque l'écran d'enregistrement du prêt
2. Le système demande la saisie de l'identificateur de l'utilisateur
3. Le commis saisit l'identificateur de l'utilisateur à l'aide de la carte de membre ou manuellement
4. Le système affi che le nombre de prêts en cours et demande de saisir l'identificateur de l'exemplaire.
5. Le commis entre l'identificateur de l'exemplaire à l'aide du lecteur optique ou manuellement
6. Le système enregistre le prêt, affi che un message
d'acquiescement.
27/02/22 © Robert Godin. Tous droits réser vés.
5
Cas de test pour scénario normal
Cas d ’exception : nombre maximal
d'emprunts (ici 2) atteint
27/02/22 © Robert Godin. Tous droits réser vés.
7
Cas d ’exception : exemplaire
non disponible
Cas d'utilisation et classes métiers concernées
Personne nom : String prénom : String
Membre
téléphoneRésidence : String nbMaxPrêts : Integer = 5 duréeMaxPrêts : Integer = 7
PrêtEnCours Employé
{UNIQUE : codeMatricule}
codeMatricule : String
catégorieEm ployé : enum (b ibliothécaire, co mm is ) catégorieUtilisateur
Exemplaire {UNIQUE: idExemplaire}
idExemplaire : String dateAchat : Date
statut : enum(prêté, disponible, retiré)
Prêt datePrêt : Date
1 0..*
1 0..*
Utilisateur {UNIQUE :idUtilisateur}
idUtilisateur : String
motPasse : String 11 0..*0..*
{disjointe, complète}
{disjointe, complète}
EnregistrerPrêts
(from PackageCasServicePrêt)
27/02/22 © Robert Godin. Tous droits réser vés.
9
Patron courtier BD : classes du
programme Java et tables concernées
Membre
té léph oneRésidence : String nbMaxPrêts : Integer = 5 duréeMaxPrêts : Integer = 7
PrêtEnCours Utilisateur
idUtilisateur : String m otPasse : String catégorie : String lesPrêts : Vector
CourtierBDUtilisateur
ch erch erVari ables Stati quesDeMem bre() ch erch erUtili sateu rParIdUti lisateur()
Table Utilisateur
Table Mem bre Table Mem breGénéral
Table Prêts EnCours Table Exem plaire
CourtierBDPrêtsEnCou rs chercherLesPrêtsEnCours() insérerPrêtEnCours ()
Courtie rBDExem plaire che rche rExem plai reParId Exem plaire() Prêt
datePrêt : Date
lExem plaire : Exem plaire lUtilisateur : Utilisateur
Exem plaire idExem plaire : String statut : String Person ne
nom : Stri ng préno m : String
Em ployé {UNIQUE : codeMatricule}
codeMatricule : String
catégorieEm ployé : enum (bibliothécaire, com m is)
Table Em p loyé
~ Data Access Object
(DAO) + Domain Data
Transfer Object
Classe Java pour Personne
package ExemplesJDBC.SyLeRat;
public class Personne { protected String nom;
protected String prénom;
public Personne(String nom,String prénom) { this.nom = nom;
this.prénom = prénom;
}
public String getNom(){return nom;}
public String getPrénom(){return prénom;}
public void setNom(String nom){this.nom = nom;}
public void setPrénom(String prénom){this.prénom = prénom;}
}
Lecteurs/modifieurs pour attributs
(peut en faire un Java Bean)
27/02/22 © Robert Godin. Tous droits réser vés.
11
Classe Java pour Utilisateur
package ExemplesJDBC.SyLeRat;
import java.util.*;
public class Utilisateur extends Personne { protected String idUtilisateur;
protected String motPasse;
protected String catégorie;
protected Vector lesPrêts; // Association avec Prêt // NB Ce constructeur de crée pas lesPrêts
public Utilisateur(String idUtilisateur, String motPasse, String nom, String prénom, String catégorie){
super(nom,prénom);
this.idUtilisateur = idUtilisateur;
this.motPasse = motPasse;
this.catégorie = catégorie;
}
public String getIdUtilisateur(){return idUtilisateur;}
public String getMotPasse(){return motPasse;}
public String getCatégorie(){return catégorie;}
public Vector getLesPrêts(){return lesPrêts;}
public int getNbPrêtsEnCours(){
Enumeration enumerationPrêts = lesPrêts.elements();
int nbPrêtsEnCours = 0;
while (enumerationPrêts.hasMoreElements()){
Prêt unPrêt = (Prêt)enumerationPrêts.nextElement();
if (unPrêt instanceof PrêtEnCours){
nbPrêtsEnCours++;
} }
return nbPrêtsEnCours;
}
public void setIdUtilisateur(String idUtilisateur){this.idUtilisateur = idUtilisateur;}
public void setMotPasse(String motPasse){this.motPasse = motPasse;}
public void setCatégorie(String catégorie){this.catégorie = catégorie;}
public void setLesPrêts(Vector lesPrêts){this.lesPrêts = lesPrêts;}
}
Lecteur pour donnée dérivée
Lecteurs/modifieurs
pour naviguer les
associations
Classe Java pour Membre
package ExemplesJDBC.SyLeRat;
import java.util.*;
public class Membre extends Utilisateur { private static int nbMaxPrêts;
private static int duréeMaxPrêt;
private String téléphoneRésidence;
public Membre(String idUtilisateur, String motPasse, String nom, String prénom, String catégorie, String téléphoneRésidence){
super(idUtilisateur, motPasse, nom, prénom, catégorie);
this.téléphoneRésidence = téléphoneRésidence;
}
public static int getNbMaxPrêts(){return nbMaxPrêts;}
public static int getDuréeMaxPrêt(){return duréeMaxPrêt;}
public static void setNbMaxPrêts(int leNbMaxPrêts){nbMaxPrêts = leNbMaxPrêts;}
public static void setDuréeMaxPrêts(int laDuréeMaxPrêt){duréeMaxPrêt = laDuréeMaxPrêt;}
public void setTéléphoneRésidence(String téléphoneRésidence) {this.téléphoneRésidence = téléphoneRésidence;}
public String getTéléphoneRésidence(){return téléphoneRésidence;}
public int getNbRetards(){
Enumeration enumerationPrêts = lesPrêts.elements();
int nbRetards = 0;
Calendar maintenant = Calendar.getInstance(); // Calendrier avec date actuelle // Soustrait ensuite la durée maximale en jours pour obtenir la date minimale // avant laquelle il y a un retard
maintenant.add(Calendar.DATE,-duréeMaxPrêt);
java.sql.Date dateMinSansRetard = new java.sql.Date(maintenant.getTime().getTime());
while (enumerationPrêts.hasMoreElements()){
Prêt unPrêt = (Prêt)enumerationPrêts.nextElement();
if (unPrêt instanceof PrêtEnCours){
if (dateMinSansRetard.after(unPrêt.getDatePrêt())){
nbRetards++;
} } }
return nbRetards;
}
public boolean conditionsPrêtAcceptées(){
Attributs et méthodes
static pour attributs de
classe (ou singleton)
27/02/22 © Robert Godin. Tous droits réser vés.
13
Classe Java pour Employé
package ExemplesJDBC.GererPrets;
import java.util.*;
public class Employé extends Utilisateur { private String codeMatricule;
private String catégorieEmployé;
public Employé(String idUtilisateur, String motPasse, String nom,
String prénom, String catégorie, String codeMatricule, String catégorieEmployé){
super(idUtilisateur, motPasse, nom, prénom, catégorie);
this.codeMatricule = codeMatricule;
this.catégorieEmployé = catégorieEmployé;
}
public String getCodeMatricule(){return codeMatricule;}
public String getCatégorieEmployé(){return catégorieEmployé;}
public void setCodeMatricule(String codeMatricule) {this.codeMatricule = codeMatricule;}
public void setCatégorieEmployé(String catégorieEmployé) {this.catégorieEmployé = catégorieEmployé;}
}
Classe Java pour Prêt
package ExemplesJDBC.SyLeRat;
import java.sql.Date;
public class Prêt {
protected Utilisateur lUtilisateur;
protected java.sql.Date datePrêt;
protected Exemplaire lExemplaire;
public Prêt(Utilisateur lUtilisateur,java.sql.Date datePrêt, Exemplaire lExemplaire) { this.lUtilisateur = lUtilisateur;
this.datePrêt = datePrêt;
this.lExemplaire = lExemplaire;
}
public java.sql.Date getDatePrêt(){return datePrêt;}
public String getIdExemplaire(){return lExemplaire.getIdExemplaire();}
public String getIdUtilisateur(){return lUtilisateur.getIdUtilisateur();}
}
27/02/22 © Robert Godin. Tous droits réser vés.
15
Classe Java pour PrêtEnCours
package ExemplesJDBC.GererPrets;
public class PrêtEnCours extends Prêt {
public PrêtEnCours(Utilisateur lUtilisateur,java.sql.Date datePrêt, Exemplaire lExemplaire) {
super(lUtilisateur,datePrêt,lExemplaire);
}
// Le constructeur suivant ne construit pas le lien vers Exemplaire public PrêtEnCours(Utilisateur lUtilisateur,java.sql.Date datePrêt) { super(lUtilisateur,datePrêt,null);
}
}
Classe Java pour Exemplaire
package ExemplesJDBC.SyLeRat;
public class Exemplaire {
private String idExemplaire;
private String statut;
public Exemplaire(String idExemplaire,String statut) { this.idExemplaire = idExemplaire;
this.statut = statut;
}
public String getStatut(){return statut;}
public String getIdExemplaire(){return idExemplaire;}
}
27/02/22 © Robert Godin. Tous droits réser vés.
17
CourtierBDUtilisateur
package ExemplesJDBC.GererPrets;
import java.sql.*;
import java.util.*;
public class CourtierBDUtilisateur{
private Connection uneConnection;
// Constructeur pour connexion passée par le créateur public CourtierBDUtilisateur(Connection laConnection){
this.uneConnection = laConnection;
}
…
public Utilisateur chercherUtilisateurParIdUtilisateur(String idUtilisateur) // Retourne un objet Membre ou un Employé selon le cas
throws Exception {
// Verrouillage de l'utilisateur pour sérialisabilité (Oracle mode READ COMMITTED) PreparedStatement unEnoncéSQL = uneConnection.prepareStatement
("SELECT motPasse,nom,prénom,catégorieUtilisateur,téléphoneRésidence,codeMatricule,catégorieEmployé "+
"FROM Membre m, Utilisateur u, Employé e WHERE u.idUtilisateur = ? AND "+
"u.idUtilisateur = m.idUtilisateur (+) AND "+
"u.idUtilisateur = e.idUtilisateur (+) FOR UPDATE");
unEnoncéSQL.setString(1,idUtilisateur);
ResultSet résultatSelect = unEnoncéSQL.executeQuery();
if (résultatSelect.next ()){
if (résultatSelect.getString ("catégorieUtilisateur").equals("membre")){
Membre leMembre = new Membre(
idUtilisateur,résultatSelect.getString ("motPasse"),
résultatSelect.getString ("nom"),résultatSelect.getString ("prénom"), résultatSelect.getString ("catégorieUtilisateur"),
résultatSelect.getString ("téléphoneRésidence"));
unEnoncéSQL.close();
return leMembre;
}
else{// Pas un Membre, doit être un Employé
Employé lEmployé = new Employé(idUtilisateur,résultatSelect.getString ("motPasse");
…
Diagramme de séquence pour CourtierBDUtilisateur
: ContrôleEnregistrerPrêts : CourtierBDUtilisateur
:java.sql .Connection
:java.sql.Statement
: Membre
: Em pl oyé 2. chercherUtilisateur(idUtilisateur)
1. «create»(uneConnection)
3. prepareStatement()
4. executeQuery()
5. [catégorie = 'membre']«create»
7. unU til isateur
6. [catégorie='employé']«create»
27/02/22 © Robert Godin. Tous droits réser vés.
19
Classe UsineConnection
package ExemplesJDBC.GererPrets;
import java.sql.*;
public class UsineConnection { public UsineConnection() {}
public Connection getConnectionSansAutoCommit(
String nomPilote, // "oracle.jdbc.driver.OracleDriver" pour Oracle
String URLBD, // exemple : "jdbc:oracle:thin:@localhost:1521:ora817i"
String authorizationID, String password)
throws Exception {
Class.forName (nomPilote);
Connection uneConnection = DriverManager.getConnection (URLBD, authorizationID,password);
uneConnection.setAutoCommit(false);
return uneConnection;
}
public Connection getConnection(
String nomPilote, // "oracle.jdbc.driver.OracleDriver" pour Oracle
String URLBD, // exemple : "jdbc:oracle:thin:@localhost:1521:ora817i"
String authorizationID, String password)
throws Exception {
Class.forName (nomPilote);
Connection uneConnection = DriverManager.getConnection (URLBD, authorizationID,password);
return uneConnection;
}
}
Courtier CourtierBDPrêtEnCours : chercherLesPrêtsEnCours
package ExemplesJDBC.GererPrets;
import java.sql.*;
import java.util.*;
public class CourtierBDPrêtEnCours { private Connection uneConnection;
…
public void chercherLesPrêtsEnCours(Utilisateur unUtilisateur) // Dématérialiser les PrêtEnCours d'un Utilisateur
throws Exception{
// Verrouiller la table des prêts en cours pour sérialisabilité // (Oracle mode READ COMMITTED)
PreparedStatement unEnoncéLock = uneConnection.prepareStatement(
"LOCK TABLE PrêtEnCours IN SHARE ROW EXCLUSIVE MODE");
unEnoncéLock.execute();
unEnoncéLock.close();
PreparedStatement unEnoncéSQL = uneConnection.prepareStatement ("SELECT datePrêt,idExemplaire "+
"FROM PrêtEnCours WHERE idUtilisateur = ? " );
String idUtilisateur = unUtilisateur.getIdUtilisateur();
unEnoncéSQL.setString(1,idUtilisateur);
ResultSet résultatSelect = unEnoncéSQL.executeQuery();
// lesPrêts contiendra la collection des objets PrêtEnCours Vector lesPrêts = new Vector();
while (résultatSelect.next ()){
PrêtEnCours unPrêt = new PrêtEnCours(unUtilisateur,résultatSelect.getDate(1));
lesPrêts.addElement(unPrêt);
}
// Faire les références inverses ! unUtilisateur.setLesPrêts(lesPrêts);
unEnoncéSQL.close();
}
… }
27/02/22 © Robert Godin. Tous droits réser vés.
21
Matérialisation d ’un PrêtEnCours : insérerPrêtEnCours
package ExemplesJDBC.GererPrets;
import java.sql.*;
import java.util.*;
public class CourtierBDPrêtEnCours { private Connection uneConnection;
…
public void insérerPrêtEnCours (PrêtEnCours unPrêtEnCours) // Matérialise un nouveau PrêtEnCours dans la BD
throws Exception, SQLException {
PreparedStatement unEnoncéSQL = uneConnection.prepareStatement ("INSERT INTO PrêtEnCours(idExemplaire,idUtilisateur)"+
"VALUES(?,?)");
unEnoncéSQL.setString(1,unPrêtEnCours.getIdExemplaire());
unEnoncéSQL.setString(2,unPrêtEnCours.getIdUtilisateur());
//NB la date est générée automatiquement par le serveur de BD (default sysdate) // et le statut est modifié par un TRIGGER
int n = unEnoncéSQL.executeUpdate();
unEnoncéSQL.close();
if (n != 1){throw new Exception("Insertion dans PrêtEnCours a échoué");}
}
}
Enjeux de la conception des courtiers
Granularité des courtiers
Granularité de
matérialisation/dématérialisation
– minimiser les appels au serveur de BD
– limiter le volume de données à
transférer
27/02/22 © Robert Godin. Tous droits réser vés.
23
Classe de contrôle
ControleEnregistrerPrets
package ExemplesJDBC.GererPrets;
/* Classe de contrôle simple pour EnregistrerPrêts * Interface à l'utilisateur minimaliste
* NB Vérifie les conditions de prêt et le statut de l'exemplaire au niveau du programme client */
import java.sql.*;
import javax.swing.JOptionPane;
import java.util.*;
class ControleEnregistrerPrets {
public static void main (String args []) throws Exception { // Création d'une Connection globale pour l'application UsineConnection uneUsineConnection = new UsineConnection();
Connection uneConnection = uneUsineConnection.getConnectionSansAutoCommit(
"oracle.jdbc.driver.OracleDriver",
"jdbc:oracle:thin:@localhost:1521:ora817i", "clerat","oracle");
try{
// Dématérialiser l'Utilisateur et ses PrêtsEnCours Membre unMembre = null;
String idUtilisateur =
JOptionPane.showInputDialog("Entrez l'identificateur de l'utilisateur: ");
// Création du courtier et dématérialisation de l'Utilisateur
CourtierBDUtilisateur unCourtierBDUtilisateur = new CourtierBDUtilisateur(uneConnection);
Utilisateur unUtilisateur =
unCourtierBDUtilisateur.chercherUtilisateurParIdUtilisateur(idUtilisateur);
//Création du courtier et dématérialisation des PrêtsEnCours
CourtierBDPrêtEnCours unCourtierBDPrêtEnCours = new CourtierBDPrêtEnCours(uneConnection);
unCourtierBDPrêtEnCours.chercherLesPrêtsEnCours(unUtilisateur);
JOptionPane.showMessageDialog(null,
"Nombre de prêts en cours :" + unUtilisateur.getNbPrêtsEnCours());
…
uneTransaction
: Commis au prêt :
ContrôleEnregistrerPrêts :
CourtierBDUtilisateur
: CourtierBDPrêtsEnCours
:
CourtierBDExemplaire : Usin eConnection
uneConnection 2. getConnexionSansAutoCommit( )
4. uneConnection
9. «create»(uneConnection) 10 . chercherLesPrêtsEnCours(un Utilisateur )
18. insérerPrêtEnCou rs (unPrêtEnCours) 7. chercherUtilisateur(idUtilisateur)
12. chercherVariablesStatiquesDeMembre( ) 6. «cre ate»(uneConnection)
15. «create»(uneConnection) 16. chercherExem plaire (i dExemplaire )
3. «create»
8. prepareStatement()
11. prepareStatement()
13. prepareStatement()
17. prepareStatement()
20. commit() 21. close() 1. créerNouveauPrêt()
5 . entrer(idUtilisateur)
14. entrer(i dExempl aire)
19. prepapreStatement()
27/02/22 © Robert Godin. Tous droits réser vés.
25
uneTransaction : Commis au prêt :
ContrôleEnregistrerPrêts : CourtierBDUtilisateur
: CourtierBDPrêtsEnCours
: CourtierBDExemplaire
: Usin eConnection
uneConnection 2. getConnexionSansAutoCommit( )
4. uneConnection
9. «create»(uneConnection) 10 . chercherLesPrêtsEnCours(un Utilisateur )
18. insérerPrêtEn Cours (unPrêtEnCours) 7. chercherUtilisateur(idUtilisateur)
12. chercherVariablesStatiquesDeMembre( ) 6. «cre ate»(uneConnection)
15. «create»(uneConnection) 16. chercherExem plaire (i dExempla ire )
3. «create»
8. prepareStatement()
11. prepareStatement()
13. prepareStatement()
17. prepareStatement()
20. commit() 21. cl ose() 1. créerNouveauPrêt()
5 . entrer(idUtilisateur)
14. entrer(idExemplaire)
19. prepapreStatement()
15.1.1 Enjeux de conception d'une application Java/JDBC
Dépendance
au temps de
réflexion
Limiter les verrouillages ?
Transaction T
1Transaction T
2SQL> SELECT * FROM PrêtEnCours 2 WHERE idUtilisateur = 2;
IDEXEMPLAI DATEPRÊT IDUTILISAT --- --- ---
3 02-03-21 2
SQL> SELECT * FROM PrêtEnCours 2 WHERE idUtilisateur = 2;
IDEXEMPLAI DATEPRÊT IDUTILISAT --- --- ---
4 02-03-21 2
SQL> INSERT INTO
2 PrêtEnCours(idExemplaire,idUtilisateur) 3 VALUES(4,2);
1 row created.
SQL> COMMIT;
Commit complete.
SQL> INSERT INTO
2 PrêtEnCours(idExemplaire,idUtilisateur) 3 VALUES(5,2);
1 row created.
SQL> COMMIT;
Commit complete.
Dépasse la limite du nombre de prêts (maximum 2)
27/02/22 © Robert Godin. Tous droits réser vés.
27
Limiter la durée des transactions
Contraintes de sérialisabilité ?
Vérification des contraintes par le serveur
Transaction T
1Transaction T
2SQL> SELECT * FROM PrêtEnCours 2 WHERE idUtilisateur = 2;
IDEXEMPLAI DATEPRÊT IDUTILISAT --- --- ---
3 02-03-21 2
SQL> SELECT * FROM PrêtEnCours 2 WHERE idUtilisateur = 2;
IDEXEMPLAI DATEPRÊT IDUTILISAT --- --- ---
4 02-03-21 2
SQL> INSERT INTO
2 PrêtEnCours(idExemplaire,idUtilisateur) 3 VALUES(4,2);
1 row created.
SQL> COMMIT;
Commit complete.
SQL> INSERT INTO
2 PrêtEnCours(idExemplaire,idUtilisateur) 3 VALUES(5,2);
INSERT INTO
PrêtEnCours(idExemplaire,idUtilisateur) *
ERROR at line 1:
ORA-20101: le nombre maximal d'emprunts est atteint
ORA-06512: at "CLERAT.BIPRÊTENCOURSVÉRIFIER", line 59
ORA-04088: error during execution of trigger 'CLERAT.BIPRÊTENCOURSVÉRIFIER'
Non
sérialisabilité
perçue par T2
27/02/22 © Robert Godin. Tous droits réser vés.
29
Contrôle de concurrence optimiste par estampillage explicite
Lecture en une première transaction
– Note l’estampille courante (ou numéro de version, …)
Écriture en une deuxième transaction distincte
– Vérifie si l’état a changé depuis la lecture
Si non, met à jour les données et l’estampille
Si oui, annulation
Ne bloque pas les objets lus
Réduire l'interactivité
Nom: EnregistrerPrêtsSimple
Description courte : Enregistrer les prêts en un aller-retour au système Type: Interactif
Description : Ce cas d'utilisation est déclenché par le commis au prêt suite à une requête d'un membre ou d'un employé et lui permet d'enregistrer un prêt en un aller-retour au système.
Exigence d'intégrité : la séquence constitue une transaction Séquence normale d'interaction :
Commis au prêt Système
1. Le commis invoque l'écran d'enregistrement du prêt
2. Le système demande la saisie de l'identificateur de l'utilisateur et de l’exemplaire
3. Le commis saisit l'identificateur de l'utilisateur à l'aide de la carte de membre ou manuellement et entre l'identificateur de l'exemplaire à l'aide du lecteur optique ou manuellement.
4. Le système enregistre le prêt, affi che un message
d'acquiescement.
27/02/22 © Robert Godin. Tous droits réser vés.
31
ControleEnregistrerPretsSimple
uneTransaction : Commis au prêt :
ContrôleEnregistrerPrêts
: CourtierBDPrêtsEnCours :
UsineConnection
uneConnection 1. créerNouveauPrêt()
5. entrer(idUtilisate ur, idExempl aire)
6. «create»(uneConnection) 7. insérerPrêtEnCours (unPrêtEnCours)
2. getConnexion( )
4. uneConnection 3. «create»
9. close()
8. prepapreStatem ent()
public typeRetour nomMéthodeCourtier(listeParamètres) throws Exception {
Connection uneConnection = uneUsineConnection.getConnection…
// Utiliser uneConnection
…
uneConnection.close();
}
Libérer la connexion entre les appels
Transaction ne peut chevaucher les appels
Ouverture/fermeture couteuse
– Solution : connection pooling (JDBC 2)
27/02/22 © Robert Godin. Tous droits réser vés.
33
15.1.2 Gestion de la sécurité
Qui gère l ’idUtilisateur et le mot de passe ?
– par les données : le SGBD
– par les traitements : le programme
client
ControleEnrPretsSecuriteParDonnees
package ExemplesJDBC.GererPrets;
/* Classe de contrôle simple pour EnregistrerPrêts * Interface à l'utilisateur minimaliste
* NB Vérifie les conditions de prêt et le statut de l'exemplaire au niveau du programme client
*/ import java.sql.*;
import javax.swing.JOptionPane;
import java.util.*;
class ControleEnrPretsSecuriteParDonnees {
public static void main (String args []) throws Exception { String idCommis =
JOptionPane.showInputDialog("Entrez l'identificateur du commis au prêt: ");
String motDePasse =
JOptionPane.showInputDialog("Entrez le mot de passe : ");
// Création d'une Connection à partir du idCommis et de son motDePasse UsineConnection uneUsineConnection = new UsineConnection();
Connection uneConnection = uneUsineConnection.getConnectionSansAutoCommit(
"oracle.jdbc.driver.OracleDriver",
"jdbc:oracle:thin:@localhost:1521:ora817i", idCommis, motDePasse);
try{
// Dématérialiser l'Utilisateur et ses PrêtsEnCours
…
// Le reste du code est identique à ControleEnregistrerPrets
27/02/22 © Robert Godin. Tous droits réser vés.
35
ControleEnrPretsSecuriteParTraitement
package ExemplesJDBC.GererPrets;
/* Classe de contrôle pour EnregistrerPrêts * Sécurité «par les traitements»
* Interface à l'utilisateur minimaliste
* NB Vérifie les conditions de prêt et le statut de l'exemplaire au niveau du programme client */
import java.sql.*;
import javax.swing.JOptionPane;
import java.util.*;
class ControleEnrPretsSecuriteParTraitement {
public static void main (String args []) throws Exception {
// Création d'une Connection avec un authorizationID SQL indépendant du idCommis UsineConnection uneUsineConnection = new UsineConnection();
Connection uneConnection = uneUsineConnection.getConnectionSansAutoCommit(
"oracle.jdbc.driver.OracleDriver",
"jdbc:oracle:thin:@localhost:1521:ora817i", "clerat", "oracle");
try{
// Authentifier le commis au prêt (en utilisant la table Utilisateur) String idCommis =
JOptionPane.showInputDialog("Entrez l'identificateur du commis au prêt: ");
CourtierBDUtilisateur unCourtierBDUtilisateur = new CourtierBDUtilisateur(uneConnection);
Utilisateur lUtilisateur =
unCourtierBDUtilisateur.chercherUtilisateurParIdUtilisateur(idCommis);
if (!(lUtilisateur instanceof Employé)){
JOptionPane.showMessageDialog(null,"Pas un employé :"+idCommis);
}else {
Employé leCommis = (Employé)lUtilisateur;
if (!(leCommis.getCatégorieEmployé().equals("commis"))){
JOptionPane.showMessageDialog(null,"Pas un commis au prêt:"+idCommis);
} else {
String motDePasse =
JOptionPane.showInputDialog("Entrez le mot de passe : ");
if (!(leCommis.getMotPasse().equals(motDePasse))){
JOptionPane.showMessageDialog(null,"Mot de passe invalide:"+motDePasse);
}else{//OK Commis est authentifié
// Dématérialiser l'Utilisateur et ses PrêtsEnCours …
// Le reste du code est identique à ControleEnregistrerPrets
15.1.3 Façade pour les services de la couche application
Membre PrêtEnCours
Utilisateur
CourtierBDUtilisateur CourtierBDPrêtsEnCours CourtierBDExemplaire Prêt
Exemplaire Personne
ControleEnregistrerPretsAvecFacade
FacadeEnregistrerPrets
UsineConnection Connection
27/02/22 © Robert Godin. Tous droits réser vés.
37
Diagramme de séquence pour
ControleEnregistrerPretAvecFacade
: ControleEnregistrerPretsAvecFacade : FacadeEnregistrerPrets : UsineConnection uneConnection
3. chercherOTDUtilisateurPrets()
4. getStatutExemplaire()
5. insererPretEnCours( )
6. confirmerTransaction( ) 1. «create»
1.1. getConnexionSansAuto Commit( )
1.1.1. «create»
2. u neConnectio n
7. commit() 8. close()
Dépendance réduite par rapport à la
couche persistence
Patron d'objet de transfert de données (OTD)
uneClasseControle unOTD uneClasseFacade
1. getOTD()
3. getPropriété1() 4. getPropriété2() 5. getPropriété3() etc.
2. unOTD
27/02/22 © Robert Godin. Tous droits réser vés.
39
ControleEnregistrerPretsSimpleAvecFacade
:ControleEnregistrerPretsSimpleAvecFacade :FacadeEnregistrerPretsSimple : UsineC onne ction uneConnection 1. «create»
2. insererPretEnCours(idUtilisateur,idExemplaire)
3. getConn ection() 5. uneCon nection
6. close()
4. «create»
Connexion libérée
entre les appels
15.2 Développement d'applications Web par servlet Java
F u r e t e u r W e b : - p r é s e n t a t i o n
S G B D
- p e r s i s t e n c e
- p a r t i e d u d o m a i n e d 'a p p l i c a t i o n ?
C l i e n t m i n c e S e r v e u r B D
S e r v e u r d 'a p p l i c a t i o n : - c o n t r ô l e
- d o m a i n e d 'a p p l i c a t i o n
S e r v e u r d ' a p p l i c a t i o n
27/02/22 © Robert Godin. Tous droits réser vés.
41
15.2.1 Principe de base du Web : le protocole HTTP et le langage de
présentation HTML
F u r e t e u r W e b S e r v e u r W e b
R e q u ê t e H T T P
R é p o n s e H T T P
15.2.2 Développement de servlet Java
S e r v e u r d 'a p p l i c a t i o n ( W e b )
C o n t e n e u r à s e r v l e t
2 . L e s e r v e u r t é l é c h a r g e l a F O R M H T M L
F u r e t e u r W e b
s e r v l e t J a v a
3 . L e f u r e t e u r e n v o i e d e s
p a r a m è t r e s ( H T T P P O S T ) 4 . L e s e r v e u r d é l è g u e l ' a p p e l a u c o n t e n e u r à s e r v l e t 1 . L e f u r e t e u r I n v o q u e l ' é c r a n
d e s a i s i e ( H T T P G E T )
5 . L e c o n t e n e u r à s e r v l e t d é m a r r e u n f i l d e l a s e r v l e t
7 . L a s e r v e l t p r o d u i t l a r é p o n s e H T T P q u i e s t r e t o u r n é e a u f u r e t e u r
S e r v e u r B D
6 . L a s e r v e l t f a i t a p p e l a u
s e r v e u r d e B D B D
F O R M H T M L
27/02/22 © Robert Godin. Tous droits réser vés.
43
Diagramme de séquence de l'invocation de la servlet
ServletEnregistrerPretSimpleFacade
unFureteur unServeurWeb
: ServletEnregistrerPretSimpleFacade
: FacadeEnregistrerPretSimple 1. requête HTTP POST
2. doPost(HttpServletRequest, HttpServletResponse)
5. HttpServletResponse 6. réponse HTTP (document HTML)
3. insererPretEnCours(idUtilisateur,idExemplaire ) 4. date du prêt
Réutilisation des classes du client-serveur
<html>
<head>
<title>
Bibliothèque LeRat : Enregistrer un prêt (avec un servlet, interaction simplifiée)
</title>
</head>
<body>
<form action = "servlet/ServletEnregistrerPretsSimpleFacade" method = "post">
<p> Entrez l'identificateur de l'utilisateur et de l'exemplaire et cliquez Soumettre</p>
<table>
<tr>
<td>Identificateur d'utilisateur</td>
<td><input type = "text" name = "idUtilisateur" /></td>
</tr>
<tr>
<td>Identificateur d'exemplaire</td>
<td><input type = "text" name = "idExemplaire" /></td>
</tr>
</table>
<input type = "submit" value = "Soumettre" />
</form>
</body>
</html>
27/02/22 © Robert Godin. Tous droits réser vés.
45
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.sql.*;
public class ServletEnregistrerPretsSimpleFacade extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
//Chercher le paramètre idUtilisateur de la FORM HTML et créer un Utilisateur String idUtilisateur = "";
try { idUtilisateur = request.getParameter("idUtilisateur"); } catch (Exception e) { e.printStackTrace(); }
//Chercher le paramètre idExemplaire de la FORM HTML et créer un Exemplaire String idExemplaire = "";
try { idExemplaire = request.getParameter("idExemplaire"); } catch (Exception e) { e.printStackTrace(); }
// Entête de la page de réponse HTML response.setContentType("text/html");
OutputStreamWriter unOutputStreamWriter =
new OutputStreamWriter(response.getOutputStream());
PrintWriter out = new PrintWriter(unOutputStreamWriter);
out.println("<html>");
out.println("<head><title>Réponse de ServletEnregistrerPretsSimpleFacadeEJB</title></head>");
out.println("<body>");
FacadeEnregistrerPretsSimple uneFacadeEnregistrerPretsSimple = null;
try{
uneFacadeEnregistrerPretsSimple = new FacadeEnregistrerPretsSimple();
// Enregistrer le prêt en passant par la façade java.sql.Date datePret =
uneFacadeEnregistrerPretsSimple.insererPretEnCours(idUtilisateur,idExemplaire);
// Message de confirmation du prêt
out.println("Prêt de l'exemplaire " + idExemplaire +
" à l'utilisateur " + idUtilisateur + " confirmé.<br>Date :" + datePret);
}
…
15.2.3 Cycle de vie d'une servlet
Compilation et démarrage à la
première invocation (par conteneur)
– init() appelé une fois
permet d ’initialiser des ressources (e.g.
connexion)
– nouveau fil à chaque invocation d ’une méthode de service (doGet, doPost,…)
– destroy() à la fin
e.g. fermer connexion
27/02/22 © Robert Godin. Tous droits réser vés.
47
15.2.4 Gestion d'une session HTTP dans une servlet
La FORM
n ’envoie que
le idUtilisateur
FormIdentificationUtilisateurFacade.html
<html>
<head>
<title> Exemple de session http pour cas Enregistrer Prêts : Identification utilisateur
</title>
</head>
<body>
<form action = "servlet/ServletIdentificationUtilisateurFacade" method = "post">
<p>Entrez l'identifiant de l'utilisateur et cliquez Soumettre</p>
<input type = "text" name = "idUtilisateur" />
<input type = "submit" value = "Soumettre" />
</form>
</body>
</html>
27/02/22 © Robert Godin. Tous droits réser vés.
49
EnregistrerPrets en deux servlets
unFureteur unServeurWeb
: ServletIdentificationUtilisateurFacade
: ServletTerminerPretFacade uneSession :
HttpSession
uneFacadeEnregistrerPrets : FacadeEnregistrerPrets
uneTransaction 1. requête HTTP POST pour ServletIdentificationUtilisateurFacade
9. réponse HTTP (FormTerminerPret)
2. doPost(HttpServletRequest, HttpServletResponse)
8. HttpServletResponse
15. insererPretEnCours(idUtilisateur,idExemplaire ) 5. chercherOTDUtilisateurPrets()
4. «create»
3. «create»
6. setAttribute('uneFacadeEnregistrerPrets', uneFacadeEnregistrerPrets)
10. requête HTTP POST pour ServletTerminerPretFacade
11. doPost(HttpServletRequest, HttpServletResponse)
14. getStatutExem plaire() 12. getAttribute('uneFacadeEnregistrerPrets')
16. confirm erTransaction( ) 17. HttpServletResponse
18. réponse HTTP (confirmation)
7. setAttribute('idUtilis ateur',idUtilis ateur)
13. getAttribute('idUtilisateur')
…
public class ServletIdentificationUtilisateurFacade extends HttpServlet { public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
//Chercher le paramètre idUtilisateur de la form String idUtilisateur = "";
try { idUtilisateur = request.getParameter("idUtilisateur"); } catch (Exception e) { e.printStackTrace(); }
// Créer un objet session si non existant
HttpSession uneSession = request.getSession(true);
// Entête de la page de réponse html response.setContentType("text/html");
…
try{
// Créer la facade et chercher l'OTDUtilisateurPrets
FacadeEnregistrerPrets uneFacadeEnregistrerPrets = new FacadeEnregistrerPrets();
OTDUtilisateurPrets unOTDUtilisateurPrets =
uneFacadeEnregistrerPrets.chercherOTDUtilisateurPrets(idUtilisateur);
// Affichage de l'idUtilisateur et du nombre de prêts out.println("Utilisateur :" + idUtilisateur);
out.println(" Nombre de prêts en cours :" + unOTDUtilisateurPrets.getNbPretsEnCours()+"<br>");
// Vérifier si les conditions préalables sont violées
…
}else{
// Sauvegarder les objets du contexte de la session
uneSession.setAttribute("uneFacadeEnregistrerPrets", uneFacadeEnregistrerPrets);
uneSession.setAttribute("idUtilisateur", idUtilisateur);
// Construire la FORM pour saisir l'idExemplaire
out.println("<form action = \"ServletTerminerPretFacade\" method = \"post\">");
out.println("<p>Entrez l'identifiant de l'exemplaire et cliquez Soumettre</p>");
out.println("<input type = \"text\" name = \"idExemplaire\" />");
out.println("<input type = \"submit\" value = \"Soumettre\" />");
out.println("</form>");
} ...
27/02/22 © Robert Godin. Tous droits réser vés.
51
…
public class ServletTerminerPretFacade extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//Chercher le paramètre idUtilisateur de la form String idExemplaire = "";
try { idExemplaire = request.getParameter("idExemplaire"); } catch (Exception e) { e.printStackTrace(); }
// Chercher l'objet de la session en cours
HttpSession uneSession = request.getSession(false);
// Chercher les objets du contexte de la session en cours FacadeEnregistrerPrets uneFacadeEnregistrerPrets =
(FacadeEnregistrerPrets)uneSession.getAttribute("uneFacadeEnregistrerPrets");
String idUtilisateur = (String)uneSession.getAttribute("idUtilisateur");
// Entête de la page de réponse html
…
try{
// Vérifier statut de l'exemplaire
String statut = uneFacadeEnregistrerPrets.getStatutExemplaire(idExemplaire);
if (statut.equals("disponible")){
// Enregistrer le prêt en passant par la façade java.sql.Date datePret =
uneFacadeEnregistrerPrets.insererPretEnCours();
…
finally{
try{
out.println("</body></html>");
out.close();
uneFacadeEnregistrerPrets.confirmerTransaction();
}
catch(Exception lException){
lException.printStackTrace();
} } } }
15.2.5 DataSource,
ConnectionPoolDataSource et PooledConnection
Passage par serveur JNDI (Java Naming and Directory Interface)
– e.g. serveur LDAP
– repérage de ressources (e.g. serveur BD)
– accès sécurisé
27/02/22 © Robert Godin. Tous droits réser vés.
53
Ouverture d ’une Connection en passant par DataSource
package ExemplesJDBC.GererPrets;
import java.sql.*;
import javax.naming.*;
import javax.sql.*;
public class UsineConnection { public UsineConnection() {}
…
public Connection getConnectionFromDataSource(
String nomDataSource) throws Exception {
InitialContext unContexte = new InitialContext();
DataSource unDataSource =
(DataSource)unContexte.lookup(nomDataSource);
Connection uneConnection = unDataSource.getConnection();
return uneConnection;
}
}
Enregistrement du DataSource par descripteur de
déploiement XML pour serveur embarqué OC4J de Oracle9i JDevelopper (généré par JDevelopper)
Connection uneConnection =
uneUsineConnection.getConnectionFromDataSource("jdbc/ora9icleratCoreDS");
<?xml version = '1.0' encoding = 'windows-1252'?>
<!DOCTYPE data-sources PUBLIC "Orion data-sources" "http://xmlns.oracle.com/ias/dtds/data-sources.dtd">
<data-sources>
<data-source class="com.evermind.sql.DriverManagerDataSource"
connection-driver="oracle.jdbc.driver.OracleDriver"
ejb-location="jdbc/ora9icleratDS"
inactivity-timeout="30"
location="jdbc/ora9icleratCoreDS"
name="ora9icleratDS"
password="oracle"
pooled-location="jdbc/ora9icleratPooledDS" url="jdbc:oracle:thin:@localhost:1521:ora9i"
username="clerat"
xa-location="jdbc/xa/ora9icleratXADS"/>
</data-sources>
27/02/22 © Robert Godin. Tous droits réser vés.
55
Partage d'un pool de connexions
package ExemplesJDBC.GererPrets;
import java.sql.*;
import javax.naming.*;
import javax.sql.*;
import oracle.jdbc.pool.*;
public class UsineConnection { public UsineConnection() {}
…
public Connection getConnectionFromConnectionPoolDataSource(
String nomDataSource) throws Exception {
InitialContext unContexte = new InitialContext();
ConnectionPoolDataSource unDataSource =
(ConnectionPoolDataSource)unContexte.lookup(nomDataSource);
PooledConnection unePooledConnection = unDataSource.getPooledConnection();
Connection uneConnection = unePooledConnection.getConnection();
return uneConnection;
}
}
15.2.6 Mécanismes de sécurité pour l'accès à un servlet
Sécurité programmatique
Sécurité déclarative par le conteneur
– rôles/utilisateurs
– géré par conteneur
27/02/22 © Robert Godin. Tous droits réser vés.
57
15.3 Architecture pour la persistance transparente
Persistance gérée par la classe métier
Transparent au client
Mécanisme paresseux de
matérialisation/dématérialisation
– gestion de cache transactionnelle
– programmation complexe
Norme Java Data Objects (JDO)
– http://access1.sun.com/jdo/
– inspirée de ODMG
– outils : http://www.javaskyline.com/database.html
15.4 Norme EJB de J2EE (http://
java.sun.com/products/ejb/)
Transparence « extrême »
– persistance
– répartition
– services
Spécification déclarative de services
– comportement transactionnel
– sécurité
– partage de ressources (CPU, mémoire, serveurs, ...)
partage transparent d’un bassin d’objets EJB (pooling) entre clients
Prise en charge des services par le conteneur à EJB
27/02/22 © Robert Godin. Tous droits réser vés.
59
Séparation propre des responsabilités (rôles)
Fournisseur de EJB (EnterpriseBean Provider)
– développe les composantes EJB
Assembleur d'application (Application Assembler) .
– assemble EJB + servlet, JSP, HTML, etc.
Déployeur (Deployer)
– déploie les EJB dans leur environnement d'exécution
Fournisseur de serveur EJB (EJB Server Provider).
– serveur EJB : services de bas niveau pour le conteneur EJB
Fournisseur de conteneur EJB (EJB Container Provider)
– conteneur EJB : environnement de déploiement et d'exécution des EJB
Administrateur de Système (System Administrator)
– administre serveur et le conteneur EJB
Catégories de EJB
EJB session (Session Bean)
– service d ’objet distant
– un seul client à la fois par objet
– partage d’un bassin d’objets entre clients
– état au besoin entre les appels
stateful/stateless session EJB
– non persistent (perdu suite à une panne)
EJB entité (Entity Bean)
– services d'objet distant persistent
– objet ~ proxy pour une ligne d'une table
– un objet EJB entité peut être partagé par plusieurs clients
EJB message (Message Bean)
– service de message
27/02/22 © Robert Godin. Tous droits réser vés.
61
Codage d ’un EJB
Interface home
– usine à objet EJB
Interface à distance (remote)
– accès aux méthodes d'un objet EJB
Classe bean (bean class)
– implémente les méthodes de
l'objet EJB
15.4.1 Développement d'un EJB session sans état : FacadeEnrPretSimpleSessionEJB
Interface home (usine à EJB)
Interface remote (interface à l’objet EJB)
package ExemplesJDBC.GererPrets;
import javax.ejb.EJBHome;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
public interface FacadeEnrPretSimpleSessionEJBHome extends EJBHome {
FacadeEnrPretSimpleSessionEJB create() throws RemoteException, CreateException;
}
package ExemplesJDBC.GererPrets;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
import java.sql.Date;
public interface FacadeEnrPretSimpleSessionEJB extends EJBObject {
Date insererPretEnCours(String idUtilisateur, String idExemplaire) throws RemoteException, Exception;
}
27/02/22 © Robert Godin. Tous droits réser vés.
63
package ExemplesJDBC.GererPrets.impl;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import java.sql.Date;
import ExemplesJDBC.GererPrets.*;
import java.sql.Connection;
import java.util.*;
public class FacadeEnrPretSimpleSessionEJBBean implements SessionBean {
public void ejbCreate(){}
public void ejbActivate(){}
public void ejbPassivate(){}
public void ejbRemove(){}
public void setSessionContext(SessionContext ctx){}
public Date insererPretEnCours(String idUtilisateur, String idExemplaire) throws Exception {
UsineConnection uneUsineConnection = new UsineConnection();
Connection uneConnection =
uneUsineConnection.getConnectionFromDataSource("jdbc/ora9icleratCoreDS");
Utilisateur unUtilisateur = new Utilisateur(idUtilisateur);
Exemplaire unExemplaire = new Exemplaire(idExemplaire);
// Générer la date du jour et l'objet PrêtEnCours
Calendar maintenant = Calendar.getInstance(); // Calendrier avec date actuelle java.sql.Date dateMaintenant = new java.sql.Date(maintenant.getTime().getTime());
PrêtEnCours leNouveauPrêtEnCours =
new PrêtEnCours(unUtilisateur,dateMaintenant,unExemplaire);
// Matérialiser le PrêtEnCours dans la BD CourtierBDPrêtEnCours unCourtierBDPrêtEnCours = new CourtierBDPrêtEnCours(uneConnection);
unCourtierBDPrêtEnCours.insérerPrêtEnCours(leNouveauPrêtEnCours);
// Pas besoin de commit uneConnection.close();
return dateMaintenant;
} }
Descripteur de
déploiement XML
<?xml version = '1.0' encoding = 'windows-1252'?>
<!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN"
"http://java.sun.com/j2ee/dtds/ejb-jar_1_1.dtd">
<ejb-jar>
<enterprise-beans>
<session>
<description>Session Bean ( Stateless )</description>
<display-name>FacadeEnrPretSimpleSessionEJB</display-name>
<ejb-name>FacadeEnrPretSimpleSessionEJB</ejb-name>
<home>ExemplesJDBC.GererPrets.FacadeEnrPretSimpleSessionEJBHome</home>
<remote>ExemplesJDBC.GererPrets.FacadeEnrPretSimpleSessionEJB</remote>
<ejb-class>ExemplesJDBC.GererPrets.impl.FacadeEnrPretSimpleSessionEJBBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Bean</transaction-type>
</session>
</ejb-jar>
27/02/22 © Robert Godin. Tous droits réser vés.
65
Client du EJB : façade locale qui délègue à la façade EJB distante
(patron Business Delegate)
package ExemplesJDBC.GererPrets;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.InitialContext;
import ExemplesJDBC.GererPrets.FacadeEnrPretSimpleSessionEJB;
import ExemplesJDBC.GererPrets.FacadeEnrPretSimpleSessionEJBHome;
// Façade pour le cas d'utilisation EnregistrerPretsSimple
// La façade utilise les services du EJB session FacadeEnrPretSimpleSessionEJB public class FacadeEJBEnregistrerPretsSimple
{
public FacadeEJBEnregistrerPretsSimple()throws Exception {
}
// Insère le prêt et retourne la date d'enregistrement public java.sql.Date insererPretEnCours(
String idUtilisateur, String idExemplaire) throws Exception{
// Chercher une référence au EJB session
FacadeEnrPretSimpleSessionEJB uneFacadeEnrPretSimpleSessionEJB;
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.evermind.server.rmi.RMIInitialContextFactory");
env.put(Context.SECURITY_PRINCIPAL, "admin");
env.put(Context.SECURITY_CREDENTIALS, "welcome");
env.put(Context.PROVIDER_URL, "ormi://localhost:23893/current-workspace-app");
Context ctx = new InitialContext(env);
FacadeEnrPretSimpleSessionEJBHome facadeEnrPretSimpleSessionEJBHome =
(FacadeEnrPretSimpleSessionEJBHome)ctx.lookup("FacadeEnrPretSimpleSessionEJB");
uneFacadeEnrPretSimpleSessionEJB = facadeEnrPretSimpleSessionEJBHome.create();
// Déléguer l'insertion du PrêtEnCours à la méthode du EJB
return uneFacadeEnrPretSimpleSessionEJB.insererPretEnCours(idUtilisateur,idExemplaire);
} }
JDevelopper 10g (déploiement
de défaut différent)
27/02/22 © Robert Godin. Tous droits réser vés.
67
Interposition transparente d ’objets
: Controle Enregi strerPretsSimpleAvecFacadeEJB
: FacadeEJBEnregistrerPretsSimple
ctx : Context
uneFacad eEnrPretSim ple SessionEJB : FacadeEnregistrerPretsSimpleSessionEJB
: FacadeEn regi strerPretsSimpleSessi onEJBBean facadeEnrPretSimpl
eSessionEJBHome
In terposition transparente d'objets générés par le conten eur pour e ffectuer l'envoie de message à l'objet be an Client du EJB
ObjetEJB local qui implémente l'interface remote
Conteneur EJB Poste du client du EJB
1. insererPretEnCours(idUtilisateur,idExemplaire)
7. in sererPretEnCours(idUtil is ateur,idExemplaire)
8. insererPretEnCours(idUtilisateur,idExemplaire) 2. «create»
3. lookup()
4. facadeEnrPretSimpleSessionEJBHome 5. create()
6. uneFacadeEnrPretSimpleSessionEJB Ob jet home
Objet bean
Conteneur
de bean
Dans ServletEnregistrerPretsSimpleFacade remplacer FacadeEnregistrerPretsSimple par une
FacadeEJBEnregitrerPretSimple
package ExemplesJDBC.GererPrets;
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.sql.*;
public class ServletEnregistrerPretsSimpleFacadeEJB extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
…
FacadeEJBEnregistrerPretsSimple uneFacadeEnregistrerPretsSimple = null;
try{
uneFacadeEnregistrerPretsSimple = new FacadeEJBEnregistrerPretsSimple();
…
}
}
27/02/22 © Robert Godin. Tous droits réser vés.
69
15.4.2 Développement d'un EJB session avec état
package ExemplesJDBC.GererPrets;
import javax.ejb.EJBHome;
import java.rmi.RemoteException;
import javax.ejb.CreateException;
public interface FacadeEnrPretsSessionEJBHome extends EJBHome {
FacadeEnrPretsSessionEJB create() throws RemoteException, CreateException;
}
package ExemplesJDBC.GererPrets;
import javax.ejb.EJBObject;
import java.rmi.RemoteException;
import java.sql.Date;
public interface FacadeEnrPretsSessionEJB extends EJBObject {
OTDUtilisateurPrets chercherOTDUtilisateurPrets(String idUtilisateur) throws Exception, RemoteException;
void confirmerTransaction() throws Exception, RemoteException;
String getStatutExemplaire(String idExemplaire) throws Exception, RemoteException;
Date insererPretEnCours() throws Exception, RemoteException;
}
Classe bean
package ExemplesJDBC.GererPrets.impl;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import java.sql.Connection;
import ExemplesJDBC.GererPrets.*;
import java.sql.Date;
import java.util.*;
public class FacadeEnrPretsSessionEJBBean implements SessionBean {
private Connection uneConnection;
private Utilisateur unUtilisateur;
private Exemplaire unExemplaire;
private CourtierBDPrêtEnCours unCourtierBDPretEnCours;
public void ejbCreate()throws Exception{}
public void ejbActivate(){}
public void ejbPassivate(){}
public void ejbRemove(){}
public void setSessionContext(SessionContext ctx) { try {
UsineConnection uneUsineConnection = new UsineConnection();
uneConnection =
uneUsineConnection.getConnectionFromDataSourceSansAutoCommit("jdbc/ora9icleratCoreDS");
}
catch(Exception lException){
lException.printStackTrace();
} }
…