Base de données d'objets persistants

Année 2006-2007

Enseignants: G. Blin(), E. Duris, R. Forax

gblin at univ-mlv.fr, duris at univ-mlv.fr, forax at univ-mlv.fr

Présentation générale

Le but de ce projet est de réaliser une base de données objet (pas relationnelle) permettant de stocker des objets Java en binaire. De plus il vous est demandé de developper un petit frontal graphique permettant de visualiser facilement le contenu de la base de données.

Travail demandé

On souhaite pouvoir obtenir la persistance des objets d'une application entre deux lancements successifs. Pour cela les données des objets seront sauvegardées et restaurées entre deux exécutions. De façon plus fine, la base de données devra être capable de gérer la notion de transaction. Une transaction est un contexte associé à un thread dans lequel les objets peuvent être chargés, modifiés puis sauvegardés une fois le contexte terminé (lors d'un commit).
La base de données doit supporter un environnement multi-threadé, de telle sorte que si plusieurs threads effectuent des modifications en concurrence sur un même objet, l'état de ce dernier est forcément dans un état correspondant à une des transactions l'ayant modifié.

Sémantique des transactions

On vous demande de supporter les sémantiques suivantes :

Quelque soit la sémantique, le gestionnaire de la base de données doit garantir que toute transaction s'effectue en totalité ou pas du tout.

Il est possible pour l'utilisateur de mixer les sémantiques, i.e. de demander la création de deux transactions avec des sémantiques différentes. Attention, ce n'est qu'une demande de l'utilisateur. Le gestionnaire de sémantiques peut, le cas échéant, refuser la création d'un transaction avec une sémantique donnée (e.g. si cette dernière n'est pas compatible avec celles des transactions en cours) et proposer alors une sémantique adéquate.
De plus, il est demandé de gérer la création de transactions imbriqués, i.e. une transaction créée dans une autre.

Rollback

Un rollback correspond à ne pas appliquer à la base de donnée l'ensemble des modifications d'une transaction. Il y a deux types de rollback :

  1. rollback explicite : c'est l'utilisateur qui, par l'appel de la méthode rollback sur une transaction donnée, provoque le rollback
  2. rollback implicite : c'est le gestionnaire de la base de données qui, afin de garantir l'intégrité de la base, doit effectuer un rollback sur une transaction donnée. Ce type de rollback peut intervenir à des moments différents en fonction de la sémantique de la transaction (et la sémantique des transactions environnantes).

Tout rollback conduit à la levée d'une exception RollbackException afin de permettre au code utilisateur d'effectuer la reprise sur cette erreur.

Persistence

Nous considérons, dans un premier temps, que les objets que l'on souhaite pouvoir sauvegarder ne sont composés que de champs de types primitifs. Vous pouvez optionnellement gérer les String et les champs de référence vers des objets persistants.

Afin de pouvoir gérer les objets à sauvegarder, le gestionnaire d'objets impose que

  1. Le type de l'objet soit défini par une interface taggée via l'annotation @Persistent. Le gestionnaire ne considère donc pas des objets Java mais plutôt des objets ayant des champs virtuels dont les valeurs sont sauvegardées dans un ou plusieurs fichiers.
  2. L'interface devra contenir uniquement des accesseurs (couples getter/setter) permettant d'accéder aux valeurs des champs de l'objet.
  3. Pour identifier l'objet, un getter particulier de type long devra être annoté par @Id. La valeur retournée par ce getter correspond à un identifiant unique de l'objet (on parle souvant de clé primaire). Il ne devra pas y avoir de setter pour ce getter particulier.

Par exemple, l'interface suivante déclare un type d'objet correspondant à un point en 2 dimensions.
@Persistent public interface Point2D {
  /*
   * Getter and Setter for all fields except id
   */
  public int getX();
  public void setX(int x);
  public int getY();
  public void setY(int y);

  /*
   * Getter for id
   */
  @Id
  public long getId();
}

Opérations

Sur une transaction, il est possible d'effectuer les opérations suivantes :

