Details
-
Type: Bug
-
Status: Closed
-
Priority: Major
-
Resolution: Cannot Reproduce
-
Affects Version/s: 1.3.1
-
Fix Version/s: 1.4.2
-
Component/s: Converters
-
Labels:None
-
JDK version and platform:Sun 1.6.0_23
Description
We have our own abstract Enum base class implementation for which a custom readResolve method has been implemented that ensures that singleton instances are returned upon deserialization (with our without XStream) that looks like this:
public Object readResolve() throws java.io.ObjectStreamException {
try
catch (NoSuchFieldException ex)
{ return null; }}
Additionally according readObject and writeObject implementations ensure that the name of the Enum field is (de)serialized:
private void readObject(java.io.ObjectInputStream in) throws java.io.IOException {
try
catch (ClassNotFoundException ex)
{ throw new java.io.IOException(ex.getMessage(), ex); }}
Now instead of throwing an Exception in case a value is being read that is not yet available (in case a newer file is being read by an application using an older Enum implementation where the field is not available) we want to initialize such missing Enum values with null - hence null is returned in case the field with the deserialized name cannot be found in readResolve.
XStream does currently not support this because the AbstractReferenceUnmarshaller does not cache null values (line 63):
result = super.convert(parent, type, converter);
if (currentReferenceKey != null && result != null)
What's making things worse is that the AbstractReflectionConverter (line 165) calls readResolve after the Object that has been created by default deserialization has already been cached:
public Object unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context)
{ Object result = instantiateNewInstance(reader, context); // after this call the Object returned by readObject has been cached: result = doUnmarshal(result, reader, context); return serializationMethodInvoker.callReadResolve(result); }So in case multiple references to the Enum singleton are stored in a file the behaviour is as follows:
- Upon first deserialization null is returned (as desired) because readResolve is called
- For all successive references the cached Object deserialized using readObject() is returned
The attached .xml file contains an ArrayList with multiple Objects referencing such a (non-existing) Enum value.
While this may seem like a very specific use case it makes me wonder if missing support for null return values in readResolve implementations is really desired.
Please use latest XStream version. Without a real unit test, all I can say is, that the code in AbstractReferenceUnmarshaller looks different now and null values are cached.