+ All Categories
Home > Documents > EJB3-GLG203

EJB3-GLG203

Date post: 28-Dec-2015
Category:
Upload: pablo-sene
View: 10 times
Download: 0 times
Share this document with a friend
Popular Tags:
78
EJB3.1/Java EE 6 S. Rosmorduc, Conservatoire National des Arts et Métiers (avec des vrais bouts de transparents de Marc Le Bihan dedans) 1
Transcript
Page 1: EJB3-GLG203

EJB3.1/Java EE 6S. Rosmorduc, Conservatoire National des Arts et Métiers

(avec des vrais bouts de transparents de Marc Le Bihan dedans)

���1

Page 2: EJB3-GLG203

Bibliographie et sources

• Oracle Java EE 6 tutorial

• A. Goncalves, Beginning Java EE6

• Cours GLG203 2012-2013 Marc Le Bihan

���2

Page 3: EJB3-GLG203

Plan• Rappels d'architecture

• Définition des EJB

• Types d’EJB

• Interfaces d’EJB

• Cycle de vie

• Utilisation des EJB

• Déploiement

• Concurrence

• Transactions

• Mécanismes sous-jacents

���3

Page 4: EJB3-GLG203

Rappels d'architectureCouche Présentation

(Web, Swing…)

Couche Métier

Couche Accès aux données (DAO)

���4

Page 5: EJB3-GLG203

Rappels d'architecture

Couche Métier

façade1 = service façade2 = service

classe métier

classe métier

classe métier

���5

Page 6: EJB3-GLG203

Rappels d'architecture• Les « services » vont servir de façade pour l’accès

au couche métier

• Ils sont organisés selon les use-case

• Permettent d’isoler la couche métier de son interface : couplage plus faible, meilleure sécurité

• En JEE, ils sont implantés sous forme d’EJB

• Ils peuvent être répartis (remote beans) : leur interface permet de contrôler les opérations possibles.

���6

Page 7: EJB3-GLG203

Définition des EJBs

• Objets Gérés par le serveur applicatif

• créés et partagés par le serveur applicatif

• récupération par appels JNDI ou Injection de dépendance

• le cycle de vie dépend du type de bean

• Vous n’appellerez jamais new pour créer un EJB (sauf éventuellement pour les tests)!!!

• Objets façade pour les couches métier

���7

Page 8: EJB3-GLG203

Caractéristiques des EJBs

• objet décorés fournissant des services supplémentaires

• accès distant

• gestion de transaction

• événements liés au cycle de vie

• injection de dépendances

���8

Page 9: EJB3-GLG203

Contraintes

• ne créent pas de threads

• pas de champ statique

• méthodes exportées non final

• classe non final

• pas de méthode finalize() (anti-pattern, de toutes façons)

���9

Page 10: EJB3-GLG203

Types d'EJB

• Stateless

• fréquemment utilisé comme façade d’accès aux données

• Stateful

• Singleton

• Message-driven Bean (plus tard)

���10

Page 11: EJB3-GLG203

EJB Stateless• Pas d’état : on ne peut

pas garder d’information dans les variables d’instance du bean

• Annotation : @Stateless

• Très souvent utilisé pour l’accès aux données

• Injection d’EntityManager (JPA) par @PersistenceContext

���11

@Stateless public class ForumBean { @PersistenceContext EntityManager em; ! public Message addMessage(Message newMessage) { em.persist(newMessage); return newMessage; } ! public Message getMessage(Long id) { return em.find(Message.class, id); } ! public List<MessageList> getAllMessages() { return em.createQuery( "select m from Message m").getResultList(); } }

Page 12: EJB3-GLG203

L’EJB sans état (Stateless bean)

• Parce qu’il est sans état, le stateless bean ne devrait pas comporter de variables membres,

• sinon en considérant ceci:

• Elles ont des chances de ne plus avoir de contenu à l’appel suivant.

• et il y a un risque qu’elles aient encore le contenu qu’elles avaient à l’appel précédent.

���12

Page 13: EJB3-GLG203

L’EJB sans état peut être initialisé

• Il reste possible de procéder à son initialisation dans une méthode porteuse de l’annotation

@PostConstruct

• Et un équivalent « destructeur » pourra être défini dans une méthode annotée

@PreDestroy

���13

Page 14: EJB3-GLG203

