TUTORIELS 
Introduction aux transactions sous J2EE
Les transactions sont un élément de sécurité (cohérence) essentiel pour une base de données. Gros plan sur les attributs des transactions pour les composants EJB.  (30 novembre 2001)
 

Les transactions sous J2EE sont un vaste sujet, nous nous focalisons aujourd'hui uniquement sur la définition des attributs d'une transaction pour les composants EJB (Enterprise Java Beans). L'utilisation des transactions avec ces composants est simplifiée grâce à "l'EJB container". Celui prend en charge l'étendue d'une transaction, le programmeur n'a pas besoin de les spécifier lui-même. Une transaction débute alors lorsqu'une méthode du container est appelée.

Rappel des propriétés d'une transaction

Les transactions partagent toutes 4 principes, résumés par l'acronyme ACID :

- Atomicité : Une transaction est indivisible, elle est soit exécutée complètement soit pas du tout, mais pas à moitié.

- Cohérence : Une transaction assure l'intégrité des données, elle transfère des données d'un état cohérent à un autre. Si la procédure de mise à jour se passe mal, elle restaure les données initiales. La base reste cohérente même en cas de problèmes.

- Isolation : Cette propriété assure que des transactions concurrentes n'interférent pas entre elles. Si plusieurs transactions sont exécutées en même temps, elles se déroulent séquentiellement.

- Durabilité : Stipule que les résultats d'une transaction qui s'est effectuée correctement sont permanents et ne peuvent être affectés par une panne quelconque du système.

Une transaction n'a que deux issues possibles : le succès ("COMMIT"), ou l'échec ("ROLLBACK"), dans ces conditions, pas de compromis ou de situation intermédiaire possible.
Un "COMMIT" signifie que les traitements encadrés par une transaction ont été exécutés et enregistrés dans la base.
A l'inverse un "ROLLBACK" va "dérouler" la transaction et remonter jusqu'à la situation initiale de la base, c'est à dire avant le début de la transaction.

Lorsque plusieurs mises à jour sont nécessaires sur une base et que l'interruption de l'une d'entre elles mettrait en péril la cohérence de la base, une transaction est nécessaire. Ces cas sont très fréquents, l'exemple est classique est celui d'un mouvement de fond bancaire. Vous souhaitez par exemple débiter de l'argent de votre compte courant pour le placer sur un compte "épargne", en pseudo-code cela nous donne :

- Débiter somme sur compte courant
- Créditer somme (la même) sur compte épargne.

Manque de chance, le système informatique tombe en panne entre le débit et le crédit. Une somme a donc été retirée de votre compte courant mais pas créditée sur votre compte épargne, quel était le montant ? Sans mécanisme spécifique de gestion d'une telle erreur, impossible de le savoir.

Début_Transaction
     - Débiter somme sur compte courant
     - Créditer somme (la même) sur compte épargne.

Fin_Transaction

Dans cette situation, avec l'utilisation des transactions, si le même problème survient entre le débit et le crédit, la transaction va échouer et provoquer un ROLLBACK de la base. Le débit sera annulé.

Les transactions se caractérisent également par leur degré "d'isolation". Ce degré mesure la capacité de transactions concurrentes à distinguer les données mises à jour, mais pas encore enregistrées (pas encore de COMMIT donc), par une autre transaction.
Le réglage de ce dégré d'isolation est un compromis entre les performances et la sécurité (cohérence) de la base. Plus ce degré est elevé moins des transactions concurrentes peuvent accéder aux données manipulées par d'autres transactions. Il en résulte une baisse des performances mais le risque pour une transaction de lire une donnée erronée est lui aussi en baisse.

Les attributs d'une transaction

Nous le disions, l'EJB container facilite la vie du programmeur pour la définition de l'étendue d'une transaction. Celles-ci débutent et se terminent en fonction des appels de méthodes. Quelques précisions sont néanmoins nécessaires pour prédir quelle méthode se situe dans quelle transaction.

En effet, si la plate-forme J2EE accepte les transactions distribuées (mises à jour sur différentes bases de données), les transactions imbriquées ne sont pas supportées. Les attributs de transaction permettent de prévoir ces mécanismes.

Considérons que nous avons une méthode contenue dans un Bean, lorsqu'elle est appelée, une transaction débute, mais que se passe t'il si cette méthode appelle une autre méthode située dans un autre Bean ? Cette seconde méthode s'exécute t'elle dans la même transaction que la première méthode ? Cela dépend des attributs liés à la transaction.

Il existe 6 attributs que l'on peut appliquer à une transaction :

- Required
- RequiresNew
- Mandatory
- NotSupported
- Supports
- Never

Un tableau récapitulatif résume les différents comportements possibles :

(schéma tiré de la documentation de Sun, voir liens en fin d'article)

Attribut Client's transaction Business Method Transaction
Required / T2
T1
T1
RequireSNew / T2
T1
T2
Mandatory / Erreur
T1
T1
NotSupported / /
T1
/
Supports / /
T1
T1
Never / /
T1
Erreur

La lecture de ce tableau est simple. Prenons par exemple l'attribut "Required". Si la première méthode de notre exemple est contenue dans une transaction T1, alors la méthode qui est appelée sera inclue dans cette même transaction. Par contre si la première méthode n'est pas inclue dans une transaction, la seconde méthode initiera une nouvelle transaction.
Des erreurs (exceptions) peuvent également se produire. Dans le cas de l'attribut "mandatory", si la méthode de départ n'est pas inclue dans une transaction, alors l'appel à la seconde méthode lance une exception "TransactionRequiredException".

Pour aller plus loin :
- Chez Sun (vous retrouverez entre autres le tableau ci-dessus et le détail de chaque attribut)
- Un article sur JavaWorld, toujours sur la gestion des transactions.

 
[ Arnaud GadalJDNet
 
Accueil | Haut de page