De plus, sur le gestionnaire de base de données, il est possible de :

Votre implantation devra faire en sorte d'effectuer ces opérations le plus rapidement possible et sans effectuer d'opérations/allocations inutiles.
Rappelons que les opérations de modifications ont un impact sur la base de données uniquement lors d'un commit de la transaction. Tous les objets persistants sont mis-à-jours dans la base de données, insérés en cas d'absence, m-à-j sinon.

Le frontal graphique

Le frontal graphique est une petite application swing permettant d'afficher le contenu de la base de données. Cette application devra :

  1. Etre indépendante d'une implantation d'une base de données i.e. marcher avec l'implantation du voisin.
  2. Permettre de lister l'ensemble des types de la base de données sous forme d'un arbre à gauche de l'application. Un menu contextuel devra permettre la suppression de tous les objets d'un type selectionné.
  3. Permettre de lister l'ensemble des objets pour un type donné (au préalablement choisi dans la partie gauche) dans la partie droite sous forme d'une table dont chaque colonne indique les propriétés d'un objet et chaque ligne correspond à un objet particulier. De plus, il devra être possible de supprimer des objets sélectionnés et de modifier les valeurs d'un objet particulier.

Détail du rendu

Ce projet est à faire en binôme (cela veut dire deux personnes pas trois ni une), un seul groupe de 3 personnes est admis. Le rendu s'effectuera par mail sous forme d'une pièce jointe au format ZIP contenant l'ensemble des programmes et documents. Le mail devra être envoyé avant minuit aux trois adresses données au début de ce document. Le fichier s'appellera nom1_nom2.zip - nom1 et nom2 étant les noms respectifs des personnes formant le binôme triés dans l'ordre alphabétique - et devra être envoyé au plus tard le 4 mars à 23h59:59.

Voici les noms des répertoires et fichiers qui doivent être contenus dans l'archive zip.

  1. un fichier readme.txt indiquant comment compiler le programme, comment exécuter le frontal, où se trouve la documentation, etc.
  2. un fichier Ant build.xml permettant de compiler les sources du programme, et de créer le jar javaodb-impl.jar ainsi que le jar exécutable javaodb-ui.jar dans bin.
  3. un répertoire src contenant l'ensemble des sources (.java), en utilisant un ou plusieurs paquetages.
  4. un répertoire test contenant l'ensemble des tests unitaires (.java) au format JUnit 4 (junit.org), en utilisant un ou plusieurs paquetages. Il doit y avoir au moins un test pour chaque stratégie que vous avez implantée.
  5. un répertoire classes contenant l'ensemble des classes (.class) correspondant aux sources et aux tests.
  6. un répertoire lib contenant les jars javaodb-lib.jar, javaodb-impl.jar et javaodb-ui.jar
  7. un répertoire docs contenant deux documents au format PDF :
    1. La documentation utilisateur user.pdf contenant en plus des informations classiques (comment compiler, exécuter, etc.) une description de l'application graphique, et comment l'utiliser.
    2. La documentation développeur dev.pdf contenant :
      • Une diagramme de classe (UML) de chaque paquetage
      • Les stratégies que vous avez utilisées dans votre implantation
        1. pour gérer les différentes sémantiques
        2. pour gérer le mixage des sémantiques
        3. pour gérer les transactions imbriquées
        4. pour gérer les drops des classes si des transactions existent déjà.
        Vous profiterez de la description de chaque stratégie pour fournir une description détaillée de chaque classe que vous avez implantée. Evitez les copier/coller de la javadoc, essayer plutôt de décrire en français les classes par leur responsabilité (ce qu'elles font et comment elles le font) et dans un ordre logique. Pour expliquer les enchaînements d'appels entre les objets, vous utiliserez des diagrammes de séquences (UML).
      • Une liste des bugs connus (s'il y en a) détaillant le scénario permettant de générer un bug ainsi que la raison pour laquelle celui-ci se produit.
    En plus des deux documents, le répertoire docs devra contenir un sous répertoire api contenant la documentation complète du logiciel au format javadoc.