Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Fixed
-
Affects Version/s: None
-
Fix Version/s: 1.2
-
Component/s: None
-
Labels:None
-
JDK version and platform:1.4.0_01 on Windoes 98SE
Description
I'm getting an error when deserializing a Font. These is a brief code that reproduces the error:
XStream xstream =new XStream(new PureJavaReflectionProvider());
xstream.registerConverter(new FontConverter());
Font f = new Font("",Font.ITALIC,12);
//FOR SERIALIZATION
try
catch(Exception e)
{ e.printStackTrace(); }//FOR DESERIALIZATION
try {
ObjectInputStream in = xstream.createObjectInputStream(new FileReader("c:
font.xml"));
Font c = (Font)in.readObject();
System.out.println("Deserialized");
System.out.println(c.toString());
} catch(Exception e) {
e.printStackTrace();
}
This is the StackTrace:
com.thoughtworks.xstream.converters.ConversionException: : unknown attribute name
---- Debugging information ----
cause-exception : com.thoughtworks.xstream.converters.reflection.ObjectAccessException
required-type : java.awt.font.TextAttribute
class : java.awt.Font
message : : unknown attribute name
line number : 5
path : /awt-font/attributes/entry/java.awt.font.TextAttribute
cause-message : : unknown attribute name
-------------------------------
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:45)
at com.thoughtworks.xstream.core.ReferenceByXPathUnmarshaller.convertAnother(ReferenceByXPathUnmarshaller.java:39)
at com.thoughtworks.xstream.converters.collections.AbstractCollectionConverter.readItem(AbstractCollectionConverter.java:82)
at com.thoughtworks.xstream.converters.collections.MapConverter.populateMap(MapConverter.java:68)
at com.thoughtworks.xstream.converters.collections.MapConverter.unmarshal(MapConverter.java:59)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:38)
at com.thoughtworks.xstream.core.ReferenceByXPathUnmarshaller.convertAnother(ReferenceByXPathUnmarshaller.java:39)
at com.thoughtworks.xstream.converters.extended.FontConverter.unmarshal(FontConverter.java:31)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:38)
at com.thoughtworks.xstream.core.ReferenceByXPathUnmarshaller.convertAnother(ReferenceByXPathUnmarshaller.java:39)
at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:99)
at com.thoughtworks.xstream.core.ReferenceByXPathMarshallingStrategy.unmarshal(ReferenceByXPathMarshallingStrategy.java:12)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:549)
at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:528)
at com.thoughtworks.xstream.XStream$2.readFromStream(XStream.java:798)
at com.thoughtworks.xstream.core.util.CustomObjectInputStream.readObjectOverride(CustomObjectInputStream.java:66)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:316)
at SerialXStream2.main(SerialXStream2.java:74)
Caused by: com.thoughtworks.xstream.converters.reflection.ObjectAccessException: : unknown attribute name
at com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider.instantiateUsingSerialization(PureJavaReflectionProvider.java:93)
at com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider.newInstance(PureJavaReflectionProvider.java:48)
at com.thoughtworks.xstream.converters.reflection.ReflectionConverter.instantiateNewInstance(ReflectionConverter.java:145)
at com.thoughtworks.xstream.converters.reflection.ReflectionConverter.unmarshal(ReflectionConverter.java:87)
at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:38)
... 17 more
Caused by: java.io.InvalidObjectException: unknown attribute name
at java.awt.font.TextAttribute.readResolve(TextAttribute.java:116)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:324)
at java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:896)
at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1645)
at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1264)
at java.io.ObjectInputStream.readObject(ObjectInputStream.java:322)
at com.thoughtworks.xstream.converters.reflection.PureJavaReflectionProvider.instantiateUsingSerialization(PureJavaReflectionProvider.java:91)
... 21 more
I have found the problem:
Because PureJavaReflectionProvider is being used, XStream is having problems instantiating the java.awt.font.TextAttribute objects that are members of java.awt.Font.
<problem> (if you're interested)
The reason behind this is that this class doesn't have a default constructor, so XStream doesn't know how to directly instantiate this. It gets around this internally by building a stream of bytes that can be deserialized using standard Java Object (de)Serialization into a TextAttribute object, which it then populates as normal. What's happening is the TextAttribute class has some additional code in it (a method called readResolve()) that is automatically called by Java Object (de)Serialization before XStream has had a chance to fully populate the object even though this method relies on the object being fully populated.
</problem>
I can see a number of solutions:
1. Use Sun14ReflectionProvider instead of PureJavaReflectionProvider. I've confirmed that this works ok, however it is not available to all JDKs.
2. If you are not using a JDK that Sun14ReflectionProvider works on, let me know which JDK you are using and I can try to build an equivalent.
3. A special Converter for TextAttribute could be created. This would do some custom code to instantiate the class correctly. However there may be other classes with similar problems.
Which option sounds the most suitable for you?