Master 1 d'Informatique - Option MAD (Middleware et Applications aDaptables) - Université Grenoble I - UFR IMA


Aspect-Oriented Programming / AspectJ

Enseignant : Sara Bouchenak, Sara.Bouchenak@imag.fr

Page de l'option MAD : http://sardes.inrialpes.fr/~bouchena/teaching/MAD/


TP 3 : Transactions

  1. Objectif
     
  2. Environnement logiciel
     
  3. Application bancaire persistante
     
  4. Système transactionnel
     
  5. Ajout des transactions à l'application bancaire
     
  6. Mise en oeuvre des transactions avec AspectJ
     
  7. Combinaison des transactions et du traçage
     
  8. Compte-rendu global

1. Objectif

Conception et mise en oeuvre d'un système transactionnel avec AOP/AspectJ.

2. Environnement logiciel

Les logiciels suivants sont nécessaires au TP ; les installer s'ils ne sont pas disponibles dans votre environnement.

Logiciels

En plus des logiciels utilisés dans les TP précédents :

Les logiciels nécessaires au TP sont également disponibles dans ~sbouchen/ENS/MAD/AOP/Soft/

Variables d'environnement

Définir la variable d'environnement suivante :

En plus des variables utilisées dans les TP précédents :

Exemple de fichier de commandes pour Unix/tcsh env-tcsh (soit ajouter ces commandes à votre fichier ~/.cshrc, soit exécuter la commande source env-tcsh).
Exemple de fichier de commandes pour Windows env-win.bat (exécuter la commande env-win.bat).
Ces fichiers sont disponibles dans ~sbouchen/ENS/MAD/AOP/Soft/

3. Application bancaire persistante

Récupérer le TP3 qui se trouve dans ~sbouchen/ENS/MAD/AOP/Project/TP3.tgz

Une application bancaire persistante est donnée dans Project/TP3/Basic :

Configurer la base de données McKoi :

Compiler et exécuter l'application puis naviguer dans son API et son code pour comprendre son fonctionnement :

4. Système transactionnel

Problématique : Incohérence

L'application bancaire propose, entre autres, d'effectuer des transferts d'une certaine somme d'argent entre deux comptes bancaires (voir la méthode banking.InterAccountOperations.transfer). Un transfert est ainsi constitué de deux opérations : une opération de débit sur un compte et une opération de crédit sur un autre compte.

Que se passe-t-il si la première opération s'effectue avec succès et qu'un problème intervient lors de la seconde opération ?
La base de données de l'application bancaire serait dans un état incohérent (une somme d'argent a disparu).

Transactions : Garantie de la cohérence

Pour éviter cette incohérence, les deux opérations constituant un transfert doivent s'effectuer dans une transaction. Une transaction définit une unité atomique qui garantit que le système reste cohérent avant et après l'exécution de la transaction.

De façon générale, une transaction est caractérisée par quatre propriétés ACID : Atomicité, Cohérence, Isolation et Durabilité. L'atomicité garantit que soit toutes les opérations d'une transaction sont effectuées avec succès (transaction validée), soit aucune d'elles n'est effectuée (transaction annulée).
Dans ce TP, nous nous intéresserons plus particulièrement à la propriété d'atomicité.

5. Ajout des transactions à l'application bancaire

Le répertoire Project/TP3/Transactions_HandCoded/ contient une extension "programmée à la main" de l'application bancaire pour la prise en compte des transactions.

Les principales modifications apportées à l'application sont les suivantes :

  1. Désactiver le mode auto-commit afin d'éviter que les opérations ne soient validées individuellement et qu'elles soient plutôt validées à la fin d'une transaction.
    Pour cela, un appel à setAutoCommit(false) a été ajoutée à la fin de la méthode banking.DatabaseImpl.getConnection.
     
  2. Utiliser la même connexion à la base de données pour effectuer les opérations de mise à jour constituant une transaction.
    Pour cela, la connexion utilisée par chaque opération (méthode) d'une transaction est passée comme paramètre supplémentaire à l'opération. Voir les nouvelles versions des méthodes debit, credit, getBalance et setBalance de la classe banking.DatabaseAccountImpl et les nouvelles versions des méthodes query et update de la classe banking.DatabaseImpl.
     
  3. Valider les opérations d'une transaction à la fin de cette transaction si toutes les opérations imbriquées se sont terminées avec succès, sinon annuler la transaction.
    Pour cela, des appels aux méthodes commit et rollback n'ont été ajoutés qu'à la méthode de plus haut niveau dans la transaction et pas aux méthodes imbriquées (méthode banking.InterAccountOperations.transfer et pas les méthodes banking.DatabaseAccountImpl.debit, banking.DatabaseAccountImpl.credit, banking.DatabaseAccountImpl.getBalance, banking.DatabaseAccountImpl.setBalance, banking.DatabaseImpl.query, banking.DatabaseImpl.update).

6. Mise en oeuvre des transactions avec AspectJ

Proposer une mise en oeuvre de l'aspect de transactions en utilisant AspectJ.

Pour ce faire, copier le répertoire Project/TP3/Transactions_Aspects/ et écrire l'aspect demandé dans Project/TP3/Transactions_Aspects/aspects/transaction/TransAspect.java.

Pour la compilation et les tests, penser à utiliser ant compile_aj et ant run_aj.

Quelques directions

  1. Utiliser la même connexion à la base de données (même objet java.sql.Connection) pour effectuer les mises à jour d'une transaction dans la base de données.
    Penser à l'utilisation de percflow qui crée une instance d'aspect par flot de contrôle (thread Java). Ainsi, à chaque flot de contrôle exécutant une transaction, il est possible d'associer une instance d'aspect distincte et donc, un objet java.sql.Connection distinct de ceux utilisés par les flots exécutant les autres transactions.
    La solution préconisée ici est différente de celle proposée dans la version Project/TP3/Transactions_HandCoded/ puisqu'ici, la connexion utilisée par une transaction est celle associée au flot de contrôle sous-jacent alors que dans Project/TP3/Transactions_HandCoded/, la connexion utilisée par une transaction est passée en paramètre des opérations constituant cette transaction.
     
  2. Désactiver le mode auto-commit afin d'éviter que les opérations ne soient validées que lors du succès d'une transaction. Pour cela, faire appel à setAutoCommit(false) lors de la création d'une nouvelle connexion.
     
  3. Valider les opérations d'une transaction à la fin de cette transaction si toutes les opérations imbriquées se sont terminées avec succès, sinon annuler la transaction.
    Pour cela, faire appel aux méthodes commit et rollback dans la méthode de plus haut niveau dans une transaction.
    Pour savoir si une méthode imbriquée dans une transaction est de plus haut niveau, penser à l'utilisation de cflowbelow.
    Pour l'appel aux méthodes commit et rollback, voir l'exemple donné dans Project/TP3/Transactions_HandCoded/src/banking/InterAccountOperations.java

7. Combinaison des transactions et du traçage

Combiner l'utilisation de l'aspect de traçage proposé dans le TP2 et de l'aspect de transactions proposé dans ce TP à votre application bancaire.

Pour cela, vous ne devez pas modifier le code de vos aspects ni le code de l'application mais utiliser le compilateur AspectJ avec ces deux aspects et l'application bancaire.

8. Compte-rendu global

Un compte-rendu global sur les TP 2, 3 et 4 est à rendre lors de la séance de démonstration.
Voir ici pour plus d'informations.