Hi Rad,

EXT-Widmer, Rad M wrote:

> Hello List:
> 
> I'm in the process of migrating a project from java 6 to java 7. The
> project had been using XStream 1.3. We had to update that to XStream 1.4.4
> because of java 7. Most things now work. However, we have some old xml
> files written by an unknown version of XStream that can't be deserialized
> now. The problem is with SynchronizedList. Here's the error I get:
> 
> com.thoughtworks.xstream.converters.ConversionException: Cannot
> deserialize object with new readObject()/writeObject() methods ----
> Debugging information ----
> class               : java.util.Collections$SynchronizedList
> required-type       : java.util.Collections$SynchronizedList
> converter-type      :
> com.thoughtworks.xstream.converters.reflection.SerializableConverter
> path                : /java.util.Collections-SynchronizedRandomAccessList
> line number         : 1
> 
> 
> The xml file looks like this:
> 
> <java.util.Collections-SynchronizedRandomAccessList
> resolves-to="java.util.Collections-SynchronizedList">
>   <list>
>       ... the list content
>   </list>
>   <c class="list" reference="../list"/>
>   <mutex class="java.util.Collections-SynchronizedList">
>     <list reference="../../list"/>
>     <c class="list" reference="../../list"/>
>     <mutex class="java.util.Collections-SynchronizedList" reference=".."/>
>   </mutex>
> </java.util.Collections-SynchronizedRandomAccessList>
> 
> Here's the code that creates the XStream instance:
> 
>         XStream xstream = new XStream(new XppDriver(new
>         XStream11XmlFriendlyReplacer())) {
>             @Override
>             protected boolean useXStream11XmlFriendlyMapper() {
>                 return true;
>             }
>         };
> 
> I also tried using XStream11NameCoder instead of the
> XStream11XmlFriendlyReplacer with the same results.
> 
> Any ideas?

The problem is not the new version of XStream, the problem is that this XML 
has been written with an old JDK.

XStream has no specialized converters for collection types that have been 
created with the java.util.Collections.synchronizedXXX methods, simply 
because it is not possible to access the wrapped collection afterwards and 
the implementation details between the different JDK versions and vendors 
differ too much to use reflection in a compatible way.

Therefore such an instance is simply handled by a reflection-based converter 
i.e. in this case it should have been the SerializableConverter. The drawbck 
of this solutions are situations like you're currently facing: Upgrade to a 
new JDK and the internals of such a class change in an incompatible way.

You can try now  to write a custom converter that is able to handle such a 
construct for your use case, something along:

================= %< ===========

 class SynchronizedListConverter extends Converter {
   Mapper mapper;
   public SynchronizedListConverter(Mapper mapper) {
     this.mapper = mapper;
   }
   boolean canConvert(Class type) {
     return 
"java.util.Collections$SynchronizedList".equals(type.getClass.getName());
   }
   public Object unmarshal(HierarchicalStreamReader reader, 
UnmarshallingContext context) {
     reader.moveDown(); // <list>
     Class type = HierarchicalStreams.readClassType(reader, mapper);
     List list = (List)context.convertAnother(null, type);
     reader.moveUp();
     // ignore the rest, it's synchronization clutter
     return Collections.synchronizedList(list);
   }
 }

================= %< ===========

Cheers,
Jörg


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

    http://xircles.codehaus.org/manage_email


Reply via email to