Hi Алексеев,

Алексеев Сергей wrote:

>    Hello team. I got some question/problem with XStream.
> 
>    I have a class with custom realization of methods equals/hashCode. Such
> objects contains in HashSet collection. Default XStream behavior: create
> object instance, read attributes, read inner fields, return object and add
> it to collection if needed.
>    The problem: due a specific object graph on some step of
>    deserialization
> object was created, added to collection, and after all other fields was
> loaded. After fields was loaded, result of hashCode was changed, causing
> "damage" to collection (because HashSet uses HashMap inside). That happens
> because xstream got object with null fields from cache by 'refference'
> attribute. This does not looks like a bug, but working behavior is not
> ideal.

Well, your object graph has circular references and at therefore it is 
simply not possible. At some stage, one of the object cannot be initialized 
fully. XStream behaves even here exactly like Java serialization. Let 
ConnectionPin and Pin both implement Serializable and make the serialization 
algorithm exchangeable:

===================== %< ===================
    private static List<?> serializedWithXStream(List<ConnectionPin> inList) 
{
        /* toXML ---------------------------------------- */
        XStream xstream = new XStream();
        xstream.setMode(XStream.ID_REFERENCES);
        xstream.autodetectAnnotations(true);

        String serialization = xstream.toXML(inList);
        System.out.println(serialization);

        /* fromXML ---------------------------------------- */

        System.out.println("\nLoad from xml\n");

        List<?> list = (List<?>)xstream.fromXML(serialization);

        System.out.println();
        return list;
    }

    private static List<?> 
serializedWithJavaSerialization(List<ConnectionPin> inList) {
        try {
            /* to bytes ---------------------------------------- */
            ByteArrayOutputStream outputStream = new 
ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(outputStream);
            oos.writeObject(inList);
            oos.close();

            /* fromXML ---------------------------------------- */

            System.out.println("\nLoad from bytes\n");

            ByteArrayInputStream inputStream = new 
ByteArrayInputStream(outputStream.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(inputStream);

            List<?> list = (List<?>)ois.readObject();

            System.out.println();
            return list;
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        }
    }
===================== %< ===================

If you run your application now calling one time the serialization with 
XStream and one time with Java serialization, you'll see, that you have 
exactly the same problems, because it is simply not possible to have the 
referring and the referred element initialized completely at the same time.

> In my project I fixed it by restoring collection (just recreate it with
> same objects) in readResolve of other object (1 level upward in graph).
>    There are other problem: calling readResolve does not guarantee that
>    all
> fields of 'this' object (including sub objects in fields) was fully
> deserialized at moment of call. That why I cant fix collection  in
> readResolve of object with HashSet or HashMap and should do it in other
> place.
> 
>    There are attach file that nicely describes a situation.

You will have to break the circle for serialization and restore it at 
deserialization time. You may consider readResolve and writeReplace methods 
that actually write/read different replacement objects or play with 
Externalizable or ...

Cheers,
Jörg


---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email


Reply via email to