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

Langage Java Discussion :

Sérialiser un attribut marqué transient !


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 79
    Par défaut Sérialiser un attribut marqué transient !
    Salut,

    Il se trouve que j'ai une classe qui doit être sérialisée (dans une application jsf) seulement la classe en question possède des attributs dont le type n'est pas sérialisable, j'entend par la que la sérialisation de cet objet serait vraiment trop lourde car l'objet dépend d'une librairie geoapi et geotools, la serialisation de l'objet entrainerait la sérialisation de toute les dépendances de ce dernier.

    exemple voici la classe :

    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
    26
    public class Layer implements Serializable {
      ...
      private String name;
      private transient Dimension dim;
    
      ...
    
      private void writeObject(ObjectOutputStream out) throws IOException {
            // calling the default serialization.
            out.defaultWriteObject();
        }
    
        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            // calling the default deserialization.
            in.defaultReadObject();
        }
    
        Object writeReplace() throws ObjectStreamException, CloneNotSupportedException {
            ????
        }
    
        Object readResolve() throws ObjectStreamException {
            ???
        }
    }
    comment peut-on réecrire les methodes writeReplace() readResolve() readObject() et writeObject() pour garder la persistance de l'attribut Dimension dim sans utiliser static Dimension dim;.


    voici un exemple de la classe Dimension :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    public class Dimension {
     
     private Style style;
     private GeoFeature feature;
     .....
     
    }
    la classe Dimension ne peut pas être serializable car ça entrainerai la serialisation des classes Style et Geofeature qui ne peuvent pas être modifiés en aucun cas. et on ne veut surtout pas bloquer ces attributs avec transient.


    est-il donc possible d'ecrire dans le flux de données un attribut qui est marqué transient dont le type n'est pas un type simple comme String ou int ...etc c'est à dire qui n'est pas sérializable.

    merci d'avance !

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    alors on va éclaircir tout çà:

    transient ne 'bloque' pas un attribut, il empeche juste sa sérialisation par le processus par défaut (et non pas une sérialisation d'une manière générale).

    Ton problème se situe dans les attribut à l'intérieur de Dimension, c'est donc, si possible, là qu'il faut régler le problème. J'admer c'est peut etre pas possible (Dimension n'est peut etre pas censé gérer la notion de sérialisation), je vais donc partir de ton cas où tu ne touche pas Dimension.



    Tu n'as pas besoin des deux méthode de remplacement (writeReplace, readResolve).

    dans writeObject, tu commence par utiliser la sérialisation par défaut qui va sérializer ce qui est non transient (c'est plus simple qu'à la main ^^)
    Ligne suivante de code, tu va écrire dans l'objet outputstream des info à toi qui décrivent dimension en termes simple (des ints, des tableaux de int, des strings etc), c'est à toi de choisir ce que tu a besoin de conserver dans Dimension. Par exemple, tu pourrais écrire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    out.writeFloat(lattitude);
    out.writeFloat(longitude);
    out.writeFloat(rayon);
    out.writefloat(altitude);
    J'oversimplifie hein

    Pour la lecture, tu fais la même chose. D'abord tu fais la lecture par défaut (çà va repeupler tes champs non transient), ensuit tu reconstitue toi meme un objet Dimension à partir des infos qui t'as sauvées:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    lattitude=in.readfloat();
    longitude=in.readFloat();
    rayon=in.readFloat();
    altitude=in.readFloat();
    dimension = new Dimension();
    //ajuster dimension en fonction de lattitude,longitude,rayon,altitude

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 79
    Par défaut
    Salut tchize_

    Oui cela va marcher pour un attribut qui dépend des autres, c'est à dire dans ton exemple tu as recréer un objet Dimension à partir des attributs qui eux sont sérialisés lattitude longitude ...Etc, Mais comme t'a pu le voir dans mon exemple qui est simplifié par rapport à mon code afin de refléter aux mieux mes besoins et éclaircir mon problème, mon objet d'exemple : Dimension ne dépend pas des autres attributs qui eux peuvent être sauvés !! de plus il est fortement déconseillé de former une redondance entre attributs de classe.

    Je précise également que le niveau de sérialization de cette exemple correspond au maximum ou je peut décendre pour éviter des Serialized Exception. donc la classe Dimension ne doit pas être modifiée.

    J'ai tentée dans un désespoir fou () de cloner() l'objet Dimension après l'avoir stocker dans un attribut static, la sérialization a marché mais j'ai obtenu le résultat que je craignait, c'est à dire que l'objet en question n'est pas unique pour chaque client (j'entends par la que lors de la manipulation de cette objet par différentes instances de client par exemple ici il s'agit d'une application jsf, les client serait les navigateurs sur différents pc alors ils pointeront tous sur le même objet Dimension à cause de static)

    voici comment j'ai tenter l'expérience :

    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
     
     
    public class Layer implements Serializable, Cloneable {
      private static final long serialVersionUID = 7526471155622776147L;
     
      // l'objet qui va servir de sauvegarde de Dimension.
      static private Layer singleton = null;
     
      private String name;
      private transient Dimension dim;
     
      .. getters et setters
    .
      // le getter du singleton Layer
      static public synchronized Layer getSingleton() {
            if (singleton == null) {
                singleton = new Layer();
            }
            return singleton;
        }
     
     
      private void writeObject(ObjectOutputStream out) throws IOException {
            // calling the default serialization.
            out.defaultWriteObject();
        }
     
        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            // calling the default deserialization.
            in.defaultReadObject();
        }
     
        Object writeReplace() throws ObjectStreamException, CloneNotSupportedException {
    //je récupère l'objet Dimension qui à cet instant n'est pas null. et je le clone pour avoir une instance différente à coup sûr.
            Dimension dim_ = (Dimension) getDimension().clone();
     
    //ici le singleton a pour valeur null à tous ses attributs.
            Layer tmp = (Layer) getSingleton().clone();
     
    //je lui affecte le Dimension courant pour que ce singleton aura seulement un attribut non null qui vaut donc le singleton courant.
            tmp.setDimension(dim_);
     
            Layer l = this;
     
    //je renvoi l'instance courante de Layer car je sérialise Layer
            return l;
        }
     
        Object readResolve() throws ObjectStreamException {
    //je récupère l'instance courante qui à ce momment la tout les attributs sont rempli sauf le Dimension qui est null, cad tous les attributs non transient sont la.
            Layer l = this;
     
    //je récupère le Dimension qui a été affecté au singleton dans le writeReplace()     
            Dimension dim_ = getSingleton().clone().getDimension();
     
    // j'affecte au Layer récupérer le Dimension qui reste à remplir
            l.setDimension(dim_);
     
        reutrn l; //et enfin je renvoi le tout
        }
    }
    avec cette méthode je garde Dimension mais même en clonant les objets je garde une persistance entre les clients de l'objet Dimension dim qui est intolérable dans une application web.

    Donc comment sauvé Dimension sans passer par static ou autre mécanisme de stockage dangereux qui rendrait l'objet Dimension constant.

    j'espère être un peu plus clair cette fois dans mon problème


    Cordialement,

    Mediii

  4. #4
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    je sais pas ce que tu as compris, mais dans l'objectoutputstream, quand tu code ton writeObject et ton readObject tu peux écrire ce que tu veux! pas uniquement des champs de ta classe. Tout ce qu'on te demande c'est de lire et traiter ce que tu écrit. Et non, pour la deuxième fois (faut lire), tu n'as pas besoin des méthode replace.


    Exemple simple pour comprendre

    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
     
    public class MaClasse implements Serializable {
     
        private int monInt;
        private transient MaClassePasSerializable unTruc;
        private void writeObject(ObjectOutputStream out) throws IOException {
            out.defaultWriteObject();
            out.writeInt(unTruc.getA());
            out.writeFloat(unTruc.getB());
        }
     
        private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
            in.defaultReadObject();
            unTruc = new MaClassePasSerializable(in.readInt(),in.readFloat());
        }
     
    }

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Septembre 2007
    Messages
    79
    Détails du profil
    Informations personnelles :
    Âge : 44
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 79
    Par défaut
    biensûr tchize_ on peut écrire n'importe quoi dans writeObject() seulement pour reconstruire une instance de MaClassePasSerializable comment avoir les bonne valeurs pour initialiser l'objet ? je ne vois pas comment puisque mon objet Dimension est en réalité dans mon cas d'application une instance résultante de la déserialisation d'un fichier xml par JAXB.

    en appelant tous les getter() de Dimension ??
    par la reflection ??


    Donc mon problème se situe sur comment reconstruire l'objet Dimension afin de le restaurer!

  6. #6
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    tu peux pas le resérializer par jaxb et tapper la string résultante dans le flux? Bien sur le problème est sa reconstitution, toute la difficulté c'est à toi de déterminer ce qui est relevant et ce qui est possible. oui tu peux jouer avec les getters et ensuite appeler les setters lors de la reconstruction. A toi de voir.

Discussions similaires

  1. Réponses: 2
    Dernier message: 05/02/2015, 18h34
  2. Impossible de sérialiser l'attribut de session
    Par momjunior dans le forum Développement Web en Java
    Réponses: 7
    Dernier message: 18/11/2014, 14h04
  3. Question sérialisation / transient
    Par ®om dans le forum Langage
    Réponses: 6
    Dernier message: 18/11/2006, 14h23
  4. Sérialisation: Quelles différences entre les attributs ?
    Par eldoctor.Sylvain dans le forum Framework .NET
    Réponses: 2
    Dernier message: 18/09/2006, 15h12
  5. Impossible de sérialiser l'attribut de session
    Par dehbi dans le forum Struts 1
    Réponses: 8
    Dernier message: 15/04/2006, 16h17

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