• Aucun résultat trouvé

Transparents (PowerPoint)

N/A
N/A
Protected

Academic year: 2022

Partager "Transparents (PowerPoint)"

Copied!
106
0
0

Texte intégral

(1)

15 Développement d'application de

base de données en Java

(2)

27/02/22 © Robert Godin. Tous droits réservés. 2

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.

(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 ?

(4)

27/02/22 © Robert Godin. Tous droits réservés. 4

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.

(5)

Cas de test pour scénario normal

(6)

27/02/22 © Robert Godin. Tous droits réservés. 6

Cas d ’exception : nombre maximal

d'emprunts (ici 2) atteint

(7)

Cas d ’exception : exemplaire

non disponible

(8)

27/02/22 © Robert Godin. Tous droits réservés. 8

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)

(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 otPass e : String catégorie : String lesPrêts : Vector

CourtierBDUtilisateur

ch erch erVari ables StatiquesDeMem bre() ch erch erUtili sateu rParIdUti lisateur()

CourtierBDPrêtsEnCou rs chercherLesPrêtsEnCours() insérerPrêtEnCours ()

Courtie rBDExem plaire che rche rExem plaireParId 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 : Stri ng

Em ployé {UNIQUE : codeMatricule}

codeMatricule : String

catégorieEm ployé : enum (bibliothécaire, com m is)

~ Data Access Object

(DAO) + Domain Data

Transfer Object

(10)

27/02/22 © Robert Godin. Tous droits réservés. 10

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)

(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++;

} }

Lecteur pour donnée dérivée

Lecteurs/modifieurs

pour naviguer les

associations

(12)

27/02/22 © Robert Godin. Tous droits réservés. 12

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(){

return (this.getNbRetards() == 0 && this.getNbPrêtsEnCours() < nbMaxPrêts);

} }

Attributs et méthodes

static pour attributs de

classe (ou singleton)

(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é;}

}

(14)

27/02/22 © Robert Godin. Tous droits réservés. 14

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();}

}

(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);

}

}

(16)

27/02/22 © Robert Godin. Tous droits réservés. 16

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;}

}

(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"),

(18)

27/02/22 © Robert Godin. Tous droits réservés. 18

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»

(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;

(20)

27/02/22 © Robert Godin. Tous droits réservés. 20

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();

}

… }

(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é");}

}

}

(22)

27/02/22 © Robert Godin. Tous droits réservés. 22

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

(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);

(24)

27/02/22 © Robert Godin. Tous droits réservés. 24

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()

(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 ) 7. chercherUtilisateur(idUtilisateur)

12. chercherVariablesStatiquesDeMembre( ) 6. «cre ate»(uneConnection)

15. «create»(uneConnection)

3. «create»

8. prepareStatement()

11. prepareStatement()

13. prepareStatement() 1. créerNouveauPrêt()

5 . entrer(idUtilisateur)

14. entrer(idExemplaire)

15.1.1 Enjeux de conception d'une application Java/JDBC

Dépendance

au temps de

réflexion

(26)

27/02/22 © Robert Godin. Tous droits réservés. 26

Limiter les verrouillages ?

(27)

Limiter la durée des transactions

 Contraintes de sérialisabilité ?

(28)

27/02/22 © Robert Godin. Tous droits réservés. 28

Vérification des contraintes par le serveur

Non

sérialisabilité

perçue par T2

