modifi par Richard Grin (version 1.0, 22/11/11) Gestion de transactions Service cl pour le dveloppement ct serveur, Permet des applications de fonctionner de manire robuste, Les transactions sont trs utiles lorsqu'on effectue des oprations de persistance, comme des mises--jours dans une base de donnes Dans ce chapitre nous prsentons le concept de transaction et sa mise en application au sein des EJB.
Motivation pour les transactions Oprations atomiques, bien que composes de plusieurs petites oprations Ex : transfert de compte compte bancaire : on enlve sur un compte, on dpose sur l'autre Si une des deux oprations choue, perte de cohrence ! On veut que soit les deux oprations russissent, mais si une d'elles choue, on annule le tout et on remet les comptes dans l'tat initial ! On dit que les deux oprations forment une seule et mme transaction !
Traitement par exceptions On peut s'en sortir en grant des exceptions try { // retirer de l'argent du compte 1 } catch (Exception e){ // Si une erreur est apparue, on arrte. return; } try { // Sinon, on dpose l'argent sur le compte 2 } catch (Exception e){ // Si une erreur est apparue, o s'arrte, mais avant, on redpose //l'argent sur le compte 1 return; } Qu'en pensez-vous ? Traitement par exceptions Et si on choue la dernire opration et qu'on narrive pas remettre l'argent sur le compte 1 ? Et si au lieu d'un traitement simple on a un gros traitement faire qui se compose de 20 oprations diffrentes ? Comment on teste tous les cas d'erreur ? Panne rseau ou panne machine Le rseau plante, le client reoit une RMI Remote Exception L'erreur est intervenue avant qu'on enlve l'argent, ou aprs ? Impossible de savoir Peut-tre que le SGBD s'est crash ? La machine ? La BD est peut-tre devenue inconsistante ? Le traitement par Exception est vraiment inacceptable ici, il n'est pas suffisant !
Partage concurrent de donnes
Partage concurrent de donnes Plusieurs clients consultent et modifient les mmes donnes On ne peut tolrer de perte d'intgrit des donnes ! Problmes rsolus par les transactions ! Un transaction est une srie d'oprations qui apparaissent sous la forme d'une large opration atomique. Soit la transaction russit, soit elle choue. Traduire par "toutes les oprations qui la composent" Les transactions s'accordent avec les pannes machines ou rseau, Rpondent au problmes du partage de donnes. Un peu de vocabulaire Objet ou composant transactionel Un composant bancaire impliqu dans une transaction. Un EJB compte bancaire, un composant .NET, CORBA Gestionnaire de transaction Celui qui en coulisse gre l'tat de la transaction Ressource L'endroit o on lit et crit les donnes : un DB, une queue de messages, autre Gestionnaire de ressource Driver d'accs une BD, une queue de message Implmentent l'interface X/Open XA, standard de facto pour la gestion de transactions Les proprits ACID Atomicit Nombreux acteurs qui votent pour indiquer si la transaction s'est bien passe ( commit 2 phases ) Consistance Le systme demeure consistant aprs l'excution d'une transaction (comptes bancaires ok!) Isolation Empche les transactions concurrentes de voir des rsultats partiels. Chaque transaction est isole des autres. Implment par des protocoles de synchronisation bas-niveau sur les BDs Durabilit Garantit que les mises jour sur une BD peuvent survivre un crash (BD, machine, rseau) En gnral, on utilise un fichier de log qui permet de revenir dans l'tat avant le crash. Modles de transactions Il existe deux modles 1. Flat transactions ou transactions plat Supportes par les EJBs 2. Nested transactions ou transactions imbriques Non supportes par les EJBs pour le moment Flat transactions Modle le plus simple. Aprs qu'une transaction ait dmarr, on effectue des oprations Si toutes les oprations sont ok, la transaction est valide (commited), sinon elle choue (aborted) En cas de commit, les oprations sont valides (permanent changes) En cas d'abort, les oprations sont annules (rolled back). L'application est galement prvenue Transactions imbriques Cas d'cole : on veut faire un tour du monde 1. Notre application achte un billet de train de Nice Marseille, 2. Puis un billet d'avion de Marseille Londres, 3. Puis un billet d'avion de Londres New-York, 4. L'application s'aperoit qu'il n'y a plus de billet d'avion disponible ce jour-l pour New-York Tout choue et on annule toutes les rservations ! Transactions imbriques Avec un modle de transactions imbrique, une transaction peut inclure une autre transaction, Si on ne trouve pas de vol pour New-York, on essaiera peut-tre de prendre une correspondance par Philadelphie Gestion des transactions avec les EJBs Seul le modle flat est support. Le code que le dveloppeur crit, s'il dcide de grer les transactions par programmation, demeurera d'un trs haut niveau, Simple vote pour un commit ou un abort, Le container fait tout le travail en coulisse 3 manires de grer les transactions 1. Par programmation, 2. De manire dclarative, 3. De manire initie par le client.
Gestion des transactions par programmation Responsable : le dveloppeur de bean Il dcide dans son code du begin, du commit et du abort Ex: le banquier Gestion des transactions dclarative Le bean est automatiquement enrl (enrolled) dans une transaction Le container fait le travail Gestion des transactions dclarative Gnial pour le dveloppeur! Transactions inities par le client
Que choisir ? Par programmation : contrle trs fin possible Dclaratif : super, mais granularit importante, Contrl par le client N'empche pas de grer les transactions dans le bean (par programmation ou de manire dclarative) Ajoute une couche de scurisation en plus, qui permet de dtecter les crashes machine, rseau, etc Transactions et entits Une entit n'accde pas la BD chaque appel de mthode, mais chaque transaction. Si une entit s'excute trop lentement, la cause est peut-tre quune transaction est dmarre pour chaque appel de mthode de lentit, impliquant des accs BD. Solution : inclure plusieurs appels de mthodes de l'entit dans une mme transaction. Se fait en prcisant les attributs de transaction du bean. Transactions et Message-Driven Beans Bean-Managed Transactions La transaction commence et se termine aprs que le message a t reu par le MDB. On indique dans le descripteur de dploiement les aknowledgement modes pour indiquer au container comment accuser rception Container-Managed Transactions La rception du message s'inscrit dans la mme transaction que les appels de mthodes mtier du MDB. En cas de problme, la transaction fait un rollback. Le container envoi accus de rception (message acknowledgement) Pas de transaction Le container accusera rception aprs rception. Quand exactement, ce n'est pas prcis Transactions et Message-Driven Beans Que choisir ? Si on dcide de ne pas laisser le container grer les transactions, on a pas de moyen de conserver le message dans la queue de destination si un problme arrive. On choisit Container-Managed Transaction Pige : si un MDB est expditeur et consommateur du message, le tout intervient dans une mme transaction Impossible de terminer ! Le message expdi n'est pas mis dans la queue de destination de manire dfinitive tant que l'envoi n'est pas commit. Donc le message ne peut tre consomm! Cqfd. Solution : appeler commit() sur l'objet JMS session juste aprs l'envoi. Attributs de transactions gres par le container Pour chaque bean, on prcise des attributs de transaction On peut spcifier des attributs pour le bean entier ou mthode par mthode, On peut prciser les deux Le plus restrictif gagne. Chaque mthode mtier doit tre traite (globalement ou individuellement) Par dfaut : attribut = REQUIRED Gnial pour le dveloppeur! Valeur des attributs de transaction Required Le bean est toujours dans une transaction. Si une transaction pour ce bean existe, alors le bean la rejoint (join), sinon, le container cre une nouvelle transaction. La plupart du temps propos comme valeur par dfaut par les IDEs Attribut de transaction : Required Exemple : passage d'une commande Un session bean utilise deux entits : un bean carte de crdit et bean commande, Lors d'un passage de commande, on envoie la commande, puis on dbite la carte de crdit, Si le bean session a comme attribut de transaction Required, une transaction est cre ds que le passage de commande dmarre, Lors de l'appel au bean Commande, si celui-ci est galement en mode Required, il rejoindra la transaction en cours. Idem lors de l'appel au bean Carte de Crdit, Si un problme se pose, la carte de crdit ne sera pas dbite et la commande ne sera pas passe.
Attribut de transaction : RequiresNew RequiresNew Le bean est toujours dans une nouvelle transaction. Si une transaction existe, elle est suspendue, Lorsque la nouvelle transaction se termine (abort ou commit), l'ancienne transaction est rsume. Utile si on veut respecter les proprits ACID dans l'unit du bean, sans qu'une logique externe intervienne.
Attribut de transaction : Supports Supports Semblable Required sauf que si une transaction n'existe pas, elle n'est pas cre. Si l'excution du bean intervient dans une transaction existante, il la rejoint nanmoins. A viter pour les applications mission-critical ! Dans ce cas, choisir Required. Attribut de transaction : Mandatory Mandatory Une transaction doit exister lorsque le bean est excut. Si ce n'est pas le cas, javax.ejb.TransactionRequiredException est leve et renvoye au client. Si le client est local, c'est javax.ejb.TransactionRequiredLocalException qui est leve Attribut sr, qui oblige le client inscrire sa logique dans une transaction avant d'appeler le bean. Attribut de transaction : NotSupported NotSupported Le Bean ne supporte pas les transactions, Si une transaction existe lors de l'appel du bean, la transaction est suspendue, le bean s'excute, puis la transaction est rsume. Utiliser cet attribut lorsque les proprits ACID ne sont pas importantes Exemple : un bean qui fait des statistiques toutes les dix minutes en parcourant une BD. On tolre que les donnes lues ne soient peut-tre pas jour Gain en performance vident. Attribut de transaction : Never Never Le Bean ne supporte pas les transactions, Une exception javax.rmi.RemoteException ou javax.ejb.EJBException est envoye au client si une transaction existe au moment de l'appel du bean. A utiliser lors du dveloppement d'une logique non transactionnelle. Tous les attributs ne s'appliquent pas tous les beans
Transactions gres par programmation Plus complexes manipuler, mais plus puissantes, Le dveloppeur doit utiliser Java Transaction API (JTA) CORBA Object Transaction Service (OTS) Dans une transaction de nombreux partis sont impliqus : le driver de DB, le bean, le container, Premier effort pour assurer les transactions dans un systme distribu : le service CORBA Object Transaction Service (OTS) OTS = ensemble d'interfaces pour le gestionnaire de transactions, le gestionnaire de ressources, etc Mortel utiliser ! Java Transaction Service (JTS) Sun Microsystems a encapsul OTS en deux API distinctes JTS s'adresse aux vendeurs d'outils capables d'assurer un service de transaction, elle couvre tous les aspects complexes d'OTS, JTA s'adresse au dveloppeur d'application (vous) et simplifie grandement la gestion de transactions en contexte distribu. Java Transaction API (JTA) JTA permet au programmeur de contrler la gestion de transaction dans une logique mtier. Il pourra faire les begin, commit, rollback, etc Il peut utiliser JTA dans des EJB mais aussi dans n'importe quelle application cliente. JTA se compose de deux interfaces distinctes. JTA : deux interfaces Une pour les gestionnaires de ressources X/Open XA (hors sujet pour nous) Une pour le programmeur dsirant contrler les transactions :
javax.transaction.UserTransaction
L'interface javax.transaction.UserTransaction public interface javax.transaction.UserTransaction { public void begin(); public void commit(); public int getStatus(); public void rollback(); public void setRollbackOnly(); public void setTransactionTimeout(int); }
Constantes de la classe javax.transaction.Status Constantes renvoyes par getStatus() public interface javax.transaction.Status { public static final int STATUS_ACTIVE; public static final int STATUS_NO_TRANSACTION; public static final int STATUS_MARKED_ROLLBACK; public static final int STATUS_PREPARING; public static final int STATUS_PREPARED; public static final int STATUS_COMMITTING; public static final int STATUS_COMMITTED; public static final int STATUS_ROLLING_BACK; public static final int STATUS_ROLLEDBACK; public static final int STATUS_UNKNOWN; }
Exemple de transaction gre par programmation
Exemple de transaction gre par programmation (suite)
Transactions inities par le client C'est la dernire des mthodes prsentes au dbut de ce chapitre Il est ncessaire d'obtenir une rfrence sur un objet UserTransaction, fourni par JTA Via JNDI ! Faire attention ce que chaque transaction ne dure pas longtemps !!! Pige classique ! Transactions inities par le client (servlet par ex) try { // Obtenir une transaction par JNDI Context ctx = new InitialContext(); userTran = (javax.transaction.UserTransaction) ctx.lookup("java:comp/UserTransaction"); userTran.begin(); // Operations de la transaction userTran.commit(); } catch (Exception e) { // Traiter les exceptions. // Certaines peuvent provoquer un rollback. }
Niveau d'isolation Le niveau d'isolation limite la faon dont les transactions multiples et entrelaces interfrent les unes sur les autres dans une BD multi-utilisateur. 3 types de violations possibles 1. Lecture impropre (ou brouille), 2. Lecture ne pouvant tre rpte, 3. Lecture fantme. Niveau d'isolation Lecture impropre La transaction T1 modifie une ligne, la transaction T2 lit ensuite cette ligne, Puis T1 effectue une annulation (rollback), T2 a donc vu une ligne qui n'a jamais vraiment exist. Lecture ne pouvant tre rpte T1 extrait une ligne, T2 met jour cette ligne, T1 extrait nouveau la mme ligne, T1 a extrait deux fois la mme ligne et a vu deux valeurs diffrentes. Niveau d'isolation Lecture fantme T1 lit quelques lignes satisfaisant certaines conditions de recherche, T2 insre plusieurs lignes satisfaisant ces mmes conditions de recherche, Si T1 rpte la lecture elle verra des lignes qui n'existaient pas auparavant. Ces lignes sont appeles des lignes fantmes. Niveau d'isolation
Attribut Syntaxe Description Uncommited TRANSACTION_READ_UNCOMMITED Autorise l'ensemble des trois violations Commited TRANSACTION_READ_COMMITED
Autorise les lectures ne pouvant tre rptes et les lignes fantmes, n'autorise pas les lectures brouilles Repeatable TRANSACTION_REPEATABLE_READ Autorise les lignes fantmes mais pas les deux autres violations Serialisable TRANSACTION_SERIALIZABLE N'autorise aucune des trois violations Quel niveau utiliser Uncommited Uniquement si on est sr qu'une transaction ne pourra tre mise en concurrence avec une autre. Performant mais dangereux ! A viter pour les applications mission-critical ! Commited Utile pour les applications qui produisent des rapports sur une base de donne. On veut lire des donnes consistances, mmes si pendant qu'on les lisait quelqu'un tait en train de les modifier. Lisent un snapshot des donnes commites Niveau d'isolation par dfaut de la plupart des BD (Oracle) et aussi le niveau disolation de JPA Quel niveau utiliser Repeatable Lorsqu'on veut pouvoir lire et modifier des lignes, les relire au cours d'une mme transaction, sans perte de consistance. Serialisable Pour les applications mission-critical qui ncessitent un niveau d'isolation absolu, ACID 100% ! Attention ,les performances se dgradent vitesse grand V avec ce mode !
Comment spcifier ces niveaux ? Transactions gres par le bean : appel de Connection.SetTransactionIsolation(...). aprs avoir rcupr la connexion, par exemple par DataSource ds = jndiCtxt.lookup("java:comp/env/jdbc/mabd"); ds.getConnection(); Transactions gres par le container Non, on ne peut pas spcifier le niveau d'isolation dans le descripteur ! On le fera via le driver JDBC, ou via les outils de configuration de la DB ou du container, Problmes de portabilit !
Impossibilit de spcifier le niveau d'isolation ???
Deux stratgies Lorsqu'on veut grer les transactions, on doit toujours choisir entre deux stratgies 1. Stratgie pessimiste On pense quil va y avoir des problmes, on prend donc un verrou lors des accs BD, on fait notre travail, puis on libre le verrou. 2. Stratgie optimiste Espre que tout va bien se passer. Nanmoins, si la BD dtecte une collision, on fait un rollback de la transaction. Que faire dans le code EJB ??? Ok, nous avons vu comment spcifier le type de gestion de transaction, gre par le bean ou le container, Nous avons vu les niveaux d'isolations, que l'on spcifie la plupart du temps via les pilotes JDBC, Mais que faire en cas de rollback par exemple On ne peut pas re-essayer indfiniment d'excuter une transaction, on peut envoyer une Exception au client On veut galement tre tenu au courant de ce qu'il se passe pendant l'excution d'une transaction. Que faire dans le code EJB ??? En cas de rollback, si on envoie une Exception au client, que faire de l'tat du bean ? Si le bean est stateful, on risque d'avoir un tat incorrect (celui qui a provoqu l'chec de la transaction), Lors du design d'un bean, il faut prvoir la possibilit de restaurer un tat correct, Le container ne peut le faire pour vous car le traitement est en gnral spcifique l'application, Il peut nanmoins vous aider raliser cette tche. Que faire dans le code EJB ??? L'EJB peut implementer une interface optionnelle javax.ejb.SessionSynchronization public interface javax.ejb.SessionSynchronization { public void afterBegin(); public void beforeCompletion(); public void afterCompletion(boolean commited); } Uniquement pour les session beans stateful dont les transactions sont gres par le container.
Que faire dans le code EJB ??? Le container appelle afterCompletion() que la transaction se soit termine par un commit ou par un abort Le paramtre de la mthode nous signale dans quel cas on se trouve Que faire dans le code EJB ??? @Stateful public class CountBean implements SessionSynchronization { private int val; private int oldVal; public CountBean(int val) { this.val=val; this.oldVal=val; } public void afterBegin() { oldVal = val;} public void beforeCompletion() {} public void afterCompletion(boolean commited) { if (! commited) val = oldVal; } public int count() { return ++val; } }