Alternative converter invocation when previous's call failed

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

Alternative converter invocation when previous's call failed

Kowalski, Pawel

 

Hi,

 

I have plenty of data (joda DateTime objects) serialized with default (ReflectionConverter) now I’d like to simplify serialization and created my own Converter for these  objects.

The issue is I’d like to have possibility to support both versions at the same time as there is no possibility to convert already exiting records.

What I’m trying to do is simply create new converter that will work more or less like following:

 

Try to unmarshall in new version

If failed

                Do something to call another converter (in my case Reflection Converter)???

               

Is there possibility to manage above with existing XStream API? I mean is there any way like throwing some exception to call alternative converter once previous failed, or should I register converters in some specific way?

How to get access to one converter from another? How to reset the reader to point the same element as it was primary called with (once data read multiple times moveDown/moveUp etc. and then  failed)?

Thanks for your help in advance.

 

 

Best regards,

Pawel

 

 

 

Reply | Threaded
Open this post in threaded view
|

Re: Alternative converter invocation when previous's call failed

Jörg Schaible-4
Hi Pawel,

Kowalski, Pawel wrote:

>
> Hi,
>
> I have plenty of data (joda DateTime objects) serialized with default
> (ReflectionConverter) now I'd like to simplify serialization and created
> my own Converter for these  objects. The issue is I'd like to have
> possibility to support both versions at the same time as there is no
> possibility to convert already exiting records. What I'm trying to do is
> simply create new converter that will work more or less like following:
>
> Try to unmarshall in new version
> If failed
>                 Do something to call another converter (in my case
>                 Reflection Converter)???
>
> Is there possibility to manage above with existing XStream API? I mean is
> there any way like throwing some exception to call alternative converter
> once previous failed, or should I register converters in some specific
> way?

No.

> How to get access to one converter from another? How to reset the reader
> to point the same element as it was primary called with (once data read
> multiple times moveDown/moveUp etc. and then  failed)?

Actually this last question is the problem, why it cannot work this way.
XStream is stream-based and relies on the underlaying XML parser. There is
no possibility to reset the individual parsers to a specific mark nor can
you control the input stream because the parsers also use different caching
mechanisms i.e. you never know how many of the read bytes have actually been
processed by the XML parser.

The best option is to use a version attribute in your root element:

========== %< ============
 <root version="2">
[...]
 </root>
========== %< ============

Derive from the converter that will normally handle this element and get the
version in the unmarshal method:

========== %< ============
  public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
    String version = reader.getAttribute("version");
    context.put("version", version == null ? "1" : version);
    return super.unmarshal(reader, context);
  }
========== %< ============

Now you take a similar approach for the Joda-Time types you want to handle.
Simply derive from the converter that handled the type in the last version
(assuming ReflectionConverter for now):

========== %< ============
  class JodaTimeTypeConverter extends ReflectionConverter {
    public JodaTimeTypeConverter(Mapper mapper, ReflectionProvider
reflectionProvider) {
      super(mapper, reflectionProvider);
    }
    boolean canConvert(Class type) {
      return <true for the Joda-Time-Type this converter handles>;
    }
    public void marshal(Object source, HierarchicalStreamWriter writer,
MarshallingContext context) {
      // your implementation for the new representation
    }
    public Object unmarshal(HierarchicalStreamReader reader,
UnmarshallingContext context) {
      String version = content.get("version");
      if ("1".equals(version)) { // old format
        return super.unmarshal(reader, context);
      } else {
        // your implementation for the new representation
      }
    }
}
========== %< ============

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: Alternative converter invocation when previous's call failed

Kowalski, Pawel
Thanks Jörg. It works for me.

Best regards,
Pawel

-----Original Message-----
From: Jörg Schaible [mailto:[hidden email]]
Sent: Monday, February 03, 2014 2:53 PM
To: [hidden email]
Subject: [xstream-user] Re: Alternative converter invocation when previous's call failed

Hi Pawel,

Kowalski, Pawel wrote:

>
> Hi,
>
> I have plenty of data (joda DateTime objects) serialized with default
> (ReflectionConverter) now I'd like to simplify serialization and
> created my own Converter for these  objects. The issue is I'd like to
> have possibility to support both versions at the same time as there is
> no possibility to convert already exiting records. What I'm trying to
> do is simply create new converter that will work more or less like following:
>
> Try to unmarshall in new version
> If failed
>                 Do something to call another converter (in my case
>                 Reflection Converter)???
>
> Is there possibility to manage above with existing XStream API? I mean
> is there any way like throwing some exception to call alternative
> converter once previous failed, or should I register converters in
> some specific way?

No.

> How to get access to one converter from another? How to reset the
> reader to point the same element as it was primary called with (once
> data read multiple times moveDown/moveUp etc. and then  failed)?

Actually this last question is the problem, why it cannot work this way.
XStream is stream-based and relies on the underlaying XML parser. There is no possibility to reset the individual parsers to a specific mark nor can you control the input stream because the parsers also use different caching mechanisms i.e. you never know how many of the read bytes have actually been processed by the XML parser.

The best option is to use a version attribute in your root element:

========== %< ============
 <root version="2">
[...]
 </root>
========== %< ============

Derive from the converter that will normally handle this element and get the version in the unmarshal method:

========== %< ============
  public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
    String version = reader.getAttribute("version");
    context.put("version", version == null ? "1" : version);
    return super.unmarshal(reader, context);
  }
========== %< ============

Now you take a similar approach for the Joda-Time types you want to handle.
Simply derive from the converter that handled the type in the last version (assuming ReflectionConverter for now):

========== %< ============
  class JodaTimeTypeConverter extends ReflectionConverter {
    public JodaTimeTypeConverter(Mapper mapper, ReflectionProvider
reflectionProvider) {
      super(mapper, reflectionProvider);
    }
    boolean canConvert(Class type) {
      return <true for the Joda-Time-Type this converter handles>;
    }
    public void marshal(Object source, HierarchicalStreamWriter writer, MarshallingContext context) {
      // your implementation for the new representation
    }
    public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
      String version = content.get("version");
      if ("1".equals(version)) { // old format
        return super.unmarshal(reader, context);
      } else {
        // your implementation for the new representation
      }
    }
}
========== %< ============

Cheers,
Jörg


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

    http://xircles.codehaus.org/manage_email