Cycle de vie et annotations

• Le serveur maintient un pool de Stateless beans

• Un nouveau bean est initialisé par son constructeur,

• puis par l’injection de dépendances

• puis par l’appel de la méthode annotée par @PostConstruct (si elle existe)

• quand le bean va être libéré par le serveur, il appelle la méthode annotée par @PreDestroy

• important: si vous voulez initialiser votre bean en accédant à des valeurs de champs fixées par injection, il faut le faire dans la méthode @PostConstruct

���14

n’existe pas

prêt

2. injection de dépendance3. @PostConstruct

3. @PreDestroy

1. création, constructeur

Page 15: EJB3-GLG203

EJB Stateful

• Bean à état, sera généralement stocké en session une fois créé

• Annotation @Stateful

• Doit être Serializable (sinon, pas de passivation possible)

• Exemple typique: panier à provisions

���15

Page 16: EJB3-GLG203

Cycle de vie et annotations

• L’appel d’une méthode annotée par @Remove demande la suppression du bean

���16

n’existe pas

2. injection de dépendance

3. @PostConstruct

1. @Remove

passifprêt

1. création, constructeur

2. @PreDestroy

@PrePassivate

@PostActivate

Page 17: EJB3-GLG203

Exemple

���17

@Stateful public class BasketBean implements Serializable { private HashSet<Product> products= new HashSet<Product>(); public void addProduct(Product p) { // ..... } @Remove public void doOrder() { // Sauve la commande dans la base de données } }

l’appel de cette méthode déclenche la destruction du bean (@Remove)

Page 18: EJB3-GLG203

Singleton

• Bean qui n’existe qu’en un seul exemplaire sur un serveur (application répartie: éventuellement un singleton par serveur)

• Exemple: catalogue chargé en mémoire, conversation entre utilisateurs (non permanente)

• Attention: accès concurrents très probables.

���18

Page 19: EJB3-GLG203

Cycle de vie et annotations

• Le serveur propose toujours la même instance d’un bean singleton.

• L’annotation @Startup demande que le bean soit créé dès le lancement de l’application

• Des annotations permettent de gérer les accès concurrents

���19

n’existe pas

prêt

2. injection de dépendance3. @PostConstruct

3. @PreDestroy

1. création, constructeur

Page 20: EJB3-GLG203

Singleton et accès concurrent

• Les méthodes d’un bean singleton seront sûrement appelées simultanément par plusieurs threads

• Il importe donc de gérer la concurrence

• C’est possible simplement grâce aux annotations Lock

• On distingue l’accès en lecture (parallélisable) et en écriture (bloquant)

���20

Page 21: EJB3-GLG203

/** * Catalogue stocké en mémoire. * pas follement pratique: l'accès en BD est plus * simple. */ @Singleton @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER) public class InMemoryCatalog { ! @EJB ProductService productService; ! public Collection<Product> products; ! @PostConstruct @Lock(LockType.WRITE) public void initCatalog() { products = new HashSet<Product>(productService.getAllProducts()); } ! @Lock(LockType.WRITE) public void rafraichirCatalogue() { initCatalog(); } ! @Lock(LockType.READ) public Collection<Product> getProducts() { return products; } }

Singleton et accès concurrent

���21

optionnel (CONTAINER par défaut)

injection de l’accès aux données

non parallèle

parallèle

Page 22: EJB3-GLG203

Singleton et accès concurrent

• @ConcurrencyManagement(ConcurrencyManagementType.CONTAINER) : gestion automatique par le conteneur

• @ConcurrencyManagement(ConcurrencyManagementType.BEAN) : gestion manuelle

• @Lock(LockType.READ) : méthode de lecture. Parallélisable.

• @Lock(LockType.WRITE): méthode d’écriture, non parallélisable. Valeur par défaut.

• Quand une méthode d’écriture est en cours d’exécution, elle interdit l’appel de toute autre méthode (lecture ou écriture)

• On peut appeler simultanément autant de méthode de lecture qu’on veut.

���22

Page 23: EJB3-GLG203

Interfaces d'accès• Les beans ont été conçus pour pouvoir construire des systèmes

répartis => accès distant

• On peut avoir plusieurs types d’interface pour un bean

• Aucune (équivaut à « local » uniquement)

• Local : interface utilisable au sein de la même application que celle qui héberge le bean

• Remote : interface utilisable à distance

• différences avec RMI

• paramètres des méthodes remote

• LocalBean

���23

Page 24: EJB3-GLG203

Exemple: un bean d’accès aux produits

• Dispose de trois méthodes

• getProducts() : renvoie la liste des produits

• addProduct(Product p) : ajoute un nouveau produit

• removeProduct(Product p) : supprime un produit de la liste

• On veut que le client à distance puisse lister les produits, mais pas les supprimer ou ajouter

���24

Page 25: EJB3-GLG203

Exemple (2)

���25

@Local public interface ProductLocal extends ProductRemote { void addProduct(ProductDTO p); void removeProduct(ProductDTO p); }

!@Remote public interface ProductRemote { public Collection <ProductDTO> getAllProducts(); }

@Stateless public class ProductService implements ProductLocal, ProductRemote { ! @Override public void addProduct(ProductDTO p) { //.... } !

Page 26: EJB3-GLG203

@Local

• interface utilisée pour l’accès interne à l’application

���26

Page 27: EJB3-GLG203

@Remote

• Interface utilisée pour les accès distants

• Les arguments et les valeurs retournées par les méthodes de l’interface Remote doivent être Serializable.

���27

Page 28: EJB3-GLG203

Et si on ne dit rien ?

• Un EJB sans annotation locale ou remote est considéré comme local.

• Note importante: quand on a une interface locale ou remote, seules les méthodes de cette interface sont des méthodes EJB (transactionnelles, entre autres). Les autres méthodes sont « normales »

• Quand on n’a pas d’interface déclarée, l’interface locale correspond à l’ensemble des méthodes publiques.

���28

Page 29: EJB3-GLG203

Utilisation des beans• Nombreuses manières de faire référence à des beans

• En JSF

• injection de dépendance

• Entre beans

• règles

• Depuis une application cliente

• JNDI

• Depuis une Servlet

���29

Page 30: EJB3-GLG203

Accès depuis un Managed Bean JSF

• Dans l’architecture JSF, les clients des EJB sont essentiellement les managed beans

• Très simple: on place l’ejb comme variable d’instance et on utilise l’injection de dépendance.

• Annotation : @EJB (ou @Inject)

���30

Page 31: EJB3-GLG203

Accès depuis un Managed Bean JSF

���31

!@ManagedBean @RequestScoped public class CreatePersonBean { @EJB PersonService personService; private String name; private int age; private Person person; // Or DTO : Data transfer Object public void createPerson() { person= personService.createPerson(name, age); name= ""; age= 0; } public String getName() { return name; }

EJB

Page 32: EJB3-GLG203

Accès depuis un Managed Bean JSF: version « moderne »

���32

!@Named @RequestScoped public class CreatePersonBean { @Inject PersonService personService; private String name; private int age; private Person person; // Or DTO : Data transfer Object public void createPerson() { person= personService.createPerson(name, age); name= ""; age= 0; } public String getName() { return name; }

EJB

Page 33: EJB3-GLG203

Injection et interfaces Remote et Local

• Pour l’injection, le type à utiliser est le nom de l’interface, pas celui de la classe:

@EJB

private ProductLocal productService;

���33

Page 34: EJB3-GLG203

Entre EJB

• On peut utiliser l’injection de dépendance entre EJB

• On utilise aussi @EJB ou @Inject

���34

Page 35: EJB3-GLG203

Accès par une application

• Une application texte ou graphique peut se connecter à un bean

• Le bean doit avoir une « interface distante » (similaire à ce qui se fait pour les RMI) : @Remote

• L’application doit avoir un nombre assez conséquent de bibliothèques du serveur applicatif dans son classPath.

• Il existe une application « lanceur » nommée appclient.

• On peut utiliser l’injection, ou se connecter à JNDI

• ATTENTION : l'application distante doit avoir connaître (avoir dans son classpath) l'interface Remote du bean (pas le bean lui-même)

���35

Page 36: EJB3-GLG203

JNDI Java Naming and Directory Interface

• Fournit un accès unifié à plusieurs services d’annuaires (DNS, LDAP...)

• Annuaire: associe des données (objets) avec un nom

• http://docs.oracle.com/javase/jndi/tutorial/

• L’accès JNDI est fourni par le serveur applicatif

• Derrière l’injection de dépendance, on a quand même JNDI…

���36

Page 37: EJB3-GLG203

Récupérer un Bean avec JNDI

import javax.naming.*; .... .... Context c= new InitialContext(); String beanName= "java:app/MyApp/BasketBean"; BasketBean b= (BasketBean) c.lookup(beanName);

• Si le bean est Stateful, crée un nouveau bean • Si le bean est stateless, peut réutiliser un bean existant • Si le bean est un singleton, renvoie le singleton.

���37

Page 38: EJB3-GLG203

Coordonnées du serveur JNDI

• En local, données fournies par appclient

• Sinon (pour GlassFish) :

���38

Properties properties= new Properties(); properties.setProperty("java.naming.factory.initial", "com.sun.enterprise.naming.SerialInitContextFactory"); properties.setProperty("java.naming.factory.url.pkgs", "com.sun.enterprise.naming"); properties.setProperty("java.naming.factory.state", "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl"); properties.setProperty("org.omg.CORBA.ORBInitialHost", "localhost"); properties.setProperty("org.omg.CORBA.ORBInitialPort", "3700"); initialContext = new InitialContext(properties);

Page 39: EJB3-GLG203

Noms JNDI des beans (1)• Récemment standardisé…

• Voir trace de glassfish pour les noms des beans

• Pour un bean dans une autre application web, utiliser le nom « global »

• java:global/APP/MODULE/BEAN

• Pour une application construite à partir de plusieurs war, jars: pour accéder à des beans dans d’autres modules d’une même application utiliser le « nom d’application » :

• java:app/MODULE/BEAN

• Pour des beans dans le même module, utiliser le nom de module:

• java:module/BEAN

• APP= nom de l’appli; MODULE = nom du module; Bean= nom du bean (nom de la classe)

���39

Page 40: EJB3-GLG203

Noms JNDI des beans (2)

• Si on veut utiliser une interface particulière, on peut ajouter ‘ !INTERFACE’ après le nom de la classe.

• ex. :

java:app/MyApp/BasketBean!myshop.business.BasketRemoteIF

• Utilise l’interface remote

• nom complet, y compris package.

• Voir http://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#What_is_the_syntax_for_portable_global_ pour plus de détails.

���40

Page 41: EJB3-GLG203

Accès aux EJB depuis une Servlet

• Stateless beans et singletons peuvent être injectés dans la Servlet en utilisant l’annotation @EJB

• Dans les servlets, il faut récupérer les Stateful beans « manuellement » en utilisant JNDI, puis les stocker en session en utilisant session.setAttribute()

���41

Page 42: EJB3-GLG203

accès à un bean session depuis une servlet

• Le bean:@Stateful public class Basket { // Product is serializable ! private List<Product> content=

new ArrayList<Product> (); !

public void add(Product p) { content.add(p); }

....

���42

Page 43: EJB3-GLG203

accès à un bean session depuis une servlet

@WebServlet(name = "AddToBasketServlet", urlPatterns = {"/addToBasket"}) public class AddToBasketServlet extends HttpServlet { ... private Basket lookupBasketBean(HttpServletRequest request) { HttpSession session = request.getSession(); if (session.getAttribute("basket") == null) { try { Context c = new InitialContext(); Basket b = (Basket) c.lookup("java:global/SessionInViewTest/Basket"); session.setAttribute("basket", b); } catch (NamingException ne) { Logger.getLogger(getClass().getName()).log(Level.SEVERE, "exception", ne); throw new RuntimeException(ne); } } return (Basket) session.getAttribute("basket"); } }

Si le bean n’est pas en session, le créer avec

JNDI.

���43

Page 44: EJB3-GLG203

Déploiement

���44

Page 45: EJB3-GLG203

Concurrence

• création manuelle de Threads : INTERDITE

• Timer

• @Startup

• @Schedule

• @Timeout

• Annotation @Asynchronous

���45

Page 46: EJB3-GLG203

L'EJB Timer (1)

• Pour invoquer périodiquement un EJB, il n'existait avant la version EJB 3.1 que des solutions fastidieuses, telles que :

• Création d'une servlet qui démarre avec le serveur d'application,

• puis crée des java.util.Timer,

• et lorsque ces timers arrivent à échéance invoquent la méthode d'EJB voulue…

• Le serveur d'application peut à présent prendre en charge seul ces méthodes à l'exécution programmée dans le temps.

• Le timer est souvent attaché à un Singleton, chargé dès le déploiement (annoté par @Startup)

���46

Page 47: EJB3-GLG203

EJB Timer (2)• Pour programmer une exécution:

• annotation @Schedule placée sur une méthode

• prend une expression « cron » en paramètre pour définir son déclenchement.

• par défaut, hour, minute, second sont à 0.

• dayOfMonth="4", hour="*" : Toutes les heures le 4ème jour de chaque mois.

• minute=*/5 : toutes les cinq minutes.

• dayOfWeek="1, 3,5": lundi, mercredi et vendredi.

• la méthode cible ne doit pas avoir d'arguments.

@Schedule(dayOfMonth="*")!

public void sauvegarde() {…}

���47

Page 48: EJB3-GLG203

EJB Timer

���48

@Singleton @Startup public class MaDemoTimer implements Serializable{ private int compteur= 0; private Logger logger = Logger.getLogger(this.getClass().toString()); @PostConstruct public void myInit() { logger.severe("Init"); } @Schedule(hour = "*", minute = "*", second = "*/5", persistent = true) public void sauverDonnees() { logger.severe("On sauve les données "+ new Date()+ " compteur "+ (compteur++)); } }

souvent singleton. Startup=> créé dès le déploiement du bean

Page 49: EJB3-GLG203

EJB Timer (3)

• @Schedule prend des paramètres constants.

• Lorsque la planification à appliquer n'est connue qu'à l'exécution, il faut utiliser un TimerService.

• C'est une ressource que l'on charge avec des expressions temporelles : cron, ou bien en dates classiques.

���49

Page 50: EJB3-GLG203

Timer programmé

• On crée un timer en utilisant la classe TimerService (qu’on injecte)

• Dans la classe où on crée le timer, on cherche une méthode annotée par @Timeout

• Cette méthode est lancée selon la fréquence indiquée

���50

Page 51: EJB3-GLG203

Timer programmé

���51

@Singleton public class ExempleTimerService { @Resource TimerService timerService; private Logger logger= Logger.getLogger("TimerProgramme"); private Timer timer; // pour annuler le timer si besoin // Installe le timer pour un certain intervalle de temps. public void installerTimer(long intervalle) { cancelTimer(); timer= timerService.createIntervalTimer(1000, intervalle, new TimerConfig()); } public void cancelTimer() { if (timer != null) {timer.cancel();timer= null;} } @Timeout public void sauvegardeProgrammee() { logger.severe("Sauvegarde bis "+ (compteur++) + " a "+ new Date()); } }

Page 52: EJB3-GLG203

Note à propos de Glassfish

• Par défaut, le timer est « persistante » : il se relancera, même en cas d’arrêt du serveur. Il est capable de migrer sur un autre serveur en cas de Load-balancing

• En cas d’erreur de configuration, les timers persistants laissent des fichiers de sauvegarde incorrects dans Glassfish

• Donc, en cas de problème :

• soit désactiver la persistance :

@Schedule(hour = "*", persistent = false)

• soit effacer le fichier incriminé :

glassfish/domains/domain1/generated/ejb/ejb-timer-service-app

���52

Page 53: EJB3-GLG203

Timer programmé

• Quand on crée l'objet timer en appelant

• timerService.createIntervalTimer(10, intervalle, new TimerConfig());

• le timer démarre, et la méthode annotée @TimeOut est lancée (périodiquement ou une fois, selon le timer créé)

• Il est possible de sauver l’objet timer dans un fichier ou une BD en le sérialisant (on sauve la valeur renvoyée par timer.getHandle()).

• par défaut, le timer est persistant quand il est lancé: si on arrête le serveur JEE, le timer se relancera automatiquement.

���53

Page 54: EJB3-GLG203

���54

@Named @RequestScoped public class StartTimerBean { @Min(100) private long intervalle=2000; @EJB private ExempleTimerService timerService; public void demarrerTimer() { timerService.installerTimer(intervalle); } public void arreterTimer() { timerService.cancelTimer(); } public long getIntervalle() { return intervalle; } public void setIntervalle(long intervalle) { this.intervalle = intervalle; } }

<h:form> <p>Intervalle : <h:inputText value="#{startTimerBean.intervalle}"/></p> <h:commandButton value="Démarrer" action="#{startTimerBean.demarrerTimer()}"/> <h:commandButton value="Arrêter" action="#{startTimerBean.arreterTimer()}"/> </h:form>

Exemple de Managed Bean pour le timer précédent

JSF

Page 55: EJB3-GLG203

Gestion de transactions

• rappels

• TransactionManagement

• Annotations disponibles pour @TransactionAttribute

• REQUIRED, REQUIRES_NEW, MANDATORY, SUPPORT, NOT_SUPPORTED, NEVER

���55

Page 56: EJB3-GLG203

Le problème des transactions

• transfert entre deux comptes en banque:

• compte1.retirer(1000)

• compte2.deposer(1000)

• En BD:

• update compte set solde= solde -1000 where id= 1

• update compte set solde= solde + 1000 where id= 2

• Que se passe-t-il si l’opération est interrompue entre les deux étapes ????

• => les deux opérations doivent, ou toutes les deux réussir, ou toutes les deux échouer

���56

Page 57: EJB3-GLG203

Transactions• Définition

• opération informatique cohérente composée de plusieurs tâches unitaires

• implantent les propriétés ACID:

• atomique

• cohérente

• isolée (plus ou moins)

• durable

• mécanisme

• de base dans SQL : commit() rollback() start transaction()

���57

Page 58: EJB3-GLG203

Transaction : le problème

• opération technique au niveau SQL (accès aux données)

• au niveau logique, la délimitation des transaction correspond plutôt à la logique applicative (suite d’opération cohérente) !!

• les EJB permettent de replacer les transactions au « bon » niveau

���58

Page 59: EJB3-GLG203

Transactions et EJB Java Transaction API

• Par défaut, toutes les méthodes qui font partie de l’interface d’une EJB sont transactionnelles

• Quand l’interface utilisateur appelle une méthode EJB, on démarre une transaction; la fin de la méthode correspond au commit().

• S’interface naturellement avec JPA

• Pas besoin d’ouvrir ou fermer une transaction, c’est fait automatiquement par le conteneur

���59

Page 60: EJB3-GLG203

Annotation @TransactionAttribute• @TransactionAttribute(….) devant une

méthode d’un EJB: modifie son comportement transactionnel

• généralement, la question est la suivante:

• une méthode f() transactionnelle appelle une méthode g(), elle aussi transactionnelle

• que va-t-il se passer ? g() va-t-elle s’exécuter dans la transaction démarrée par f() ?

• quel suspense !

���60

Page 61: EJB3-GLG203

Valeurs possibles pour @TransactionAttribute• TransactionAttributeType.REQUIRED: s’il y a une transaction en cours,

exécute la méthode dans cette transaction. Sinon, crée une nouvelle transaction

• TransactionAttributeType.REQUIRES_NEW: crée une nouvelle transaction pour cet appel

• TransactionAttributeType.MANDATORY: exception s’il n’y a pas déjà une transaction en cours

• TransactionAttributeType.SUPPORTS: ne crée pas de transaction, mais s’exécute dans le cadre de celle qui est en cours si elle existe.

• TransactionAttributeType.NEVER: erreur si dans transaction

• TransactionAttributeType.NOT_SUPPORTED: s’exécute en dehors du contexte transactionnel en cours.

���61

Page 62: EJB3-GLG203

Exemple

���62

@Stateful public class PanierService { ! @PersistenceContext EntityManager em; ! private List<ProduitDTO> produits = new ArrayList<ProduitDTO>(); ! @TransactionAttribute(TransactionAttributeType.SUPPORTS) public void addProduit(ProduitDTO dto) { produits.add(dto); } ! // l'annotation ci-dessous est inutile (valeur par défaut) @TransactionAttribute(TransactionAttributeType.REQUIRED) public void sauverCommande() { // ... construit la commande à partir des produit // ... appelle em.persist() Commande c = CommandeHelper.construireCommande(produits); em.persist(c); } }

Page 63: EJB3-GLG203

Exemple (suite)• addProduit : TransactionAttributeType.SUPPORTS

• ne touche pas à la base de données, et peut donc ne pas être transactionnel

• si on l’appelle dans le cadre d’une transaction, utilise celle-ci

• sauverCommande: TransactionAttributeType.REQUIRED

• va forcément s’exécuter dans le cadre d’une transaction.

���63

Page 64: EJB3-GLG203

Transactions• Concrètement, les transactions agissent sur des connections fournies

par les Datasources que le serveur d’application a sous sa garde.

• Agir sur les connections pour débuter une transaction n’est pas nécessaire, le serveur d’application s’en charge.

• Le commit advient de lui-même lorsque le service qui a débuté une transaction s’ est exécuté intégralement et a su composer avec d’autres services

• Sans avoir reçu de notification d’abandon.

• Sans s’être retrouvé dans une situation d’annulation.

• De sorte que dans un service, on ne s’occupe que de notifier les situations de rollback.

���64

Page 65: EJB3-GLG203

Exceptions Systèmes:

• sur initiative du serveur d’application et dans des situations « sévères ».

• Les exceptions issues de RuntimeException, RemoteException, et EJBException.

• Ce sont des exceptions système qu’il n’est pas attendu que nous levions nous-mêmes

���65

Page 66: EJB3-GLG203

Exceptions applicatives• Les exceptions non système

• peuvent être annotées par

@ApplicationException(rollback=true)

• et alors elles provoqueront l’annulation de la transaction en cours si elles sont levées par le service.

• Attention: prendre cette décision pour la classe d’exception elle-même est brutal. C’est peut-être une décision à laisser au service ?

���66

Page 67: EJB3-GLG203

Notification d’abandon• En ajoutant à l’EJB session la variable membre et la

méthode

@Stateless public class MonBean {

@Resource

private SessionContext sessionContext;

….

• Une méthode de service de ce bean pourra annuler une transaction en cours par un:

• sessionContext.setRollbackOnly(true);

���67

Page 68: EJB3-GLG203

Mécanismes sous-jacents

• Quand on appelle une méthode d’EJB, comment le système peut-il décider de commencer/terminer une transaction ?

• On utilise le pattern Décorateur avec un Proxy

• On génère une classe de même interface que le Bean, qui appelle le bean, mais « enrobe » les appels de méthodes dans le code nécessaire au traitement de la transaction

• Pour ça

• classe Proxy : permet d’implanter par programme java une interface quelconque (c’est du java standard). Fonctionne seulement s’il y a une interface Local ou Remote explicite.

• Héritage et synthèse de code : on crée le bytecode d’une nouvelle classe (bibliothèque ASM), qui étend la classe d’origine (d’où l’interdiction de final).

���68

Page 69: EJB3-GLG203

Pour résumer... un exemple de C(RUD) en JSF+EJB (+JPA)

• Base de données de Dvd

• Contrôle : un managed bean CreateDvdBean

• Couche métier : un Stateless Bean DvdService

• Accès aux données : JPA (et le bean DvdService)

���69

Page 70: EJB3-GLG203

���70

on ajoute JSF…

Page 71: EJB3-GLG203

Dvds… la suite

• Noter le découpage en packages

���71

On crée la base de données

Page 72: EJB3-GLG203

Ajout d’une Persistence Unit (pour JPA)

���72

Page 73: EJB3-GLG203

Création du modèle (réduit à une classe ici)

���73

Page 74: EJB3-GLG203

L’EJB d’accès aux Dvd• (on pourrait faire deux EJB: un de bas

niveau (DAO), l'autre orienté façade pour l'interface graphique

���74

Page 75: EJB3-GLG203

Le managed bean pour la création et sa JSF

���75

Page 76: EJB3-GLG203

Note sur la valeur de retour de l'action

• return

"montrerDvd?faces-redirect=true&id=" +id;

• faces-redirect => redirection (on charge une nouvelle page)

• id=… : cette page va afficher le DVD créé

���76

Page 77: EJB3-GLG203

Managed Bean de visualisation

���77

Page 78: EJB3-GLG203

Injection de paramètres GET

@ManagedProperty(value="#{param.id}")

Long id;

• injecte la valeur de param.id dans id

• ne fonctionne que sur un @ManagedBean (pas @Named)

• FacesContext.getCurrentInstance().getExternalContext() permet d’avoir accès aux paramètres comme avec une servlet

• Sinon, on peut injecter les valeurs à partir de la JSF :

���78

<f:metadata> <f:viewParam name="id" value="#{dvd.id}"/> </f:metadata>


Recommended