Custom Serializer Issue

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Custom Serializer Issue

Robert Feustel

Hello there,

 

I'm trying to serialize a complex object that I wrote a custom serializer (write/readObject() method) for. Now, when I try running this through xstream it appears that this custom serializer is completely ignored... It's a hierarchical dataset containing multiple instances (in depth as well as width) of custom objects with custom serialization methods...

Is there a way to tell xstream to only use the serialization that java uses... The one I specified?

Thanks,

 

Robert.

Reply | Threaded
Open this post in threaded view
|

Re: Custom Serializer Issue

Jörg Schaible-4
Hi Robert,

Robert Feustel wrote:

> Hello there,
>
> I'm trying to serialize a complex object that I wrote
> a custom serializer (write/readObject() method) for. Now, when I try
> running this through xstream it appears that this custom serializer is
> completely ignored... It's a hierarchical dataset containing multiple
> instances (in depth as well as width) of custom objects with custom
> serialization methods...
>
> Is there a way to tell xstream to only use
> the serialization that java uses... The one I specified?

XStream respects those serializers by default (*), why do you think
otherwise? Marshal such an object to XML and back again and ensure either
with the debugger or System.println() calls that your methods have been
called.

*) Without XStream annotations or further configuration, just by:

==================== %< ====================
 XStream xstream = new XStream();
 String xml = xstream.toXML(yourObject);
 YourType yourObjectAgain = (YourType)xstream.fromXML(xml);
==================== %< ====================

However, you might have influenced this depending on your XStream setup.

Cheers,
Jörg


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

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Custom Serializer Issue

Robert Feustel
Hiho Jörg,

The problem appears to be that xstream is (in contrast to the default
serialization?) automatically trying to serialize parent classes as
well... Even if they aren't serializable (I know that part is not a bug,
but a feature ;))
Can I turn that off somehow? This is what breaks my xstream, because
there are some objects referenced there that cannot be serialized using
a standard ObjectOutputStream. And they shouldn't be in the xml in the
first place, because they are (although not marked) transient. I really
don't want to have to recheck my entire hierarchy for that.

Or should I really implement a serialization method for the parent?
Parent data is stored during serialization, but I just moved that to the
child classes (parent is abstract and most data in it not serialized
anyway)...

Looking forward to hearing from you,

Robert.


Am 12.03.2014 15:19, schrieb Jörg Schaible:

> Hi Robert,
>
> Robert Feustel wrote:
>
>> Hello there,
>>
>> I'm trying to serialize a complex object that I wrote
>> a custom serializer (write/readObject() method) for. Now, when I try
>> running this through xstream it appears that this custom serializer is
>> completely ignored... It's a hierarchical dataset containing multiple
>> instances (in depth as well as width) of custom objects with custom
>> serialization methods...
>>
>> Is there a way to tell xstream to only use
>> the serialization that java uses... The one I specified?
> XStream respects those serializers by default (*), why do you think
> otherwise? Marshal such an object to XML and back again and ensure either
> with the debugger or System.println() calls that your methods have been
> called.
>
> *) Without XStream annotations or further configuration, just by:
>
> ==================== %< ====================
>   XStream xstream = new XStream();
>   String xml = xstream.toXML(yourObject);
>   YourType yourObjectAgain = (YourType)xstream.fromXML(xml);
> ==================== %< ====================
>
> However, you might have influenced this depending on your XStream setup.
>
> Cheers,
> Jörg
>
>
> ---------------------------------------------------------------------
> To unsubscribe from this list, please visit:
>
>      http://xircles.codehaus.org/manage_email
>
>


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

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Re: Custom Serializer Issue

Jörg Schaible-2
Hi Robert,

Robert Feustel wrote:

> Hiho Jörg,
>
> The problem appears to be that xstream is (in contrast to the default
> serialization?) automatically trying to serialize parent classes as
> well... Even if they aren't serializable (I know that part is not a bug,
> but a feature ;))

Actually, it is ... since XStream serializes any type, not just Serializable
ones. And XStream cannot tell, whether the implementation of a Serializable
type actually handles such a case on purpose or the type was never meant to
be serialized with Java serialization and therefore does not handle the
situation.

> Can I turn that off somehow? This is what breaks my xstream, because
> there are some objects referenced there that cannot be serialized using
> a standard ObjectOutputStream. And they shouldn't be in the xml in the
> first place, because they are (although not marked) transient. I really
> don't want to have to recheck my entire hierarchy for that.

It's nothing you can configure, but you can create a customized
SerializationConverter:

================ %< ===========
 class ProperSerializableConverter extends SerializableConverter {
   ProperSerializableConverter(Mapper mapper, ReflectionProvider
reflectionProvider, ClassLoaderReference classLoaderReference) {
     super(mapper, reflectionProvider, classLoaderReference);
   }
   boolean canConvert(Class type) {
     return type == YourType.class;
   }
   protected void marshalUnserializableParent(HierarchicalStreamWriter
writer, MarshallingContext context, Object replacedSource) {
     // do nothing on purpose
   }
 }

 xstream.registerConverter(
   new ProperSerializableConverter(
     xstream.getMapper(),
     xstream.getReflectionProvider(),
     xstream.getClassLoaderReferenfce()));
================ %< ===========

> Or should I really implement a serialization method for the parent?
> Parent data is stored during serialization, but I just moved that to the
> child classes (parent is abstract and most data in it not serialized
> anyway)...
>
> Looking forward to hearing from you,

I did not test the solution above, but it should be working since the whole
unserializable-parent element is simply omitted.

Cheers,
Jörg


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

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Re: Custom Serializer Issue

Robert Feustel
All right,

This pretty much works. Only deserialization doesn't work quite
allright, but I have found the problem and multiple solutions to that.
So, here's what I've done:

class ProperSerializableConverter extends SerializableConverter {
    ProperSerializableConverter(Mapper mapper, ReflectionProvider
reflectionProvider, ClassLoaderReference classLoaderReference) {
      super(mapper, reflectionProvider, classLoaderReference);
    }
    boolean canConvert(Class type) {
      if (type.getPackage() != null && type.getPackage().startswith(yourPackagePath) && type instanceof Serializable)
        return true;
      return false; }
    protected void marshalUnserializableParent(HierarchicalStreamWriter
writer, MarshallingContext context, Object replacedSource) {
      // do nothing on purpose
    }
  }


This will make it work for all my classes easily. However, I have
encountered a little oddity:

abstract class A {

   private LinkedList<String> stringList = new LinkedList<String>();

}

class B extends A implements Serializable {

// some properties and de-/serialization methods

}

Serializing and deserializing an Object of class B through java will
work. Through xstream however the LinkedList in class A will not be
initialized during deserialization. I don't know what java and xstream
do or don't do here. Maybe you can have a look at this. I don't mind
working around it. I already have two ideas I will try on monday,
though. (Do I have to write a deserializer for that?)

However I've encountered another (more important) problem.
If I use my custom serialization, I don't get the property names...
Yeah, I didn't consider that... So now here's a new question: Is it
possible to not use the custom serialization, even if there is one? Or,
is it possible to somehow feed the property names into the process?
Although I wouldn't know how that would be done without breaking java
serialization...

Thank you for all your help,

Robert.

Am 13.03.2014 01:10, schrieb Jörg Schaible:

> Hi Robert,
>
> Actually, it is ... since XStream serializes any type, not just Serializable
> ones. And XStream cannot tell, whether the implementation of a Serializable
> type actually handles such a case on purpose or the type was never meant to
> be serialized with Java serialization and therefore does not handle the
> situation.
>
> It's nothing you can configure, but you can create a customized
> SerializationConverter:
>
> ================ %< ===========
>   class ProperSerializableConverter extends SerializableConverter {
>     ProperSerializableConverter(Mapper mapper, ReflectionProvider
> reflectionProvider, ClassLoaderReference classLoaderReference) {
>       super(mapper, reflectionProvider, classLoaderReference);
>     }
>     boolean canConvert(Class type) {
>       return type == YourType.class;
>     }
>     protected void marshalUnserializableParent(HierarchicalStreamWriter
> writer, MarshallingContext context, Object replacedSource) {
>       // do nothing on purpose
>     }
>   }
>
>   xstream.registerConverter(
>     new ProperSerializableConverter(
>       xstream.getMapper(),
>       xstream.getReflectionProvider(),
>       xstream.getClassLoaderReferenfce()));
> ================ %< ===========
> I did not test the solution above, but it should be working since the whole
> unserializable-parent element is simply omitted.
>
> Cheers,
> Jörg

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

    http://xircles.codehaus.org/manage_email


Reply | Threaded
Open this post in threaded view
|

Re: Re: Re: Custom Serializer Issue

Jörg Schaible-2
Hi Robert,

Robert Feustel wrote:

> All right,
>
> This pretty much works. Only deserialization doesn't work quite
> allright, but I have found the problem and multiple solutions to that.
> So, here's what I've done:
>
> class ProperSerializableConverter extends SerializableConverter {
>     ProperSerializableConverter(Mapper mapper, ReflectionProvider
> reflectionProvider, ClassLoaderReference classLoaderReference) {
>       super(mapper, reflectionProvider, classLoaderReference);
>     }
>     boolean canConvert(Class type) {
>       if (type.getPackage() != null &&
>       type.getPackage().startswith(yourPackagePath) && type instanceof
>       Serializable)
>         return true;
>       return false; }
>     protected void marshalUnserializableParent(HierarchicalStreamWriter
> writer, MarshallingContext context, Object replacedSource) {
>       // do nothing on purpose
>     }
>   }
>
>
> This will make it work for all my classes easily. However, I have
> encountered a little oddity:
>
> abstract class A {
>
>    private LinkedList<String> stringList = new LinkedList<String>();
>
> }
>
> class B extends A implements Serializable {
>
> // some properties and de-/serialization methods
>
> }
>
> Serializing and deserializing an Object of class B through java will
> work. Through xstream however the LinkedList in class A will not be
> initialized during deserialization. I don't know what java and xstream
> do or don't do here. Maybe you can have a look at this. I don't mind
> working around it. I already have two ideas I will try on monday,
> though. (Do I have to write a deserializer for that?)

Normally neither Java (de-)serialization nor XStream unmarshalling will run
class initializers or constructors. Possibly Java deserialization makes an
exception here for this rule for unserializable parents, since it requires
those to have a default constructor. However, there's no official way to run
parent's class initializers or default constructors without actually
constructing an object.

> However I've encountered another (more important) problem.
> If I use my custom serialization, I don't get the property names...
> Yeah, I didn't consider that... So now here's a new question: Is it
> possible to not use the custom serialization, even if there is one? Or,
> is it possible to somehow feed the property names into the process?
> Although I wouldn't know how that would be done without breaking java
> serialization...

?? You mean, you want to define the names of the XML tags used for the
objects written in your writeObject method? Sorry, this is not possible at
all. You write the pure objects, so this is all that XStream gets.

If you have special requirements here for your XML, you will have to write a
complete custom converter(s) for your type(s), have a look at the converter
tutorial. This is not difficult, but you will have to keep the code in the
custom converter and the serialization methods logically in sync on your
own, because those two methods are then no longer relevant for the
marshalling process of XStream.

> Thank you for all your help,

Your welcome.

Cheers,
Jörg



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

    http://xircles.codehaus.org/manage_email