IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Java Discussion :

Serializable et gestion des versions


Sujet :

Java

  1. #1
    Membre confirmé Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Points : 554
    Points
    554
    Par défaut Serializable et gestion des versions
    Bonjour,

    Actuellement dans mon application, j'offre la possibilité de sauvegarder l'état de ses données (objets java assez complexes) grâce à la sérialisation. Cette méthode est très pratique, presque aucune ligne de code à écrire sauf l'écriture du flux sérialisé dans un fichier.

    Seulement, si mon application évolue, et qu'une des classes change, la désérialisation ne fonctionne plus (le serialUID - que je ne défini pas explicitement - ne correspond plus...). C'est logique, c'est le mécanisme de la sérialisation.

    Seulement, comment puis-je faire pour réussir malgré tout à lire ce fichier, même si la classe à changée ? Dois-je implémenter moi même les méthodes readObject et writeObject ? Cela fonctionnera-t-il ? Ou est-ce que je dois implémenter mon propre mécanisme de sérialisation ?

    Merci d'avance pour vos réponses

  2. #2
    Expert éminent sénior
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Points : 23 190
    Points
    23 190
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Claythest Voir le message
    Seulement, si mon application évolue, et qu'une des classes change, la désérialisation ne fonctionne plus (le serialUID - que je ne défini pas explicitement - ne correspond plus...). C'est logique, c'est le mécanisme de la sérialisation.
    L'utilisation d'un serialUID est quasi-obligatoire si tu veux que tes données soit un tant soit peu pérenne... sinon la moindre modification (même anodine) de la classe provoquera un nouvel ID et donc une erreur...

    Citation Envoyé par Claythest Voir le message
    Seulement, comment puis-je faire pour réussir malgré tout à lire ce fichier, même si la classe à changée ? Dois-je implémenter moi même les méthodes readObject et writeObject ? Cela fonctionnera-t-il ? Ou est-ce que je dois implémenter mon propre mécanisme de sérialisation ?
    Il y a plusieurs solutions qui dépendent de ce que tu veux faire précisément, mais dans tous les cas tu devras utiliser le même serialVersionUID afin que la serialisation puisse se faire.


    En précisant un serialVersionUID et en le laissant identique au fil des modifications de ta classe, tu permet la déserialisation entre des version potentiellement différente sans erreur :
    • Si un attribut de classe est supprimé, il sera ignoré lors de la désérialisation d'une instance précédente.
    • Si un attribut de classe est ajouté, il sera initialisé à la valeur par défaut selon son type (null pour les objets, 0 pour les primitifs)


    Cela peut déjà suffire à bien des cas. Éventuellement on pourrait utiliser readResolve() pour initialiser les attributs null :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    	/**
             * Cette méthode est appelée après chaque readObject(),
             * et permet soit de modifier certains champs, soit
             * carrément de renvoyer un autre objet.
             */
    	private Object readResolve() throws ObjectStreamException {
    		// Pour chaque attribut inexistant dans les versions précédentes,
    		// On lui met une valeur par défaut s'il est null 
    		if (this.attr==null) {
    			this.attr = "(default-value)";
    		}
    		return this;
    	}
    Mais cela pourrait poser problème dans le cas où les attributs pourrait être null


    Maintenant si tu veux un comportement plus poussé, tu peux redéfinir writeObject/readObject pour rajouter un numéro ID perso qui te permettra de connaitre la version enregistré, et donc d'initialiser les bon attributs manquants, par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    	private static final int CLASS_ID = 3;
     
    	private void writeObject(java.io.ObjectOutputStream out)
        	throws IOException {
    		// On écrit la liste des attributs de la classe de manière standard
    		out.defaultWriteObject();
    		// Puis on écrit la version de la classe :
    		out.writeInt(CLASS_ID);
    	}
     
    	private void readObject(java.io.ObjectInputStream in)
        	throws IOException, ClassNotFoundException {
    		// On lit les attributs standard qui ont été ecrits :
    		in.defaultReadObject();
    		// Puis on récupère la version de la classe enregistrée :
    		final int classId = in.readInt();
     
    		// Afin d'initialiser les attributs absents :
    		switch(classId) {
    		case 1:	/* Initialisation des champs absent entre la version 1 et 2 */
    			this.attr1 = "(default-value)";
    		case 2: 	/* Initialisation des champs absent entre la version 2 et 3*/
    			this.attr2 = 0;
    		}
    	}
    Tu pourrais également imaginé des versions plus complexe...




    Maintenant tu pourrais également utiliser XMLEncoder/XMLDecoder qui utilise les propriétés des beans et donc les méthodes get/set pour sauvegarder l'état d'un objet.

    Cela permet une gestion bien plus souple (si un attribut est absent, c'est sa valeur par défaut qui est utilisé et non pas null).

    De plus comme cela génère du XML c'est facilement lisible par un humain, et on peut combler le coté verbeux du XML en le compressant à la volé via du ZIP ou GZIP

    a++

  3. #3
    Membre confirmé Avatar de Claythest
    Profil pro
    Inscrit en
    Mai 2003
    Messages
    558
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2003
    Messages : 558
    Points : 554
    Points
    554
    Par défaut
    Sublime !

    Merci beaucoup pour ce petit dossier sur la question

    Pour ma part, la gestion par défaut me satisfait (initialisation à null pour les nouveaux attributs, et ignore les attributs supprimés), et je garde en tête la méthode readResolve qui va m'être très utile, j'en suis sûr

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Gestion des versions d'applications
    Par Yust dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 05/04/2007, 18h52
  2. [Utilisation] Gestion des versions archivées
    Par tatou42 dans le forum CVS
    Réponses: 2
    Dernier message: 14/12/2005, 16h10
  3. [applet] gestion des versions Java
    Par bigVinz dans le forum Applets
    Réponses: 1
    Dernier message: 09/12/2005, 16h06
  4. Gestion des versions d'objets dans les SGBD
    Par bennus dans le forum Décisions SGBD
    Réponses: 3
    Dernier message: 09/05/2005, 13h57
  5. Gestion des versions travail en équipe
    Par yanis97 dans le forum WinDev
    Réponses: 1
    Dernier message: 05/10/2004, 22h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo