Christian Danner created XSTR-690:
-------------------------------------

             Summary: Broken deserialization of singleton references using 
custom readResolve method returning null
                 Key: XSTR-690
                 URL: https://jira.codehaus.org/browse/XSTR-690
             Project: XStream
          Issue Type: Bug
          Components: Converters
    Affects Versions: 1.3.1
            Reporter: Christian Danner
            Assignee: Joerg Schaible
         Attachments: corruptSerializationTest.xml

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 {
      Class clazz = getClassWithFields();
      Field f = clazz.getField(_fieldName);
      return f.get(null);
    } 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 {
      _fieldName = (String) in.readObject();
    } 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) {
     values.put(currentReferenceKey, result);
   }

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.

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: 
https://jira.codehaus.org/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

<hr/>
<p>
To unsubscribe from this list please visit:
</p>
<p>
    <a 
href="http://xircles.codehaus.org/manage_email";>http://xircles.codehaus.org/manage_email</a>
</p>

Reply via email to