(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

 Populaire dans les applications Web

(30)

27/02/22 © Robert Godin. Tous droits réservés. 30

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.

(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()

(32)

27/02/22 © Robert Godin. Tous droits réservés. 32 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)

(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

(34)

27/02/22 © Robert Godin. Tous droits réservés. 34

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

(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 {

(36)

27/02/22 © Robert Godin. Tous droits réservés. 36

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

(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

(38)

27/02/22 © Robert Godin. Tous droits réservés. 38

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

(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

(40)

27/02/22 © Robert Godin. Tous droits réservés. 40

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

(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

(42)

27/02/22 © Robert Godin. Tous droits réservés. 42

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

(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

(44)

27/02/22 © Robert Godin. Tous droits réservés. 44

<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>

(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 =

(46)

27/02/22 © Robert Godin. Tous droits réservés. 46

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

(47)

15.2.4 Gestion d'une session HTTP dans une servlet

La FORM

n ’envoie que

le idUtilisateur

(48)

27/02/22 © Robert Godin. Tous droits réservés. 48

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>

(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')

7. setAttribute('idUtilis ateur',idUtilis ateur)

13. getAttribute('idUtilisateur')

(50)

27/02/22 © Robert Godin. Tous droits réservés. 50

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>");

} ...

(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();

}

(52)

27/02/22 © Robert Godin. Tous droits réservés. 52

15.2.5 DataSource,

ConnectionPoolDataSource et PooledConnection

 Passage par serveur JNDI (Java Naming and Directory Interface)

– e.g. service d’annuaire LDAP

– repérage de ressources (e.g. serveur BD)

– accès sécurisé

(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;

}

}

(54)

27/02/22 © Robert Godin. Tous droits réservés. 54

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>

(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;

}

}

(56)

27/02/22 © Robert Godin. Tous droits réservés. 56

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

(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

 Nouvelle norme Java Persistence API (JPA)

(58)

27/02/22 © Robert Godin. Tous droits réservés. 58

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é

– gestion de ressources (CPU, mémoire, serveurs, ...)

 e.g. partage transparent d’un bassin d’objets EJB (pooling) entre clients

 robustesse, « scalabilité »

 Prise en charge des services par le conteneur à EJB

(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)

(60)

27/02/22 © Robert Godin. Tous droits réservés. 60

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 persistant

– 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

(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

(62)

27/02/22 © Robert Godin. Tous droits réservés. 62

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;

}

NB Paramètres sérialisables (au sens de Java) passés par valeur

(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);

(64)

27/02/22 © Robert Godin. Tous droits réservés. 64

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>

(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 =

(66)

27/02/22 © Robert Godin. Tous droits réservés. 66

JDevelopper 10g (déploiement

de défaut différent)

(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

(68)

27/02/22 © Robert Godin. Tous droits réservés. 68

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();

}

}

(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;

(70)

27/02/22 © Robert Godin. Tous droits réservés. 70

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();

} }

État maintenu entre les appels Méthode du cycle de vie appelée à la création de l’objet avant ejbCreate()

NB setSessionContext() permet

d’initialiser la connexion au

DataSource (interdit dans

ejbCreate()…)

(71)

Classe Bean (suite) : méthode métier identique à FacadeEnregistrerPrets

public OTDUtilisateurPrets chercherOTDUtilisateurPrets(String idUtilisateur) throws Exception { // Création du courtier et dématérialisation de l'Utilisateur

CourtierBDUtilisateur unCourtierBDUtilisateur = new CourtierBDUtilisateur(uneConnection);

unUtilisateur =

unCourtierBDUtilisateur.chercherUtilisateurParIdUtilisateur(idUtilisateur);

//Création du courtier et dématérialisation des PrêtsEnCours

unCourtierBDPretEnCours = new CourtierBDPrêtEnCours(uneConnection);

unCourtierBDPretEnCours.chercherLesPrêtsEnCours(unUtilisateur);

// Retourner l'objet de transfert de données OTDUtilisateurPrets if (unUtilisateur instanceof Membre){

unCourtierBDUtilisateur.chercherVariablesStatiquesDeMembre();

Membre unMembre = (Membre)unUtilisateur;

return new OTDUtilisateurPrets(

unMembre.getCatégorie(),

unMembre.conditionsPrêtAcceptées(), unMembre.getNbPrêtsEnCours(),

Membre.getNbMaxPrêts(), unMembre.getNbRetards());

} else {

return new OTDUtilisateurPrets(

unUtilisateur.getCatégorie(),true,unUtilisateur.getNbPrêtsEnCours(),0,0);

(72)

27/02/22 © Robert Godin. Tous droits réservés. 72

Processus de création d ’un EJB avec état

unClientEJB unEJBHome unObjetEJBl oca l u nSessio nContext unObjetEJBBean 1. create()

2. «create»

3. «create»

4. «create»

5. setSessionContext()

6. ejbCreate()

(73)

Client du EJB : façade locale qui délègue à la façade EJB distante

public class FacadeEJBEnregistrerPrets {

private FacadeEnrPretsSessionEJB uneFacadeEnrPretsSessionEJB;

public FacadeEJBEnregistrerPrets()throws Exception {

// Le constructeur crée l'objet session EJB façade 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);

FacadeEnrPretsSessionEJBHome facadeEnrPretsSessionEJBHome =

(FacadeEnrPretsSessionEJBHome)ctx.lookup("FacadeEnrPretsSessionEJB");

uneFacadeEnrPretsSessionEJB = facadeEnrPretsSessionEJBHome.create( ); } // Cherche un Utilisateur avec ses PretsEnCours et retourne

// les données nécessaires pour EnregistrerPrets (OTDUtilisateurPrets) // Une exception est levée si l'Utilisateur n'existe pas

public OTDUtilisateurPrets chercherOTDUtilisateurPrets(String idUtilisateur)throws Exception { return uneFacadeEnrPretsSessionEJB.

chercherOTDUtilisateurPrets(idUtilisateur);

(74)

27/02/22 © Robert Godin. Tous droits réservés. 74

Dans ServletIdentificationUtilisateurFacade et ServletTerminerPretFacade

remplacer FacadeEnregistrerPrets par une FacadeEJBEnregistrerPrets

package ExemplesJDBC.GererPrets;

import javax.servlet.*;

import javax.servlet.http.*;

import java.io.*;

import java.util.*;

import java.sql.*;

public class ServletIdentUtilFacadeEJB extends HttpServlet {

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

try{

// Créer la facade et chercher l'OTDUtilisateurPrets

FacadeEJBEnregistrerPrets uneFacadeEnregistrerPrets = new FacadeEJBEnregistrerPrets();

OTDUtilisateurPrets unOTDUtilisateurPrets =

uneFacadeEnregistrerPrets.chercherOTDUtilisateurPrets(idUtilisateur);

(75)

15.4.3 Support de

transactions distribuées

 Plusieurs ressources indépendantes

– serveur BD, serveur JMS, ...

 Protocole transparent de transaction répartie

 Démarcation programmatique ou

déclarative

(76)

27/02/22 © Robert Godin. Tous droits réservés. 76

15.4.4 Démarcation programmatique de transaction distribuée (bean managed transaction demarcation)

CREATE TABLE Compte

(noCompte INTEGER PRIMARY KEY,

solde DECIMAL(10,2) CHECK (solde >= 0), dateOuverture DATE,

noClient)

package mypackage1;

import javax.ejb.*;

import java.rmi.RemoteException;

import java.sql.Connection;

public interface BanqueSessionBMTDEJB extends EJBObject {

void transferer(int noCompteADebiter, int noCompteACrediter, double montant) throws RemoteException, EJBException;

}

Deux connexions

indépendantes !

(77)

Classe bean

// Exemple de EJB session qui réalise une transaction répartie

// Démarcation programmatique de transaction avec javax.transation.UserTransaction public class BanqueSessionBMTDEJBBean implements SessionBean {

private SessionContext sessionContext;

private Connection connectionBanqueDebit;

private Connection connectionBanqueCredit;

… public void setSessionContext(SessionContext ctx){

sessionContext = ctx;

ouvrirConnections();

}

void ouvrirConnections() throws EJBException { try{

UsineConnection uneUsineConnection = new UsineConnection();

connectionBanqueDebit =

uneUsineConnection.getConnectionFromDataSource("jdbc/ora9igodinCoreDS");

connectionBanqueCredit =

uneUsineConnection.getConnectionFromDataSource("jdbc/ora9igodin2CoreDS");

}

catch(Exception lException){

throw new EJBException(lException);

Deux connexions

Références

Documents relatifs

20.8 Traitement d’un document XML avec Java API for XML Processing

– Recommander les items jugés pertinents par les utilisateurs semblables. 

public static void main (String args []) throws Exception { // Création d'une Connection globale pour l'application UsineConnection uneUsineConnection =

public static void main(String[] args) throws IOException { InputStream in=new FileInputStream(args[0]);.. Et avec

public static void main(String[] args) throws Exception { NotePad notes = new NotePad();. Invoker invoke = new

public static void main(String [] args) throws IOException{. ServerSocket serveur =

public static void main(String [] args) throws IOException{. ServerSocket serveur =

public static void main(String[] args) throws Exception { NotePad notes = new NotePad();. Invoker invoke = new